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.

673 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. group.c
  5. Abstract:
  6. Server side support for Cluster APIs dealing with groups
  7. Author:
  8. John Vert (jvert) 7-Mar-1996
  9. Revision History:
  10. --*/
  11. #include "apip.h"
  12. HGROUP_RPC
  13. s_ApiOpenGroup(
  14. IN handle_t IDL_handle,
  15. IN LPCWSTR lpszGroupName,
  16. OUT error_status_t *Status
  17. )
  18. /*++
  19. Routine Description:
  20. Opens a handle to an existing group object.
  21. Arguments:
  22. IDL_handle - RPC binding handle, not used.
  23. lpszGroupName - Supplies the name of the group to open.
  24. Status - Returns any error that may occur.
  25. Return Value:
  26. A context handle to a group object if successful
  27. NULL otherwise.
  28. --*/
  29. {
  30. PAPI_HANDLE Handle;
  31. HGROUP_RPC Group;
  32. if (ApiState != ApiStateOnline) {
  33. *Status = ERROR_SHARING_PAUSED;
  34. return(NULL);
  35. }
  36. Handle = LocalAlloc(LMEM_FIXED, sizeof(API_HANDLE));
  37. if (Handle == NULL) {
  38. *Status = ERROR_NOT_ENOUGH_MEMORY;
  39. return(NULL);
  40. }
  41. Group = OmReferenceObjectByName(ObjectTypeGroup, lpszGroupName);
  42. if (Group == NULL) {
  43. LocalFree(Handle);
  44. *Status = ERROR_GROUP_NOT_FOUND;
  45. return(NULL);
  46. }
  47. Handle->Type = API_GROUP_HANDLE;
  48. Handle->Flags = 0;
  49. Handle->Group = Group;
  50. InitializeListHead(&Handle->NotifyList);
  51. *Status = ERROR_SUCCESS;
  52. return(Handle);
  53. }
  54. HGROUP_RPC
  55. s_ApiCreateGroup(
  56. IN handle_t IDL_handle,
  57. IN LPCWSTR lpszGroupName,
  58. OUT error_status_t *pStatus
  59. )
  60. /*++
  61. Routine Description:
  62. Creates a new group object.
  63. Arguments:
  64. IDL_handle - RPC binding handle, not used.
  65. lpszGroupName - Supplies the name of the group to create.
  66. Status - Returns any error that may occur.
  67. Return Value:
  68. A context handle to a group object if successful
  69. NULL otherwise.
  70. --*/
  71. {
  72. HGROUP_RPC Group=NULL;
  73. UUID Guid;
  74. DWORD Status = ERROR_SUCCESS;
  75. WCHAR *KeyName=NULL;
  76. PAPI_HANDLE Handle;
  77. DWORD dwDisposition;
  78. HDMKEY hKey = NULL;
  79. if (ApiState != ApiStateOnline) {
  80. *pStatus = ERROR_SHARING_PAUSED;
  81. return(NULL);
  82. }
  83. Handle = LocalAlloc(LMEM_FIXED, sizeof(API_HANDLE));
  84. if (Handle == NULL) {
  85. *pStatus = ERROR_NOT_ENOUGH_MEMORY;
  86. return(NULL);
  87. }
  88. retry:
  89. //
  90. //
  91. // Create a GUID for this group.
  92. //
  93. Status = UuidCreate(&Guid);
  94. if (Status != RPC_S_OK) {
  95. goto error_exit;
  96. }
  97. Status = UuidToString(&Guid, &KeyName);
  98. if (Status != RPC_S_OK) {
  99. goto error_exit;
  100. }
  101. //
  102. // Create this group in the FM. This will also trigger the notification.
  103. //
  104. Group = FmCreateGroup(KeyName, lpszGroupName);
  105. if (Group == NULL) {
  106. Status = GetLastError();
  107. if (Status == ERROR_ALREADY_EXISTS) {
  108. RpcStringFree(&KeyName);
  109. goto retry;
  110. }
  111. }
  112. error_exit:
  113. if (KeyName != NULL) {
  114. RpcStringFree(&KeyName);
  115. }
  116. *pStatus = Status;
  117. if (Status == ERROR_SUCCESS) {
  118. CL_ASSERT(Group != NULL);
  119. Handle->Type = API_GROUP_HANDLE;
  120. Handle->Group = Group;
  121. Handle->Flags = 0;
  122. InitializeListHead(&Handle->NotifyList);
  123. return(Handle);
  124. } else {
  125. LocalFree(Handle);
  126. return(NULL);
  127. }
  128. }
  129. error_status_t
  130. s_ApiDeleteGroup(
  131. IN HGROUP_RPC hGroup
  132. )
  133. /*++
  134. Routine Description:
  135. Deletes a cluster group. The group must contain no resources.
  136. Arguments:
  137. hGroup - Supplies the group to delete.
  138. Return Value:
  139. ERROR_SUCCESS if successful.
  140. Win32 error code otherwise.
  141. --*/
  142. {
  143. DWORD Status;
  144. PFM_GROUP Group;
  145. HDMKEY Key;
  146. API_ASSERT_INIT();
  147. VALIDATE_GROUP_EXISTS(Group, hGroup);
  148. Status = FmDeleteGroup(Group);
  149. if (Status == ERROR_SUCCESS) {
  150. DmDeleteTree(DmGroupsKey,OmObjectId(Group));
  151. }
  152. return(Status);
  153. }
  154. error_status_t
  155. s_ApiCloseGroup(
  156. IN OUT HGROUP_RPC *phGroup
  157. )
  158. /*++
  159. Routine Description:
  160. Closes an open group context handle.
  161. Arguments:
  162. Group - Supplies a pointer to the HGROUP_RPC to be closed.
  163. Returns NULL
  164. Return Value:
  165. None.
  166. --*/
  167. {
  168. PFM_GROUP Group;
  169. PAPI_HANDLE Handle;
  170. API_ASSERT_INIT();
  171. VALIDATE_GROUP(Group, *phGroup);
  172. Handle = (PAPI_HANDLE)*phGroup;
  173. ApipRundownNotify(Handle);
  174. OmDereferenceObject(Group);
  175. LocalFree(Handle);
  176. *phGroup = NULL;
  177. return(ERROR_SUCCESS);
  178. }
  179. VOID
  180. HGROUP_RPC_rundown(
  181. IN HGROUP_RPC Group
  182. )
  183. /*++
  184. Routine Description:
  185. RPC rundown procedure for a HGROUP_RPC. Just closes the handle.
  186. Arguments:
  187. Group - Supplies the HGROUP_RPC that is to be rundown.
  188. Return Value:
  189. None.
  190. --*/
  191. {
  192. API_ASSERT_INIT();
  193. s_ApiCloseGroup(&Group);
  194. }
  195. error_status_t
  196. s_ApiGetGroupState(
  197. IN HGROUP_RPC hGroup,
  198. OUT DWORD *lpState,
  199. OUT LPWSTR *lpNodeName
  200. )
  201. /*++
  202. Routine Description:
  203. Returns the current state of the specified group.
  204. Arguments:
  205. hGroup - Supplies the group whose state is to be returned.
  206. lpState - Returns the current state of the group
  207. lpNodeName - Returns the name of the node where the group is currently online
  208. Return Value:
  209. ERROR_SUCCESS if successful
  210. Win32 error code otherwise
  211. --*/
  212. {
  213. PFM_GROUP Group;
  214. LPWSTR NodeName;
  215. DWORD NameLength;
  216. API_ASSERT_INIT();
  217. VALIDATE_GROUP_EXISTS(Group, hGroup);
  218. NameLength = MAX_COMPUTERNAME_LENGTH+1;
  219. NodeName = MIDL_user_allocate(NameLength*sizeof(WCHAR));
  220. if (NodeName == NULL) {
  221. return(ERROR_NOT_ENOUGH_MEMORY);
  222. }
  223. *lpState = FmGetGroupState( Group,
  224. NodeName,
  225. &NameLength);
  226. if ( *lpState == ClusterGroupStateUnknown ) {
  227. MIDL_user_free(NodeName);
  228. return(GetLastError());
  229. }
  230. *lpNodeName = NodeName;
  231. return( ERROR_SUCCESS );
  232. }
  233. error_status_t
  234. s_ApiSetGroupName(
  235. IN HGROUP_RPC hGroup,
  236. IN LPCWSTR lpszGroupName
  237. )
  238. /*++
  239. Routine Description:
  240. Sets the new friendly name of a group.
  241. Arguments:
  242. hGroup - Supplies the group whose name is to be set.
  243. lpszGroupName - Supplies the new name of hGroup
  244. Return Value:
  245. ERROR_SUCCESS if successful
  246. Win32 error code otherwise
  247. --*/
  248. {
  249. PFM_GROUP Group;
  250. HDMKEY GroupKey;
  251. DWORD Status;
  252. API_ASSERT_INIT();
  253. VALIDATE_GROUP_EXISTS(Group, hGroup);
  254. //
  255. // Tell the FM about the new name. If it is OK with the
  256. // FM, go ahead and update the registry.
  257. //
  258. Status = FmSetGroupName(Group,
  259. lpszGroupName);
  260. if (Status == ERROR_SUCCESS) {
  261. GroupKey = DmOpenKey(DmGroupsKey,
  262. OmObjectId(Group),
  263. KEY_SET_VALUE);
  264. if (GroupKey == NULL) {
  265. return(GetLastError());
  266. }
  267. Status = DmSetValue(GroupKey,
  268. CLUSREG_NAME_GRP_NAME,
  269. REG_SZ,
  270. (CONST BYTE *)lpszGroupName,
  271. (lstrlenW(lpszGroupName)+1)*sizeof(WCHAR));
  272. DmCloseKey(GroupKey);
  273. }
  274. return(Status);
  275. }
  276. error_status_t
  277. s_ApiGetGroupId(
  278. IN HGROUP_RPC hGroup,
  279. OUT LPWSTR *pGuid
  280. )
  281. /*++
  282. Routine Description:
  283. Returns the unique identifier (GUID) for a group.
  284. Arguments:
  285. hGroup - Supplies the group whose identifer is to be returned
  286. pGuid - Returns the unique identifier. This memory must be freed on the
  287. client side.
  288. Return Value:
  289. ERROR_SUCCESS if successful
  290. Win32 error code otherwise.
  291. --*/
  292. {
  293. PFM_GROUP Group;
  294. DWORD IdLen;
  295. LPCWSTR Id;
  296. API_ASSERT_INIT();
  297. VALIDATE_GROUP_EXISTS(Group, hGroup);
  298. Id = OmObjectId(Group);
  299. IdLen = (lstrlenW(Id)+1)*sizeof(WCHAR);
  300. *pGuid = MIDL_user_allocate(IdLen);
  301. if (*pGuid == NULL) {
  302. return(ERROR_NOT_ENOUGH_MEMORY);
  303. }
  304. CopyMemory(*pGuid, Id, IdLen);
  305. return(ERROR_SUCCESS);
  306. }
  307. DWORD
  308. s_ApiOnlineGroup(
  309. IN HGROUP_RPC hGroup
  310. )
  311. /*++
  312. Routine Description:
  313. Brings a group and all its dependencies online
  314. Arguments:
  315. hGroup - Supplies the group to be brought online
  316. Return Value:
  317. ERROR_SUCCESS if successful
  318. Win32 error code otherwise
  319. --*/
  320. {
  321. PFM_GROUP Group;
  322. API_ASSERT_INIT();
  323. VALIDATE_GROUP_EXISTS(Group, hGroup);
  324. return(FmOnlineGroup(Group));
  325. }
  326. DWORD
  327. s_ApiOfflineGroup(
  328. IN HGROUP_RPC hGroup
  329. )
  330. /*++
  331. Routine Description:
  332. Brings a group and all its dependents offline
  333. Arguments:
  334. hGroup - Supplies the group to be brought offline
  335. Return Value:
  336. ERROR_SUCCESS if successful
  337. Win32 error code otherwise
  338. --*/
  339. {
  340. PFM_GROUP Group;
  341. API_ASSERT_INIT();
  342. VALIDATE_GROUP_EXISTS(Group, hGroup);
  343. return(FmOfflineGroup(Group));
  344. }
  345. DWORD
  346. s_ApiMoveGroup(
  347. IN HGROUP_RPC hGroup
  348. )
  349. /*++
  350. Routine Description:
  351. Moves a group and all its dependents to another system.
  352. Arguments:
  353. hGroup - Supplies the group to be moved
  354. Return Value:
  355. ERROR_SUCCESS if successful
  356. Win32 error code otherwise
  357. --*/
  358. {
  359. PFM_GROUP Group;
  360. API_ASSERT_INIT();
  361. VALIDATE_GROUP_EXISTS(Group, hGroup);
  362. return(FmMoveGroup(Group, NULL));
  363. }
  364. DWORD
  365. s_ApiMoveGroupToNode(
  366. IN HGROUP_RPC hGroup,
  367. IN HNODE_RPC hNode
  368. )
  369. /*++
  370. Routine Description:
  371. Moves a group and all its dependents to another system.
  372. Arguments:
  373. hGroup - Supplies the group to be moved
  374. hNode - Supplies the node to move the group to
  375. Return Value:
  376. ERROR_SUCCESS if successful
  377. Win32 error code otherwise
  378. --*/
  379. {
  380. PFM_GROUP Group;
  381. PNM_NODE Node;
  382. API_ASSERT_INIT();
  383. VALIDATE_GROUP_EXISTS(Group, hGroup);
  384. VALIDATE_NODE(Node, hNode);
  385. return(FmMoveGroup(Group, Node));
  386. }
  387. error_status_t
  388. s_ApiSetGroupNodeList(
  389. IN HGROUP_RPC hGroup,
  390. IN UCHAR *lpNodeList,
  391. IN DWORD cbListSize
  392. )
  393. /*++
  394. Routine Description:
  395. Sets the list of preferred nodes for a group.
  396. Arguments:
  397. hGroup - Supplies the group to set the preferred nodes.
  398. lpNodeList - Supplies the list of preferred owners, as a REG_MULTI_SZ.
  399. cbListSize - Supplies the size in bytes of the preferred owners list.
  400. Return Value:
  401. ERROR_SUCCESS if successful
  402. Win32 error code otherwise
  403. --*/
  404. {
  405. PFM_GROUP Group;
  406. HDMKEY GroupKey;
  407. DWORD Status;
  408. LPWSTR lpszTemp = ( LPWSTR ) lpNodeList;
  409. DWORD cchListSize = cbListSize / sizeof ( WCHAR );
  410. API_ASSERT_INIT();
  411. //
  412. // Make sure the node list is formatted as a MULTI_SZ (and if it is empty it should
  413. // have at least a single NULL). Don't rely on clusapi.dll doing this since a hacker may be able to
  414. // bypass clusapi.dll (even though we make that hard with security callback). Also, since
  415. // lpNodeList is declared as a byte buffer in the IDL file, RPC won't help you with
  416. // anything (except make sure cbListSize is allocated.)
  417. //
  418. if ( ( lpNodeList == NULL ) ||
  419. ( cbListSize % sizeof ( WCHAR ) != 0 ) || // User passed in a size not a multiple of WCHAR
  420. ( cchListSize < 1 ) || // List is of zero length
  421. ( lpszTemp[ cchListSize - 1 ] != UNICODE_NULL ) || // Last char is not NULL
  422. ( ( cchListSize > 1 ) && // List has at least 2 elements and last but one is not NULL
  423. ( lpszTemp[ cchListSize - 2 ] != UNICODE_NULL ) ) )
  424. {
  425. return ERROR_INVALID_PARAMETER;
  426. }
  427. VALIDATE_GROUP_EXISTS(Group, hGroup);
  428. //
  429. // Set the registry with the REG_MULTI_SZ. Let the FM pick it up from
  430. // there.
  431. //
  432. GroupKey = DmOpenKey(DmGroupsKey,
  433. OmObjectId(Group),
  434. KEY_SET_VALUE);
  435. if (GroupKey == NULL) {
  436. return(GetLastError());
  437. }
  438. Status = DmSetValue(GroupKey,
  439. CLUSREG_NAME_GRP_PREFERRED_OWNERS,
  440. REG_MULTI_SZ,
  441. (CONST BYTE *)lpNodeList,
  442. cbListSize);
  443. DmCloseKey(GroupKey);
  444. return(Status);
  445. }