Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2592 lines
64 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_CLUSTER_NODE_NOT_READY);
  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. ClRtlLogPrint(LOG_CRITICAL, "[FM] FmsCreateResource: Unable to allocate memory for resource %1!ws!\n",
  630. ResourceName);
  631. return(ERROR_NOT_ENOUGH_MEMORY);
  632. }
  633. //
  634. // Fill in message buffer.
  635. //
  636. gumResource->Resource = NULL;
  637. gumResource->GroupIdLen = groupIdLen;
  638. gumResource->ResourceIdLen = resourceIdLen;
  639. CopyMemory(gumResource->GroupId, GroupId, groupIdLen);
  640. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen,
  641. ResourceId,
  642. resourceIdLen);
  643. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen,
  644. ResourceName,
  645. resourceNameLen);
  646. //
  647. // Send message.
  648. //
  649. status = GumSendUpdate(GumUpdateFailoverManager,
  650. FmUpdateCreateResource,
  651. bufSize,
  652. gumResource);
  653. if ( ( status == ERROR_SUCCESS ) &&
  654. ( gumResource->Resource != NULL ) )
  655. FmpCleanupPossibleNodeList(gumResource->Resource);
  656. LocalFree(gumResource);
  657. } else {
  658. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  659. }
  660. FmpReleaseLocalGroupLock( group );
  661. return(status);
  662. } // FmsCreateResource
  663. error_status_t
  664. s_FmsDeleteResource(
  665. IN handle_t IDL_handle,
  666. IN LPCWSTR ResourceId
  667. )
  668. /*++
  669. Routine Description:
  670. Receives a Delete Resource Request from a remote system and returns
  671. status for that request.
  672. Arguments:
  673. IDL_handle - The binding context - not used.
  674. ResourceId - The Id of the Resource to delete.
  675. Return Value:
  676. ERROR_SUCCESS if successful.
  677. A Win32 error code on error.
  678. Notes:
  679. The Resource lock is acquired to synchronize access to the resource. This
  680. satisfies locking the resource on all nodes in the cluster... so long
  681. as the local node is the owner of the resource.
  682. --*/
  683. {
  684. PFM_RESOURCE resource;
  685. DWORD status;
  686. DWORD resourceLen;
  687. FmpMustBeOnline();
  688. ClRtlLogPrint(LOG_NOISE,
  689. "[FM] FmsDeleteResource: To delete resource '%1!ws!'\n",
  690. ResourceId);
  691. //
  692. // Find the specified resource.
  693. //
  694. resource = OmReferenceObjectById( ObjectTypeResource,
  695. ResourceId );
  696. if ( resource == NULL ) {
  697. ClRtlLogPrint(LOG_NOISE,
  698. "[FM] FmsDeleteResource: Could not find Resource %1!ws!\n",
  699. ResourceId);
  700. return(ERROR_RESOURCE_NOT_FOUND);
  701. }
  702. FmpAcquireLocalResourceLock( resource );
  703. //
  704. // Now delete it on all nodes in the cluster if we are the owner.
  705. //
  706. if ( resource->Group->OwnerNode == NmLocalNode ) {
  707. //
  708. // Check if this is the quorum resource.
  709. //
  710. if ( resource->QuorumResource ) {
  711. status = ERROR_QUORUM_RESOURCE;
  712. goto FnExit;
  713. }
  714. //other core resources cannot be deleted either
  715. if (resource->ExFlags & CLUS_FLAG_CORE)
  716. {
  717. status = ERROR_CORE_RESOURCE;
  718. goto FnExit;
  719. }
  720. //
  721. // Check the state of the resource, before attempting to delete it.
  722. // It must be offline or failed in order to perform the delete.
  723. //
  724. if ((resource->State != ClusterResourceOffline) &&
  725. (resource->State != ClusterResourceFailed)) {
  726. status = ERROR_RESOURCE_ONLINE;
  727. goto FnExit;
  728. }
  729. //
  730. // Check whether this resource provides for any other resources.
  731. // If so, it cannot be deleted.
  732. //
  733. if (!IsListEmpty(&resource->ProvidesFor)) {
  734. status = ERROR_DEPENDENT_RESOURCE_EXISTS;
  735. goto FnExit;
  736. }
  737. if (resource->Group->MovingList)
  738. {
  739. status = ERROR_INVALID_STATE;
  740. goto FnExit;
  741. }
  742. resourceLen = (lstrlenW(ResourceId)+1) * sizeof(WCHAR);
  743. FmpBroadcastDeleteControl(resource);
  744. //
  745. // Send message.
  746. //
  747. status = GumSendUpdateEx(GumUpdateFailoverManager,
  748. FmUpdateDeleteResource,
  749. 1,
  750. resourceLen,
  751. ResourceId);
  752. } else {
  753. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  754. }
  755. FnExit:
  756. FmpReleaseLocalResourceLock( resource );
  757. return(status);
  758. } // FmsDeleteResource
  759. BOOL
  760. FmpEnumMyGroups(
  761. IN OUT PGROUP_ENUM *Enum,
  762. IN LPDWORD Allocated,
  763. IN PFM_GROUP Group,
  764. IN LPCWSTR Id
  765. )
  766. /*++
  767. Routine Description:
  768. Worker callback routine for the enumeration of Groups.
  769. This routine adds the specified Group to the list that is being
  770. generated if it is owned by the local system.
  771. Arguments:
  772. Enum - The Group Enumeration list. Can be an output if a new list is
  773. allocated.
  774. Allocated - The current number of allocated entries in Enum.
  775. Group - The Group object being enumerated.
  776. Id - The Id of the Group object being enumerated.
  777. Returns:
  778. TRUE - to indicate that the enumeration should continue.
  779. --*/
  780. {
  781. PGROUP_ENUM groupEnum;
  782. PGROUP_ENUM newEnum;
  783. DWORD newAllocated;
  784. DWORD index;
  785. LPWSTR newId;
  786. CLUSTER_GROUP_STATE state;
  787. //
  788. // If we don't own the Group, return now.
  789. //
  790. if (Group->OwnerNode != NmLocalNode) {
  791. return(TRUE);
  792. }
  793. groupEnum = *Enum;
  794. if ( groupEnum->EntryCount >= *Allocated ) {
  795. //
  796. // Time to grow the GROUP_ENUM
  797. //
  798. newAllocated = *Allocated + ENUM_GROW_SIZE;
  799. newEnum = MIDL_user_allocate(GROUP_SIZE(newAllocated));
  800. if ( newEnum == NULL ) {
  801. return(FALSE);
  802. }
  803. CopyMemory(newEnum, groupEnum, GROUP_SIZE(*Allocated));
  804. *Allocated = newAllocated;
  805. *Enum = newEnum;
  806. MIDL_user_free(groupEnum);
  807. groupEnum = newEnum;
  808. }
  809. //
  810. // Initialize new entry
  811. //
  812. newId = MIDL_user_allocate((lstrlenW(Id)+1) * sizeof(WCHAR));
  813. if ( newId == NULL ) {
  814. return(FALSE);
  815. }
  816. lstrcpyW(newId, Id);
  817. groupEnum->Entry[groupEnum->EntryCount].Id = newId;
  818. groupEnum->Entry[groupEnum->EntryCount].State = Group->State;
  819. groupEnum->Entry[groupEnum->EntryCount].StateSequence = Group->StateSequence;
  820. ++groupEnum->EntryCount;
  821. return(TRUE);
  822. } // FmpEnumMyGroups
  823. BOOL
  824. FmpEnumResources(
  825. IN OUT PRESOURCE_ENUM *Enum,
  826. IN LPDWORD Allocated,
  827. IN PFM_RESOURCE Resource,
  828. IN LPCWSTR Id
  829. )
  830. /*++
  831. Routine Description:
  832. Worker callback routine for the enumeration of Group resources.
  833. This routine adds the specified resource to the list that is being
  834. generated.
  835. Arguments:
  836. Enum - The resource enumeration list. Can be an output if a new list is
  837. allocated.
  838. Allocated - The current number of allocated entries in Enum.
  839. Resource - The Resource object being enumerated.
  840. Id - The Id of the resource object being enumerated.
  841. Returns:
  842. TRUE - to indicate that the enumeration should continue.
  843. FALSE - to indicate that the enumeration should not continue.
  844. --*/
  845. {
  846. PRESOURCE_ENUM resourceEnum;
  847. PRESOURCE_ENUM newEnum;
  848. DWORD newAllocated;
  849. DWORD index;
  850. LPWSTR newId;
  851. resourceEnum = *Enum;
  852. if ( resourceEnum->EntryCount >= *Allocated ) {
  853. //
  854. // Time to grow the RESOURCE_ENUM
  855. //
  856. newAllocated = *Allocated + ENUM_GROW_SIZE;
  857. newEnum = MIDL_user_allocate(RESOURCE_SIZE(newAllocated));
  858. if ( newEnum == NULL ) {
  859. return(FALSE);
  860. }
  861. CopyMemory(newEnum, resourceEnum, RESOURCE_SIZE(*Allocated));
  862. *Allocated = newAllocated;
  863. *Enum = newEnum;
  864. MIDL_user_free(resourceEnum);
  865. resourceEnum = newEnum;
  866. }
  867. //
  868. // Initialize new entry
  869. //
  870. newId = MIDL_user_allocate((lstrlenW(Id)+1) * sizeof(WCHAR));
  871. if ( newId == NULL ) {
  872. return(FALSE);
  873. }
  874. lstrcpyW(newId, Id);
  875. resourceEnum->Entry[resourceEnum->EntryCount].Id = newId;
  876. resourceEnum->Entry[resourceEnum->EntryCount].State = Resource->State;
  877. resourceEnum->Entry[resourceEnum->EntryCount].StateSequence = Resource->StateSequence;
  878. ++resourceEnum->EntryCount;
  879. return(TRUE);
  880. } // FmpEnumResources
  881. error_status_t
  882. s_FmsResourceControl(
  883. IN handle_t IDL_handle,
  884. IN LPCWSTR ResourceId,
  885. IN DWORD ControlCode,
  886. IN PUCHAR InBuffer,
  887. IN DWORD InBufferSize,
  888. OUT PUCHAR OutBuffer,
  889. IN DWORD OutBufferSize,
  890. OUT LPDWORD BytesReturned,
  891. OUT LPDWORD Required
  892. )
  893. /*++
  894. Routine Description:
  895. This routine passes a resource control request from a remote system.
  896. Arguments:
  897. IDL_handle - the binding context - not used
  898. ResourceId - the Id of the Resource to control
  899. ControlCode - the control code for this request
  900. InBuffer - the input buffer
  901. InBufferSize - the size of the input buffer
  902. OutBuffer - the output buffer
  903. OutBufferSize - the size of the output buffer
  904. ByteReturned - the number of bytes returned in the output buffer
  905. Required - the number of bytes required if OutBuffer is not big enough.
  906. Returns:
  907. ERROR_SUCCESS if successful.
  908. Win32 error code on failure.
  909. --*/
  910. {
  911. PFM_RESOURCE resource;
  912. DWORD status;
  913. DWORD bufSize;
  914. DWORD dataLength;
  915. CLUSPROP_BUFFER_HELPER props;
  916. //
  917. // Find the specified resource.
  918. //
  919. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  920. if ( resource == NULL ) {
  921. ClRtlLogPrint(LOG_NOISE,
  922. "[FM] FmsResourceControl: Could not find Resource %1!ws!\n",
  923. ResourceId);
  924. return(ERROR_RESOURCE_NOT_FOUND);
  925. }
  926. //
  927. // Since lpInBuffer is declared as [unique] in the IDL file, it can be NULL while dwBufferSize
  928. // is non-zero and vice-versa. To avoid confusion in the following code, we make them consistent
  929. // right here.
  930. //
  931. if ( InBuffer == NULL )
  932. {
  933. InBufferSize = 0;
  934. }
  935. else if ( InBufferSize == 0 )
  936. {
  937. InBuffer = NULL;
  938. }
  939. CL_ASSERT( resource->Group != NULL );
  940. status = FmpRmResourceControl( resource,
  941. ControlCode,
  942. InBuffer,
  943. InBufferSize,
  944. OutBuffer,
  945. OutBufferSize,
  946. BytesReturned,
  947. Required
  948. );
  949. OmDereferenceObject(resource);
  950. return(status);
  951. } // FmsResourceControl
  952. error_status_t
  953. s_FmsResourceTypeControl(
  954. IN handle_t IDL_handle,
  955. IN LPCWSTR ResourceTypeName,
  956. IN DWORD ControlCode,
  957. IN PUCHAR InBuffer,
  958. IN DWORD InBufferSize,
  959. OUT PUCHAR OutBuffer,
  960. IN DWORD OutBufferSize,
  961. OUT LPDWORD BytesReturned,
  962. OUT LPDWORD Required
  963. )
  964. /*++
  965. Routine Description:
  966. This routine passes a resource control request from a remote system.
  967. Arguments:
  968. IDL_handle - the binding context - not used
  969. ResourceTypeName - the name of the Resource Type to control
  970. ControlCode - the control code for this request
  971. InBuffer - the input buffer
  972. InBufferSize - the size of the input buffer
  973. OutBuffer - the output buffer
  974. OutBufferSize - the size of the output buffer
  975. ByteReturned - the number of bytes returned in the output buffer
  976. Required - the number of bytes required if OutBuffer is not big enough.
  977. Returns:
  978. ERROR_SUCCESS if successful.
  979. Win32 error code on failure.
  980. --*/
  981. {
  982. PFM_RESOURCE resource;
  983. DWORD status;
  984. //
  985. // Since lpInBuffer is declared as [unique] in the IDL file, it can be NULL while dwBufferSize
  986. // is non-zero and vice-versa. To avoid confusion in the following code, we make them consistent
  987. // right here.
  988. //
  989. if ( InBuffer == NULL )
  990. {
  991. InBufferSize = 0;
  992. }
  993. else if ( InBufferSize == 0 )
  994. {
  995. InBuffer = NULL;
  996. }
  997. status = FmpRmResourceTypeControl( ResourceTypeName,
  998. ControlCode,
  999. InBuffer,
  1000. InBufferSize,
  1001. OutBuffer,
  1002. OutBufferSize,
  1003. BytesReturned,
  1004. Required
  1005. );
  1006. if ((status == ERROR_MOD_NOT_FOUND) || (status == ERROR_PROC_NOT_FOUND))
  1007. {
  1008. FmpRemovePossibleNodeForResType(ResourceTypeName, NmLocalNode);
  1009. }
  1010. #if 0
  1011. if ( ((status == ERROR_SUCCESS) ||
  1012. (status == ERROR_RESOURCE_PROPERTIES_STORED)) &&
  1013. (ControlCode & CLCTL_MODIFY_MASK) ) {
  1014. ClusterEvent( CLUSTER_EVENT_RESTYPE_PROPERTY_CHANGE, XXX );
  1015. }
  1016. #endif
  1017. return(status);
  1018. } // FmsResourceTypeControl
  1019. error_status_t
  1020. s_FmsGroupControl(
  1021. IN handle_t IDL_handle,
  1022. IN LPCWSTR GroupId,
  1023. IN DWORD ControlCode,
  1024. IN PUCHAR InBuffer,
  1025. IN DWORD InBufferSize,
  1026. OUT PUCHAR OutBuffer,
  1027. IN DWORD OutBufferSize,
  1028. OUT LPDWORD BytesReturned,
  1029. OUT LPDWORD Required
  1030. )
  1031. /*++
  1032. Routine Description:
  1033. This routine processes a group control request from a remote system.
  1034. Arguments:
  1035. IDL_handle - the binding context - not used
  1036. GroupId - the Id of the Group to control
  1037. ControlCode - the control code for this request
  1038. InBuffer - the input buffer
  1039. InBufferSize - the size of the input buffer
  1040. OutBuffer - the output buffer
  1041. OutBufferSize - the size of the output buffer
  1042. ByteReturned - the number of bytes returned in the output buffer
  1043. Required - the number of bytes required if OutBuffer is not big enough.
  1044. Returns:
  1045. ERROR_SUCCESS if successful.
  1046. Win32 error code on failure.
  1047. --*/
  1048. {
  1049. PFM_GROUP group;
  1050. DWORD status;
  1051. //
  1052. // Find the specified group
  1053. //
  1054. group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
  1055. if ( group == NULL ) {
  1056. ClRtlLogPrint(LOG_NOISE,
  1057. "[FM] FmsGroupControl: Could not find Group %1!ws!\n",
  1058. GroupId);
  1059. return(ERROR_GROUP_NOT_FOUND);
  1060. }
  1061. //
  1062. // Since lpInBuffer is declared as [unique] in the IDL file, it can be NULL while dwBufferSize
  1063. // is non-zero and vice-versa. To avoid confusion in the following code, we make them consistent
  1064. // right here.
  1065. //
  1066. if ( InBuffer == NULL )
  1067. {
  1068. InBufferSize = 0;
  1069. }
  1070. else if ( InBufferSize == 0 )
  1071. {
  1072. InBuffer = NULL;
  1073. }
  1074. status = FmpGroupControl(group, ControlCode, InBuffer, InBufferSize,
  1075. OutBuffer, OutBufferSize, BytesReturned, Required);
  1076. OmDereferenceObject(group);
  1077. return(status);
  1078. } // FmsGroupControl
  1079. error_status_t
  1080. s_FmsPrepareQuorumResChange(
  1081. IN handle_t IDL_handle,
  1082. IN LPCWSTR ResourceId,
  1083. IN LPCWSTR lpszQuoLogPath,
  1084. IN DWORD dwMaxQuoLogSize
  1085. )
  1086. /*++
  1087. Routine Description:
  1088. Receives a request to prepare a resource to become the quorum resource.
  1089. A resource must be able to support a quorum log file and registry replication
  1090. files.
  1091. Arguments:
  1092. IDL_handle - The binding context - not used.
  1093. ResourceId - The Id of the resource to be made the quorum resource.
  1094. lpszQuoLogPath - The path where the logs must be created.
  1095. dwMaxQuoLogSize - The maximum size of the quorum log file.
  1096. Return Value:
  1097. ERROR_SUCCESS if successful.
  1098. A Win32 error code on error.
  1099. --*/
  1100. {
  1101. PFM_RESOURCE pResource=NULL;
  1102. DWORD Status;
  1103. ClRtlLogPrint(LOG_NOISE,
  1104. "[FM] FmsPrepareQuorumResChange: Entry\r\n");
  1105. // Find the specified resource.
  1106. //
  1107. pResource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  1108. if ( pResource == NULL )
  1109. {
  1110. ClRtlLogPrint(LOG_NOISE,
  1111. "[FM] FmsPrepareQuorumResource: Could not find Resource %1!ws!\n",
  1112. ResourceId);
  1113. Status = ERROR_RESOURCE_NOT_FOUND;
  1114. goto FnExit;
  1115. }
  1116. CL_ASSERT( pResource->Group != NULL );
  1117. if ( pResource->Group->OwnerNode == NmLocalNode )
  1118. Status = FmpPrepareQuorumResChange(pResource, lpszQuoLogPath, dwMaxQuoLogSize);
  1119. else
  1120. Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1121. FnExit:
  1122. if (pResource) OmDereferenceObject( pResource );
  1123. return(Status);
  1124. } // FmsPrepareQuorumResChange
  1125. error_status_t
  1126. s_FmsCompleteQuorumResChange(
  1127. IN handle_t IDL_handle,
  1128. IN LPCWSTR lpszOldQuoResId,
  1129. IN LPCWSTR lpszOldQuoLogPath
  1130. )
  1131. /*++
  1132. Routine Description:
  1133. Receives a request to clean up quorum logging and cluster registry files
  1134. on the old quorum resource.
  1135. Arguments:
  1136. IDL_handle - The binding context - not used.
  1137. lpszOldQuoResId - The Id of the resource to be made the quorum resource.
  1138. lpszQuoLogPath - The path where the logs must be created.
  1139. Return Value:
  1140. ERROR_SUCCESS if successful.
  1141. A Win32 error code on error.
  1142. --*/
  1143. {
  1144. PFM_RESOURCE pResource=NULL;
  1145. DWORD Status;
  1146. ClRtlLogPrint(LOG_NOISE,
  1147. "[FM] FmsCompleteQuorumResChange: Entry\r\n");
  1148. // Find the specified resource.
  1149. //
  1150. pResource = OmReferenceObjectById( ObjectTypeResource, lpszOldQuoResId );
  1151. if ( pResource == NULL )
  1152. {
  1153. ClRtlLogPrint(LOG_NOISE,
  1154. "[FM] FmsCompleteQuorumResource: Could not find Resource %1!ws!\n",
  1155. lpszOldQuoResId);
  1156. Status = ERROR_RESOURCE_NOT_FOUND;
  1157. goto FnExit;
  1158. }
  1159. CL_ASSERT( pResource->Group != NULL );
  1160. if ( pResource->Group->OwnerNode == NmLocalNode )
  1161. Status = FmpCompleteQuorumResChange(lpszOldQuoResId, lpszOldQuoLogPath);
  1162. else
  1163. Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1164. FnExit:
  1165. if (pResource) OmDereferenceObject( pResource );
  1166. return(Status);
  1167. } // FmsCompleteQuorumResChange
  1168. error_status_t
  1169. s_FmsQuoNodeOnlineResource(
  1170. IN handle_t IDL_handle,
  1171. IN LPCWSTR ResourceId,
  1172. IN LPCWSTR NodeId,
  1173. OUT LPDWORD State
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. Receives a RmResourceOnline request from (THE) remote system and returns
  1178. status for that request.
  1179. This system must own the quorum resource.
  1180. This is the first half of the sling shot. We acquire locks
  1181. and then RPC back to the originating node with a request to perform
  1182. the online.
  1183. This request is only valid for non-quorum resources.
  1184. Arguments:
  1185. IDL_handle - The binding context - not used.
  1186. ResourceId - The Id of the Resource to bring online.
  1187. NodeId - The Id of the Node that originated the request.
  1188. State - Returns the new state of the resource.
  1189. Return Value:
  1190. ERROR_SUCCESS if successful.
  1191. A Win32 error code on error.
  1192. --*/
  1193. {
  1194. //not used
  1195. return(ERROR_INVALID_FUNCTION);
  1196. }
  1197. // FmsQuoNodeOnlineResource
  1198. error_status_t
  1199. s_FmsQuoNodeOfflineResource(
  1200. IN handle_t IDL_handle,
  1201. IN LPCWSTR ResourceId,
  1202. IN LPCWSTR NodeId,
  1203. OUT LPDWORD State
  1204. )
  1205. /*++
  1206. Routine Description:
  1207. Receives a Resource Offline Request from (THE) remote system and returns
  1208. status for that request.
  1209. Arguments:
  1210. IDL_handle - The binding context - not used.
  1211. ResourceId - The Id of the Resource to bring offline.
  1212. NodeId - The Id of the Node that originated the request.
  1213. State - Returns the new state of the resource.
  1214. Return Value:
  1215. ERROR_SUCCESS if successful.
  1216. A Win32 error code on error.
  1217. --*/
  1218. {
  1219. //not used
  1220. return(ERROR_INVALID_FUNCTION);
  1221. }// FmsQuoNodeOfflineResource
  1222. error_status_t
  1223. s_FmsRmOnlineResource(
  1224. IN handle_t IDL_handle,
  1225. IN LPCWSTR ResourceId,
  1226. OUT LPDWORD pdwState
  1227. )
  1228. /*++
  1229. Routine Description:
  1230. Receives a RmResourceOnline request from quorum node and returns
  1231. status for that request.
  1232. This system was the originator of the original online request.
  1233. This is the second half of the sling shot. It just does the online
  1234. request.
  1235. This request is only valid for non-quorum resources.
  1236. Arguments:
  1237. IDL_handle - The binding context - not used.
  1238. ResourceId - The Id of the Resource to bring online.
  1239. State - Returns the new state of the resource.
  1240. Return Value:
  1241. ERROR_SUCCESS if successful.
  1242. A Win32 error code on error.
  1243. Notes:
  1244. We can't acquire any locks... but the originating thread has the
  1245. lock held for us.
  1246. --*/
  1247. {
  1248. PFM_RESOURCE resource;
  1249. DWORD status;
  1250. FmpMustBeOnline( );
  1251. ClRtlLogPrint(LOG_NOISE,
  1252. "[FM] s_FmsRmOnlineResource: To bring resource '%1!ws!' online\n",
  1253. ResourceId);
  1254. //
  1255. // Find the specified resource.
  1256. //
  1257. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  1258. if ( resource == NULL ) {
  1259. ClRtlLogPrint(LOG_NOISE,
  1260. "[FM] s_FmsRmOnlineResource: Could not find Resource %1!ws!\n",
  1261. ResourceId);
  1262. return(ERROR_RESOURCE_NOT_FOUND);
  1263. }
  1264. //
  1265. // This must not be done on the quorum resource, and the local system
  1266. // must not own the quorum resource. We'll assume that the quorum
  1267. // resource migrated while we were performng this request.
  1268. //
  1269. CL_ASSERT( gpQuoResource != NULL );
  1270. CL_ASSERT( gpQuoResource->Group != NULL );
  1271. CL_ASSERT( gpQuoResource->Group->OwnerNode != NULL );
  1272. if ( resource->QuorumResource ||
  1273. (gpQuoResource->Group->OwnerNode == NmLocalNode) ) {
  1274. OmDereferenceObject( resource );
  1275. return(ERROR_HOST_NODE_NOT_RESOURCE_OWNER);
  1276. }
  1277. //
  1278. // The local node must own the resource.
  1279. //
  1280. CL_ASSERT( resource->Group != NULL );
  1281. CL_ASSERT( resource->Group->OwnerNode != NULL );
  1282. if ( resource->Group->OwnerNode != NmLocalNode ) {
  1283. OmDereferenceObject( resource );
  1284. return(ERROR_RESOURCE_NOT_AVAILABLE);
  1285. }
  1286. //
  1287. // Just call the function that does the work.
  1288. //
  1289. OmNotifyCb( resource, NOTIFY_RESOURCE_PREONLINE );
  1290. status = RmOnlineResource( resource->Id, pdwState );
  1291. //call the synchronous notifications on the resource
  1292. FmpCallResourceNotifyCb(resource, *pdwState);
  1293. OmDereferenceObject( resource );
  1294. return(status);
  1295. } // FmsRmOnlineResource
  1296. error_status_t
  1297. s_FmsRmOfflineResource(
  1298. IN handle_t IDL_handle,
  1299. IN LPCWSTR ResourceId,
  1300. OUT LPDWORD pdwState
  1301. )
  1302. /*++
  1303. Routine Description:
  1304. Receives a Resource Offline Request from (THE) remote system and returns
  1305. status for that request.
  1306. Arguments:
  1307. IDL_handle - The binding context - not used.
  1308. ResourceId - The Id of the Resource to bring offline.
  1309. State - Returns the new state of the resource.
  1310. Return Value:
  1311. ERROR_SUCCESS if successful.
  1312. A Win32 error code on error.
  1313. Notes:
  1314. We can't acquire any locks... but the originating thread has the
  1315. lock held for us.
  1316. --*/
  1317. {
  1318. PFM_RESOURCE resource;
  1319. DWORD status;
  1320. FmpMustBeOnline( );
  1321. ClRtlLogPrint(LOG_NOISE,
  1322. "[FM] s_FmsRmOfflineResource: To take resource '%1!ws!' offline\n",
  1323. ResourceId);
  1324. //
  1325. // Find the specified resource.
  1326. //
  1327. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  1328. if ( resource == NULL ) {
  1329. ClRtlLogPrint(LOG_NOISE,
  1330. "[FM] s_FmsRmOfflineResource: Could not find Resource %1!ws!\n",
  1331. ResourceId);
  1332. return(ERROR_RESOURCE_NOT_FOUND);
  1333. }
  1334. //
  1335. // This must not be done on the quorum resource, and the local system
  1336. // must not own the quorum resource. We'll assume that the quorum
  1337. // resource migrated while we were performng this request.
  1338. //
  1339. CL_ASSERT( gpQuoResource != NULL );
  1340. CL_ASSERT( gpQuoResource->Group != NULL );
  1341. CL_ASSERT( gpQuoResource->Group->OwnerNode != NULL );
  1342. if ( resource->QuorumResource ||
  1343. (gpQuoResource->Group->OwnerNode == NmLocalNode) ) {
  1344. OmDereferenceObject( resource );
  1345. return(ERROR_HOST_NODE_NOT_RESOURCE_OWNER);
  1346. }
  1347. //
  1348. // The local node must own the resource.
  1349. //
  1350. CL_ASSERT( resource->Group != NULL );
  1351. CL_ASSERT( resource->Group->OwnerNode != NULL );
  1352. if ( resource->Group->OwnerNode != NmLocalNode ) {
  1353. OmDereferenceObject( resource );
  1354. return(ERROR_RESOURCE_NOT_AVAILABLE);
  1355. }
  1356. //
  1357. // Just call the function that does the work.
  1358. //
  1359. OmNotifyCb( resource, NOTIFY_RESOURCE_PREOFFLINE );
  1360. status = RmOfflineResource( resource->Id, pdwState );
  1361. //call the post offline obj synchronous notifications
  1362. FmpCallResourceNotifyCb(resource, *pdwState);
  1363. OmDereferenceObject( resource );
  1364. return(status);
  1365. } // FmsRmOfflineResource
  1366. error_status_t
  1367. s_FmsBackupClusterDatabase(
  1368. IN handle_t IDL_handle,
  1369. IN LPCWSTR ResourceId,
  1370. IN LPCWSTR lpszPathName
  1371. )
  1372. /*++
  1373. Routine Description:
  1374. Receives a request to backup the quorum log file and the checkpoint
  1375. file
  1376. Arguments:
  1377. IDL_handle - The binding context - not used.
  1378. ResourceId - The Id of the quorum resource
  1379. lpszPathName - The directory path name where the files have to be
  1380. backed up. This path must be visible to the node
  1381. on which the quorum resource is online.
  1382. Return Value:
  1383. ERROR_SUCCESS if successful.
  1384. A Win32 error code on error.
  1385. --*/
  1386. {
  1387. PFM_RESOURCE pResource = NULL;
  1388. DWORD Status;
  1389. FmpMustBeOnline( );
  1390. ClRtlLogPrint(LOG_NOISE,
  1391. "[FM] s_FmsBackupClusterDatabase: Entry...\r\n");
  1392. //
  1393. // Chittur Subbaraman (chitturs) - 10/12/1998
  1394. //
  1395. // Find the specified quorum resource
  1396. //
  1397. pResource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  1398. if ( pResource == NULL )
  1399. {
  1400. ClRtlLogPrint(LOG_NOISE,
  1401. "[FM] s_FmsBackupClusterDatabase: Could not find Resource %1!ws!\n",
  1402. ResourceId);
  1403. Status = ERROR_RESOURCE_NOT_FOUND;
  1404. goto FnExit;
  1405. }
  1406. FmpAcquireLocalResourceLock( pResource );
  1407. CL_ASSERT( pResource->Group != NULL );
  1408. //
  1409. // Make sure the local node owns the quorum resource
  1410. //
  1411. if ( pResource->Group->OwnerNode == NmLocalNode )
  1412. {
  1413. Status = FmpBackupClusterDatabase( pResource, lpszPathName );
  1414. }
  1415. else
  1416. {
  1417. Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1418. ClRtlLogPrint(LOG_NOISE,
  1419. "[FM] s_FmsBackupClusterDatabase: This node is not the quorum resource owner...\n"
  1420. );
  1421. }
  1422. FmpReleaseLocalResourceLock( pResource );
  1423. FnExit:
  1424. if ( pResource ) OmDereferenceObject( pResource );
  1425. return( Status );
  1426. } // FmsBackupClusterDatabase
  1427. error_status_t
  1428. s_FmsChangeResourceGroup(
  1429. IN handle_t IDL_handle,
  1430. IN LPCWSTR pszResourceId,
  1431. IN LPCWSTR pszGroupId
  1432. )
  1433. /*++
  1434. Routine Description:
  1435. Receives a Resource change group request from a remote system and returns
  1436. status for that request.
  1437. Arguments:
  1438. IDL_handle - The binding context - not used.
  1439. pszResourceId - The Id of the Resource to change a resource
  1440. pszGroupId - The Id of the Group to change to.
  1441. Return Value:
  1442. ERROR_SUCCESS if successful.
  1443. A Win32 error code on error.
  1444. --*/
  1445. {
  1446. PFM_RESOURCE pResource = NULL;
  1447. PFM_GROUP pNewGroup = NULL;
  1448. DWORD dwStatus;
  1449. PFM_GROUP pOldGroup;
  1450. FmpMustBeOnline( );
  1451. //
  1452. // Find the specified resource.
  1453. //
  1454. pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
  1455. if ( pResource == NULL ) {
  1456. ClRtlLogPrint(LOG_NOISE,
  1457. "[FM] FmsChangeResourceNode: Could not find Resource %1!ws!\n",
  1458. pszResourceId);
  1459. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1460. goto FnExit;
  1461. }
  1462. //
  1463. // Find the specified group.
  1464. //
  1465. pNewGroup = OmReferenceObjectById( ObjectTypeGroup, pszGroupId );
  1466. if ( pNewGroup == NULL ) {
  1467. ClRtlLogPrint(LOG_NOISE,
  1468. "[FM] s_FmsChangeResourceGroupe: Could not find NewGroup %1!ws!\n",
  1469. pszGroupId);
  1470. dwStatus = ERROR_GROUP_NOT_FOUND;
  1471. goto FnExit;
  1472. }
  1473. ClRtlLogPrint(LOG_NOISE,
  1474. "[FM] s_FmChangeResourceGroup : Resource <%1!ws!> NewGroup %2!ws!\n",
  1475. OmObjectId( pResource ),
  1476. OmObjectId( pNewGroup ));
  1477. //
  1478. // Synchronize both the old and the new groups.
  1479. // Lock the lowest by lowest Group Id first - to prevent deadlocks!
  1480. // Note - the order of release is unimportant.
  1481. //
  1482. // strictly, the comparison below cannot be equal!
  1483. //
  1484. if ( lstrcmpiW( OmObjectId( pResource->Group ), OmObjectId( pNewGroup ) ) <= 0 ) {
  1485. FmpAcquireLocalGroupLock( pResource->Group );
  1486. FmpAcquireLocalGroupLock( pNewGroup );
  1487. } else {
  1488. FmpAcquireLocalGroupLock( pNewGroup );
  1489. FmpAcquireLocalGroupLock( pResource->Group );
  1490. }
  1491. //remember the old group for freeing locks
  1492. pOldGroup = pResource->Group;
  1493. //boy if we are not the owner any more
  1494. //shunt the request to the new owner
  1495. if ( pResource->Group->OwnerNode != NmLocalNode )
  1496. {
  1497. // Note: FmcChangeResourceNode must release the resource lock.
  1498. dwStatus = FmcChangeResourceGroup( pResource, pNewGroup );
  1499. goto FnExit;
  1500. }
  1501. else
  1502. {
  1503. dwStatus = FmpChangeResourceGroup( pResource, pNewGroup );
  1504. }
  1505. FmpReleaseLocalGroupLock( pNewGroup );
  1506. FmpReleaseLocalGroupLock( pOldGroup );
  1507. FnExit:
  1508. if ( pResource ) OmDereferenceObject( pResource );
  1509. if ( pNewGroup ) OmDereferenceObject( pNewGroup );
  1510. ClRtlLogPrint(LOG_NOISE,
  1511. "[FM] s_FmsChangeResourceGroup : returned <%1!u!>\r\n",
  1512. dwStatus);
  1513. return( dwStatus );
  1514. } //s_FmsChangeResourceGroup
  1515. error_status_t
  1516. s_FmsDeleteGroupRequest(
  1517. IN handle_t IDL_handle,
  1518. IN LPCWSTR pszGroupId
  1519. )
  1520. /*++
  1521. Routine Description:
  1522. Receives a delete group request from a remote system and returns
  1523. the status for that request.
  1524. Arguments:
  1525. IDL_handle - The binding context - not used.
  1526. pszGroupId - The Id of the group to be deleted.
  1527. Return Value:
  1528. ERROR_SUCCESS if successful.
  1529. A Win32 error code on error.
  1530. --*/
  1531. {
  1532. PFM_GROUP pGroup = NULL;
  1533. DWORD dwStatus = ERROR_SUCCESS;
  1534. FmpMustBeOnline( );
  1535. //
  1536. // Find the specified group.
  1537. //
  1538. pGroup = OmReferenceObjectById( ObjectTypeGroup, pszGroupId );
  1539. if ( pGroup == NULL )
  1540. {
  1541. ClRtlLogPrint(LOG_NOISE,
  1542. "[FM] FmsDeleteGroupRequest: Could not find group %1!ws!\n",
  1543. pszGroupId);
  1544. dwStatus = ERROR_GROUP_NOT_FOUND;
  1545. goto FnExit;
  1546. }
  1547. FmpAcquireLocalGroupLock( pGroup );
  1548. if ( pGroup->OwnerNode == NmLocalNode )
  1549. {
  1550. dwStatus = FmpDeleteGroup( pGroup );
  1551. }
  1552. else
  1553. {
  1554. //
  1555. // FmcDeleteGroup releases the group lock
  1556. //
  1557. dwStatus = FmcDeleteGroupRequest( pGroup );
  1558. goto FnExit;
  1559. }
  1560. FmpReleaseLocalGroupLock( pGroup );
  1561. FnExit:
  1562. if ( pGroup ) OmDereferenceObject( pGroup );
  1563. return( dwStatus );
  1564. } //s_FmsChangeResourceGroup
  1565. error_status_t
  1566. s_FmsAddResourceDependency(
  1567. IN handle_t IDL_handle,
  1568. IN LPCWSTR pszResourceId,
  1569. IN LPCWSTR pszDependsOnId
  1570. )
  1571. /*++
  1572. Routine Description:
  1573. Receives an add resource dependency request from a remote system
  1574. and returns the status for that request.
  1575. Arguments:
  1576. IDL_handle - The binding context - not used.
  1577. pszResourceId - The Id of the resource to add a dependent resource.
  1578. pszDependentResourceId - The Id of the dependent resource.
  1579. Return Value:
  1580. ERROR_SUCCESS if successful.
  1581. A Win32 error code on error.
  1582. --*/
  1583. {
  1584. PFM_RESOURCE pResource = NULL;
  1585. PFM_RESOURCE pDependentResource = NULL;
  1586. DWORD dwStatus = ERROR_SUCCESS;
  1587. DWORD dwResourceLen;
  1588. DWORD dwDependsOnLen;
  1589. //
  1590. // Chittur Subbaraman (chitturs) - 5/16/99
  1591. //
  1592. // Handle add resource dependency RPC calls from non-owner nodes
  1593. //
  1594. FmpMustBeOnline( );
  1595. ClRtlLogPrint(LOG_NOISE,
  1596. "[FM] s_FmsAddResourceDependency: Resource <%1!ws!>, Dependent Resource <%2!ws!>\n",
  1597. pszResourceId,
  1598. pszDependsOnId);
  1599. //
  1600. // Find the specified resources.
  1601. //
  1602. pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
  1603. if ( pResource == NULL )
  1604. {
  1605. ClRtlLogPrint(LOG_NOISE,
  1606. "[FM] s_FmsAddResourceDependency: Could not find resource <%1!ws!>\n",
  1607. pszResourceId);
  1608. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1609. goto FnExit;
  1610. }
  1611. pDependentResource = OmReferenceObjectById( ObjectTypeResource,
  1612. pszDependsOnId );
  1613. if ( pDependentResource == NULL )
  1614. {
  1615. ClRtlLogPrint(LOG_NOISE,
  1616. "[FM] s_FmsAddResourceDependency: Could not find dependent resource <%1!ws!>\n",
  1617. pszDependsOnId);
  1618. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1619. goto FnExit;
  1620. }
  1621. //
  1622. // Acquire the resource lock
  1623. //
  1624. FmpAcquireLocalResourceLock( pResource );
  1625. if ( pResource->Group->OwnerNode != NmLocalNode )
  1626. {
  1627. dwStatus = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1628. goto FnUnlock;
  1629. }
  1630. dwStatus = FmpValAddResourceDependency( pResource, pDependentResource );
  1631. if ( dwStatus != ERROR_SUCCESS )
  1632. {
  1633. goto FnUnlock;
  1634. }
  1635. dwResourceLen = ( lstrlenW( pszResourceId ) + 1 ) * sizeof( WCHAR );
  1636. dwDependsOnLen = ( lstrlenW( pszDependsOnId ) + 1 ) * sizeof( WCHAR );
  1637. dwStatus = GumSendUpdateEx( GumUpdateFailoverManager,
  1638. FmUpdateAddDependency,
  1639. 2,
  1640. dwResourceLen,
  1641. pszResourceId,
  1642. dwDependsOnLen,
  1643. pszDependsOnId );
  1644. if ( dwStatus == ERROR_SUCCESS )
  1645. {
  1646. FmpBroadcastDependencyChange( pResource,
  1647. pszDependsOnId,
  1648. FALSE );
  1649. }
  1650. FnUnlock:
  1651. FmpReleaseLocalResourceLock( pResource );
  1652. FnExit:
  1653. if ( pResource ) OmDereferenceObject( pResource );
  1654. if ( pDependentResource ) OmDereferenceObject( pDependentResource );
  1655. ClRtlLogPrint(LOG_NOISE,
  1656. "[FM] FmsAddResourceDependency Exit: Status = %1!u!\n",
  1657. dwStatus);
  1658. return( dwStatus );
  1659. } // s_FmsAddResourceDependency
  1660. error_status_t
  1661. s_FmsRemoveResourceDependency(
  1662. IN handle_t IDL_handle,
  1663. IN LPCWSTR pszResourceId,
  1664. IN LPCWSTR pszDependsOnId
  1665. )
  1666. /*++
  1667. Routine Description:
  1668. Receives a remove resource dependency request from a remote system
  1669. and returns the status for that request.
  1670. Arguments:
  1671. IDL_handle - The binding context - not used.
  1672. pszResourceId - The Id of the resource to remove a dependent resource from.
  1673. pszDependentResourceId - The Id of the dependent resource.
  1674. Return Value:
  1675. ERROR_SUCCESS if successful.
  1676. A Win32 error code on error.
  1677. --*/
  1678. {
  1679. PFM_RESOURCE pResource = NULL;
  1680. PFM_RESOURCE pDependentResource = NULL;
  1681. DWORD dwStatus = ERROR_SUCCESS;
  1682. DWORD dwResourceLen;
  1683. DWORD dwDependsOnLen;
  1684. //
  1685. // Chittur Subbaraman (chitturs) - 5/16/99
  1686. //
  1687. // Handle remove resource dependency RPC calls from non-owner nodes
  1688. //
  1689. FmpMustBeOnline( );
  1690. ClRtlLogPrint(LOG_NOISE,
  1691. "[FM] s_FmsRemoveResourceDependency: Resource <%1!ws!>, Dependent Resource <%2!ws!>\n",
  1692. pszResourceId,
  1693. pszDependsOnId);
  1694. //
  1695. // Find the specified resources.
  1696. //
  1697. pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
  1698. if ( pResource == NULL )
  1699. {
  1700. ClRtlLogPrint(LOG_NOISE,
  1701. "[FM] s_FmsRemoveResourceDependency: Could not find resource <%1!ws!>\n",
  1702. pszResourceId);
  1703. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1704. goto FnExit;
  1705. }
  1706. pDependentResource = OmReferenceObjectById( ObjectTypeResource,
  1707. pszDependsOnId );
  1708. if ( pDependentResource == NULL )
  1709. {
  1710. ClRtlLogPrint(LOG_NOISE,
  1711. "[FM] s_FmsRemoveResourceDependency: Could not find dependent resource <%1!ws!>\n",
  1712. pszDependsOnId);
  1713. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1714. goto FnExit;
  1715. }
  1716. //
  1717. // Acquire the resource lock
  1718. //
  1719. FmpAcquireLocalResourceLock( pResource );
  1720. dwStatus = FmpValRemoveResourceDependency( pResource, pDependentResource );
  1721. if ( dwStatus != ERROR_SUCCESS )
  1722. {
  1723. ClRtlLogPrint(LOG_NOISE,
  1724. "[FM] s_FmsRemoveResourceDependency: FmpValRemoveResourceDependency returns %1!u!\n",
  1725. dwStatus);
  1726. goto FnUnlock;
  1727. }
  1728. if ( pResource->Group->OwnerNode != NmLocalNode )
  1729. {
  1730. dwStatus = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1731. goto FnUnlock;
  1732. }
  1733. pszResourceId = OmObjectId( pResource );
  1734. dwResourceLen = ( lstrlenW( pszResourceId ) + 1 ) * sizeof( WCHAR );
  1735. pszDependsOnId = OmObjectId( pDependentResource );
  1736. dwDependsOnLen = ( lstrlenW( pszDependsOnId ) + 1 ) * sizeof( WCHAR );
  1737. dwStatus = GumSendUpdateEx( GumUpdateFailoverManager,
  1738. FmUpdateRemoveDependency,
  1739. 2,
  1740. dwResourceLen,
  1741. pszResourceId,
  1742. dwDependsOnLen,
  1743. pszDependsOnId );
  1744. if ( dwStatus == ERROR_SUCCESS )
  1745. {
  1746. FmpBroadcastDependencyChange( pResource,
  1747. pszDependsOnId,
  1748. TRUE );
  1749. }
  1750. FnUnlock:
  1751. FmpReleaseLocalResourceLock( pResource );
  1752. FnExit:
  1753. if ( pResource ) OmDereferenceObject( pResource );
  1754. if ( pDependentResource ) OmDereferenceObject( pDependentResource );
  1755. ClRtlLogPrint(LOG_NOISE,
  1756. "[FM] FmsRemoveResourceDependency Exit: Status = %1!u!\n",
  1757. dwStatus);
  1758. return( dwStatus );
  1759. } // s_FmsRemoveResourceDependency
  1760. error_status_t
  1761. s_FmsCreateResource2(
  1762. IN handle_t IDL_handle,
  1763. IN LPCWSTR GroupId,
  1764. IN LPWSTR ResourceId,
  1765. IN LPCWSTR ResourceName,
  1766. IN LPCWSTR ResourceType,
  1767. IN DWORD dwFlags
  1768. )
  1769. /*++
  1770. Routine Description:
  1771. Receives a Create Resource Request from a remote system and returns
  1772. status for that request.
  1773. Arguments:
  1774. IDL_handle - The binding context - not used.
  1775. GroupId - The Id of the Group to create the resource inside.
  1776. ResourceId - The Id of the Resource to create.
  1777. ResourceName - The name of the Resource to create.
  1778. ResourceType - The name of the Resource Type.
  1779. dwFlags - Flags for the resource.
  1780. Return Value:
  1781. ERROR_SUCCESS if successful.
  1782. A Win32 error code on error.
  1783. Notes:
  1784. The Resource lock is acquired to synchronize access to the resource. This
  1785. satisfies locking the resource on all nodes in the cluster... so long
  1786. as the local node is the owner of the resource.
  1787. --*/
  1788. {
  1789. PFM_GROUP group;
  1790. DWORD status;
  1791. PGUM_CREATE_RESOURCE gumResource;
  1792. DWORD groupIdLen;
  1793. DWORD resourceIdLen;
  1794. DWORD resourceNameLen;
  1795. DWORD resourceTypeLen;
  1796. DWORD bufSize;
  1797. HDMKEY resourceKey;
  1798. HDMKEY paramsKey;
  1799. DWORD disposition;
  1800. FmpMustBeOnline();
  1801. ClRtlLogPrint(LOG_NOISE,
  1802. "[FM] FmsCreateResource2: To create resource '%1!ws!'\n",
  1803. ResourceId);
  1804. //
  1805. // Find the specified group.
  1806. //
  1807. group = OmReferenceObjectById( ObjectTypeGroup,
  1808. GroupId );
  1809. if ( group == NULL ) {
  1810. ClRtlLogPrint(LOG_NOISE,
  1811. "[FM] FmsCreateResource2: Could not find Group %1!ws!\n",
  1812. GroupId);
  1813. return(ERROR_GROUP_NOT_FOUND);
  1814. }
  1815. FmpAcquireLocalGroupLock( group );
  1816. //
  1817. // Now delete it on all nodes in the cluster if we are the owner.
  1818. //
  1819. if ( group->OwnerNode == NmLocalNode ) {
  1820. //
  1821. // Allocate a message buffer.
  1822. //
  1823. groupIdLen = (lstrlenW(GroupId)+1) * sizeof(WCHAR);
  1824. resourceIdLen = (lstrlenW(ResourceId)+1) * sizeof(WCHAR);
  1825. resourceNameLen = (lstrlenW(ResourceName)+1) * sizeof(WCHAR);
  1826. resourceTypeLen = (lstrlenW(ResourceType)+1) * sizeof(WCHAR);
  1827. bufSize = sizeof(GUM_CREATE_RESOURCE) - sizeof(WCHAR) +
  1828. groupIdLen + resourceIdLen + resourceNameLen + resourceTypeLen + 2 * sizeof( DWORD );
  1829. gumResource = LocalAlloc(LMEM_FIXED, bufSize);
  1830. if (gumResource == NULL) {
  1831. ClRtlLogPrint(LOG_CRITICAL, "[FM] FmsCreateResource2: Unable to allocate memory for resource %1!ws!\n",
  1832. ResourceName);
  1833. return(ERROR_NOT_ENOUGH_MEMORY);
  1834. }
  1835. //
  1836. // Fill in message buffer.
  1837. //
  1838. gumResource->Resource = NULL;
  1839. gumResource->GroupIdLen = groupIdLen;
  1840. gumResource->ResourceIdLen = resourceIdLen;
  1841. CopyMemory(gumResource->GroupId, GroupId, groupIdLen);
  1842. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen,
  1843. ResourceId,
  1844. resourceIdLen);
  1845. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen,
  1846. ResourceName,
  1847. resourceNameLen);
  1848. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen,
  1849. &resourceTypeLen,
  1850. sizeof( DWORD ) );
  1851. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen + sizeof( DWORD ),
  1852. ResourceType,
  1853. resourceTypeLen );
  1854. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen + sizeof( DWORD ) + resourceTypeLen,
  1855. &dwFlags,
  1856. sizeof( DWORD ) );
  1857. //
  1858. // Send message.
  1859. //
  1860. status = GumSendUpdate(GumUpdateFailoverManager,
  1861. FmUpdateCreateResource,
  1862. bufSize,
  1863. gumResource);
  1864. if ( ( status == ERROR_SUCCESS ) &&
  1865. ( gumResource->Resource != NULL ) )
  1866. {
  1867. //
  1868. // If the GUM call was successful, ensure that the resource DLL initialization stuff is
  1869. // also done so that APIs following the CreateClusterResource API can make assumptions
  1870. // that the resource is fully created. Note that the GUM call above will post a work item
  1871. // for the FM worker thread to initialize a resource but there is no guarantee when the
  1872. // FM worker thread will act on the work item. The following call will make sure we
  1873. // won't return from this API until the initialization is fully done thus not giving any
  1874. // chance for APIs such as ChangeClusterResourceGroup that follow this API to screw things
  1875. // up. For backward compatibility reasons (consider a create call originating from a
  1876. // W2K node), we still keep the work item posting in GUM and it won't do any harm since
  1877. // the FmpInitializeResource call is idempotent.
  1878. //
  1879. FmpClusterWideInitializeResource ( gumResource->Resource );
  1880. FmpCleanupPossibleNodeList(gumResource->Resource);
  1881. }
  1882. if( ( gumResource->Resource == NULL ) && FmpShutdown ) {
  1883. status = ERROR_CLUSTER_NODE_SHUTTING_DOWN;
  1884. }
  1885. LocalFree(gumResource);
  1886. } else {
  1887. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1888. }
  1889. FmpReleaseLocalGroupLock( group );
  1890. return(status);
  1891. } // FmsCreateResource2