685 lines
11 KiB
C
685 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
group.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Server side support for Cluster APIs dealing with groups
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 7-Mar-1996
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include "apip.h"
|
|||
|
|
|||
|
HGROUP_RPC
|
|||
|
s_ApiOpenGroup(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
IN LPCWSTR lpszGroupName,
|
|||
|
OUT error_status_t *Status
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Opens a handle to an existing group object.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
lpszGroupName - Supplies the name of the group to open.
|
|||
|
|
|||
|
Status - Returns any error that may occur.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A context handle to a group object if successful
|
|||
|
|
|||
|
NULL otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAPI_HANDLE Handle;
|
|||
|
HGROUP_RPC Group;
|
|||
|
|
|||
|
if (ApiState != ApiStateOnline) {
|
|||
|
*Status = ERROR_SHARING_PAUSED;
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
Handle = LocalAlloc(LMEM_FIXED, sizeof(API_HANDLE));
|
|||
|
if (Handle == NULL) {
|
|||
|
*Status = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
Group = OmReferenceObjectByName(ObjectTypeGroup, lpszGroupName);
|
|||
|
if (Group == NULL) {
|
|||
|
LocalFree(Handle);
|
|||
|
*Status = ERROR_GROUP_NOT_FOUND;
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
Handle->Type = API_GROUP_HANDLE;
|
|||
|
Handle->Flags = 0;
|
|||
|
Handle->Group = Group;
|
|||
|
InitializeListHead(&Handle->NotifyList);
|
|||
|
*Status = ERROR_SUCCESS;
|
|||
|
return(Handle);
|
|||
|
}
|
|||
|
|
|||
|
HGROUP_RPC
|
|||
|
s_ApiCreateGroup(
|
|||
|
IN handle_t IDL_handle,
|
|||
|
IN LPCWSTR lpszGroupName,
|
|||
|
OUT error_status_t *pStatus
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Creates a new group object.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
lpszGroupName - Supplies the name of the group to create.
|
|||
|
|
|||
|
Status - Returns any error that may occur.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A context handle to a group object if successful
|
|||
|
|
|||
|
NULL otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HGROUP_RPC Group=NULL;
|
|||
|
UUID Guid;
|
|||
|
DWORD Status = ERROR_SUCCESS;
|
|||
|
WCHAR *KeyName=NULL;
|
|||
|
PAPI_HANDLE Handle;
|
|||
|
DWORD dwDisposition;
|
|||
|
HDMKEY hKey = NULL;
|
|||
|
|
|||
|
if (ApiState != ApiStateOnline) {
|
|||
|
*pStatus = ERROR_SHARING_PAUSED;
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
Handle = LocalAlloc(LMEM_FIXED, sizeof(API_HANDLE));
|
|||
|
if (Handle == NULL) {
|
|||
|
*pStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
retry:
|
|||
|
//
|
|||
|
//
|
|||
|
// Create a GUID for this group.
|
|||
|
//
|
|||
|
Status = UuidCreate(&Guid);
|
|||
|
if (Status != RPC_S_OK) {
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
Status = UuidToString(&Guid, &KeyName);
|
|||
|
if (Status != RPC_S_OK) {
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create this group in the FM. This will also trigger the notification.
|
|||
|
//
|
|||
|
Group = FmCreateGroup(KeyName, lpszGroupName);
|
|||
|
|
|||
|
if (Group == NULL) {
|
|||
|
Status = GetLastError();
|
|||
|
if (Status == ERROR_ALREADY_EXISTS) {
|
|||
|
RpcStringFree(&KeyName);
|
|||
|
goto retry;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
error_exit:
|
|||
|
if (KeyName != NULL) {
|
|||
|
RpcStringFree(&KeyName);
|
|||
|
}
|
|||
|
|
|||
|
*pStatus = Status;
|
|||
|
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
CL_ASSERT(Group != NULL);
|
|||
|
Handle->Type = API_GROUP_HANDLE;
|
|||
|
Handle->Group = Group;
|
|||
|
Handle->Flags = 0;
|
|||
|
InitializeListHead(&Handle->NotifyList);
|
|||
|
return(Handle);
|
|||
|
} else {
|
|||
|
LocalFree(Handle);
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiDeleteGroup(
|
|||
|
IN HGROUP_RPC hGroup
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Deletes a cluster group. The group must contain no resources.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group to delete.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful.
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD Status;
|
|||
|
PFM_GROUP Group;
|
|||
|
HDMKEY Key;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
|
|||
|
Status = FmDeleteGroup(Group);
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
DmDeleteTree(DmGroupsKey,OmObjectId(Group));
|
|||
|
}
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiCloseGroup(
|
|||
|
IN OUT HGROUP_RPC *phGroup
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Closes an open group context handle.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Group - Supplies a pointer to the HGROUP_RPC to be closed.
|
|||
|
Returns NULL
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
PAPI_HANDLE Handle;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP(Group, *phGroup);
|
|||
|
|
|||
|
Handle = (PAPI_HANDLE)*phGroup;
|
|||
|
ApipRundownNotify(Handle);
|
|||
|
|
|||
|
OmDereferenceObject(Group);
|
|||
|
|
|||
|
LocalFree(Handle);
|
|||
|
*phGroup = NULL;
|
|||
|
|
|||
|
return(ERROR_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HGROUP_RPC_rundown(
|
|||
|
IN HGROUP_RPC Group
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
RPC rundown procedure for a HGROUP_RPC. Just closes the handle.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Group - Supplies the HGROUP_RPC that is to be rundown.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
s_ApiCloseGroup(&Group);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiGetGroupState(
|
|||
|
IN HGROUP_RPC hGroup,
|
|||
|
OUT DWORD *lpState,
|
|||
|
OUT LPWSTR *lpNodeName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns the current state of the specified group.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group whose state is to be returned.
|
|||
|
|
|||
|
lpState - Returns the current state of the group
|
|||
|
|
|||
|
lpNodeName - Returns the name of the node where the group is currently online
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
LPWSTR NodeName;
|
|||
|
DWORD NameLength;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
NameLength = MAX_COMPUTERNAME_LENGTH+1;
|
|||
|
NodeName = MIDL_user_allocate(NameLength*sizeof(WCHAR));
|
|||
|
if (NodeName == NULL) {
|
|||
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|||
|
}
|
|||
|
*lpState = FmGetGroupState( Group,
|
|||
|
NodeName,
|
|||
|
&NameLength);
|
|||
|
if ( *lpState == ClusterGroupStateUnknown ) {
|
|||
|
MIDL_user_free(NodeName);
|
|||
|
return(GetLastError());
|
|||
|
}
|
|||
|
*lpNodeName = NodeName;
|
|||
|
|
|||
|
return( ERROR_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiSetGroupName(
|
|||
|
IN HGROUP_RPC hGroup,
|
|||
|
IN LPCWSTR lpszGroupName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the new friendly name of a group.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group whose name is to be set.
|
|||
|
|
|||
|
lpszGroupName - Supplies the new name of hGroup
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
HDMKEY GroupKey;
|
|||
|
DWORD Status;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
|
|||
|
//
|
|||
|
// Tell the FM about the new name. If it is OK with the
|
|||
|
// FM, go ahead and update the registry.
|
|||
|
//
|
|||
|
Status = FmSetGroupName(Group,
|
|||
|
lpszGroupName);
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
GroupKey = DmOpenKey(DmGroupsKey,
|
|||
|
OmObjectId(Group),
|
|||
|
KEY_SET_VALUE);
|
|||
|
if (GroupKey == NULL) {
|
|||
|
return(GetLastError());
|
|||
|
}
|
|||
|
|
|||
|
Status = DmSetValue(GroupKey,
|
|||
|
CLUSREG_NAME_GRP_NAME,
|
|||
|
REG_SZ,
|
|||
|
(CONST BYTE *)lpszGroupName,
|
|||
|
(lstrlenW(lpszGroupName)+1)*sizeof(WCHAR));
|
|||
|
DmCloseKey(GroupKey);
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiGetGroupId(
|
|||
|
IN HGROUP_RPC hGroup,
|
|||
|
OUT LPWSTR *pGuid
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns the unique identifier (GUID) for a group.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group whose identifer is to be returned
|
|||
|
|
|||
|
pGuid - Returns the unique identifier. This memory must be freed on the
|
|||
|
client side.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
DWORD IdLen;
|
|||
|
LPCWSTR Id;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
|
|||
|
Id = OmObjectId(Group);
|
|||
|
|
|||
|
IdLen = (lstrlenW(Id)+1)*sizeof(WCHAR);
|
|||
|
*pGuid = MIDL_user_allocate(IdLen);
|
|||
|
if (*pGuid == NULL) {
|
|||
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|||
|
}
|
|||
|
CopyMemory(*pGuid, Id, IdLen);
|
|||
|
return(ERROR_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
s_ApiOnlineGroup(
|
|||
|
IN HGROUP_RPC hGroup
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Brings a group and all its dependencies online
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group to be brought online
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
|
|||
|
return(FmOnlineGroup(Group));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
s_ApiOfflineGroup(
|
|||
|
IN HGROUP_RPC hGroup
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Brings a group and all its dependents offline
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group to be brought offline
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
|
|||
|
return(FmOfflineGroup(Group));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
s_ApiMoveGroup(
|
|||
|
IN HGROUP_RPC hGroup
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Moves a group and all its dependents to another system.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group to be moved
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
|
|||
|
return(FmMoveGroup(Group, NULL));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
s_ApiMoveGroupToNode(
|
|||
|
IN HGROUP_RPC hGroup,
|
|||
|
IN HNODE_RPC hNode
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Moves a group and all its dependents to another system.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group to be moved
|
|||
|
|
|||
|
hNode - Supplies the node to move the group to
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
PNM_NODE Node;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
VALIDATE_NODE(Node, hNode);
|
|||
|
|
|||
|
return(FmMoveGroup(Group, Node));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_ApiSetGroupNodeList(
|
|||
|
IN HGROUP_RPC hGroup,
|
|||
|
IN UCHAR *lpNodeList,
|
|||
|
IN DWORD cbListSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the list of preferred nodes for a group.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hGroup - Supplies the group to set the preferred nodes.
|
|||
|
|
|||
|
lpNodeList - Supplies the list of preferred owners, as a REG_MULTI_SZ.
|
|||
|
|
|||
|
cbListSize - Supplies the size in bytes of the preferred owners list.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFM_GROUP Group;
|
|||
|
HDMKEY GroupKey;
|
|||
|
DWORD Status;
|
|||
|
DWORD i;
|
|||
|
DWORD multiSzLength;
|
|||
|
LPWSTR multiSz;
|
|||
|
LPWSTR tmpSz;
|
|||
|
//LPCWSTR lpszNodeList = (LPCWSTR)lpNodeList;
|
|||
|
|
|||
|
API_ASSERT_INIT();
|
|||
|
|
|||
|
VALIDATE_GROUP_EXISTS(Group, hGroup);
|
|||
|
|
|||
|
#if 0
|
|||
|
//
|
|||
|
// Marshall the node list into a MULTI_SZ.
|
|||
|
//
|
|||
|
for ( i = 0; i < dwNodeCount; i++ ) {
|
|||
|
multiSzLength += lstrlenW(rgszNodeList[i] + 1);
|
|||
|
}
|
|||
|
|
|||
|
multiSzLength += sizeof(UNICODE_NULL);
|
|||
|
|
|||
|
multiSz = MIDL_user_allocate(multiSzLength);
|
|||
|
|
|||
|
if ( multiSz == NULL ) {
|
|||
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|||
|
}
|
|||
|
|
|||
|
tmpSz = multiSz;
|
|||
|
|
|||
|
for ( i = 0; i < dwNodeCount; i++ ) {
|
|||
|
lstrcpynW( tmpSz, rgszNodeList[i], lstrlenW(rgszNodeList[i] + 1) );
|
|||
|
}
|
|||
|
|
|||
|
*tmpSz = UNICODE_NULL;
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Set the registry with the REG_MULTI_SZ. Let the FM pick it up from
|
|||
|
// there.
|
|||
|
//
|
|||
|
GroupKey = DmOpenKey(DmGroupsKey,
|
|||
|
OmObjectId(Group),
|
|||
|
KEY_SET_VALUE);
|
|||
|
if (GroupKey == NULL) {
|
|||
|
return(GetLastError());
|
|||
|
}
|
|||
|
|
|||
|
Status = DmSetValue(GroupKey,
|
|||
|
CLUSREG_NAME_GRP_PREFERRED_OWNERS,
|
|||
|
REG_MULTI_SZ,
|
|||
|
(CONST BYTE *)lpNodeList,
|
|||
|
cbListSize);
|
|||
|
|
|||
|
DmCloseKey(GroupKey);
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|