/*++ Copyright (c) 1996 Microsoft Corporation Module Name: enum.c Abstract: Server side support for Cluster APIs dealing with enumeration Author: John Vert (jvert) 9-Feb-1996 Revision History: --*/ #include "apip.h" #define ENUM_SIZE(Entries) ((Entries-1) * sizeof(ENUM_ENTRY) + sizeof(ENUM_LIST)) // // Define structure passed to enumeration routine. // typedef struct _REFOBJECT { HDMKEY RootKey; LPCWSTR FriendlyName; DWORD NameLength; LPWSTR NameBuffer; OBJECT_TYPE Type; } REFOBJECT, *PREFOBJECT; BOOL ApipRefObjectWorker( IN PREFOBJECT Target, IN PVOID *pObject, IN PVOID Object, IN LPCWSTR ObjectId ); BOOL ApipEnumResourceWorker( IN PENUM_LIST *pEnum, IN PVOID Context2, IN PFM_RESOURCE Node, IN LPCWSTR Name ); BOOL ApipEnumGroupResourceWorker( IN PENUM_LIST *pEnum, IN PVOID Context2, IN PFM_RESOURCE Node, IN LPCWSTR Name ); BOOL ApipEnumNodeWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PNM_NODE Node, IN LPCWSTR Name ); BOOL ApipEnumResTypeWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PFM_RESTYPE ResType, IN LPCWSTR Name ); BOOL ApipEnumGroupWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PFM_GROUP Group, IN LPCWSTR Name ); BOOL ApipEnumNetworkWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PVOID Object, IN LPCWSTR Name ); DWORD ApipEnumInternalNetworks( IN PENUM_LIST *pEnum, IN DWORD *pAllocated ); BOOL ApipEnumNetworkInterfaceWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PVOID Object, IN LPCWSTR Name ); VOID ApipFreeEnum( IN PENUM_LIST Enum ); error_status_t s_ApiCreateEnum( IN handle_t IDL_handle, IN DWORD dwType, OUT PENUM_LIST *ReturnEnum ) /*++ Routine Description: Enumerates all the specified objects and returns the list of objects to the caller. The client-side is responsible for freeing the allocated memory. Arguments: IDL_handle - RPC binding handle, not used dwType - Supplies the type of objects to be enumerated ReturnEnum - Returns the requested objects. Return Value: ERROR_SUCCESS if successful Win32 error code otherwise. --*/ { DWORD Status; DWORD Allocated = 0; PENUM_LIST Enum = NULL; //initialize to NULL for failure cases *ReturnEnum = NULL; if (dwType != CLUSTER_ENUM_NODE) { API_CHECK_INIT(); } if (dwType & CLUSTER_ENUM_INTERNAL_NETWORK) { if ((dwType & ~CLUSTER_ENUM_INTERNAL_NETWORK) != 0) { return(ERROR_INVALID_PARAMETER); } } else { if (dwType & ~CLUSTER_ENUM_ALL) { return(ERROR_INVALID_PARAMETER); } } Allocated = INITIAL_ENUM_LIST_ALLOCATION; Enum = MIDL_user_allocate(ENUM_SIZE(Allocated)); if (Enum == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; goto ErrorExit; } Enum->EntryCount = 0; // // Enumerate all nodes // if (dwType & CLUSTER_ENUM_NODE) { OmEnumObjects(ObjectTypeNode, ApipEnumNodeWorker, &Enum, &Allocated); } // // Enumerate all resource types // if (dwType & CLUSTER_ENUM_RESTYPE) { OmEnumObjects(ObjectTypeResType, ApipEnumResTypeWorker, &Enum, &Allocated); } // // Enumerate all resources // if (dwType & CLUSTER_ENUM_RESOURCE) { OmEnumObjects(ObjectTypeResource, ApipEnumResourceWorker, &Enum, &Allocated); } // // Enumerate all groups // if (dwType & CLUSTER_ENUM_GROUP) { OmEnumObjects(ObjectTypeGroup, ApipEnumGroupWorker, &Enum, &Allocated); } // // Enumerate all networks // if (dwType & CLUSTER_ENUM_NETWORK) { OmEnumObjects(ObjectTypeNetwork, ApipEnumNetworkWorker, &Enum, &Allocated); } // // Enumerate internal networks in highest to lowest priority order. // if (dwType & CLUSTER_ENUM_INTERNAL_NETWORK) { Status = ApipEnumInternalNetworks(&Enum, &Allocated); if (Status != ERROR_SUCCESS) { goto ErrorExit; } } // // Enumerate all network interfaces // if (dwType & CLUSTER_ENUM_NETINTERFACE) { OmEnumObjects(ObjectTypeNetInterface, ApipEnumNetworkInterfaceWorker, &Enum, &Allocated); } *ReturnEnum = Enum; return(ERROR_SUCCESS); ErrorExit: if (Enum != NULL) { ApipFreeEnum(Enum); } return(Status); } VOID ApipFreeEnum( IN PENUM_LIST Enum ) /*++ Routine Description: Frees an ENUM_LIST and all of its strings. Arguments: Enum - Supplies the Enum to free. Return Value: None. --*/ { DWORD i; // // Walk through enumeration freeing all the names // for (i=0; iEntryCount; i++) { MIDL_user_free(Enum->Entry[i].Name); } MIDL_user_free(Enum); } VOID ApipAddToEnum( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN LPCWSTR Name, IN DWORD Type ) /*++ Routine Description: Common worker callback routine for enumerating objects. Adds the specified resource to the list that is being built up. Arguments: pEnum - Supplies a pointer to the current enumeration list. pAllocated - Supplies a pointer to a dword specifying the current allocation size of the ENUM_LIST. Name - Supplies the name of the object to be added to the ENUM_LIST. A copy of this name will be created by using MIDL_user_allocate. Type - Supplies the object's type Return Value: None --*/ { PENUM_LIST Enum; PENUM_LIST NewEnum; DWORD NewAllocated; DWORD Index; LPWSTR NewName; NewName = MIDL_user_allocate((lstrlenW(Name)+1)*sizeof(WCHAR)); if (NewName == NULL) { CL_UNEXPECTED_ERROR( ERROR_NOT_ENOUGH_MEMORY ); return; } lstrcpyW(NewName, Name); Enum = *pEnum; if (Enum->EntryCount >= *pAllocated) { // // Need to grow the ENUM_LIST // NewAllocated = *pAllocated + 8; NewEnum = MIDL_user_allocate(ENUM_SIZE(NewAllocated)); if (NewEnum == NULL) { MIDL_user_free(NewName); return; } CopyMemory(NewEnum, Enum, ENUM_SIZE(*pAllocated)); CL_ASSERT( Enum->EntryCount == NewEnum->EntryCount ); *pAllocated = NewAllocated; *pEnum = NewEnum; MIDL_user_free(Enum); Enum = NewEnum; } // // Initialize new entry field. // Enum->Entry[Enum->EntryCount].Name = NewName; Enum->Entry[Enum->EntryCount].Type = Type; ++Enum->EntryCount; return; } BOOL ApipEnumResourceWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PFM_RESOURCE Resource, IN LPCWSTR Name ) /*++ Routine Description: Worker callback routine for the enumeration of resources. Adds the specified resource to the list that is being built up. Arguments: pEnum - Supplies a pointer to the current enumeration list. pAllocated - Supplies a pointer to a dword specifying the current allocation size of the ENUM_LIST. Resource - Supplies the resource to be added to the ENUM_LIST Name - Supplies the resource's name Return Value: TRUE to indicate that enumeration should continue. --*/ { LPWSTR RealName; RealName = ApipGetObjectName(Resource); if (RealName != NULL) { ApipAddToEnum(pEnum, pAllocated, RealName, CLUSTER_ENUM_RESOURCE); MIDL_user_free( RealName); } return(TRUE); } BOOL ApipEnumGroupResourceWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PFM_RESOURCE Resource, IN LPCWSTR Name ) /*++ Routine Description: Worker callback routine for the enumeration of resources. Adds the specified resource to the list that is being built up. Arguments: pEnum - Supplies a pointer to the current enumeration list. pAllocated - Supplies a pointer to a dword specifying the current allocation size of the ENUM_LIST. Resource - Supplies the resource to be added to the ENUM_LIST Name - Supplies the resource's name Return Value: TRUE to indicate that enumeration should continue. --*/ { LPWSTR RealName; RealName = ApipGetObjectName(Resource); if (RealName != NULL) { ApipAddToEnum(pEnum, pAllocated, RealName, CLUSTER_GROUP_ENUM_CONTAINS); MIDL_user_free( RealName ); } return(TRUE); } BOOL ApipEnumNodeWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PNM_NODE Node, IN LPCWSTR Name ) /*++ Routine Description: Worker callback routine for the enumeration of nodes. Adds the specified node to the list that is being built up. Arguments: pEnum - Supplies a pointer to the current enumeration list. pAllocated - Supplies a pointer to a dword specifying the current allocation size of the ENUM_LIST. Node - Supplies the node to be added to the ENUM_LIST Name - Supplies the node's name Return Value: TRUE to indicate that enumeration should continue. --*/ { LPCWSTR RealName; RealName = OmObjectName(Node); if (RealName != NULL) { ApipAddToEnum(pEnum, pAllocated, RealName, CLUSTER_ENUM_NODE); } return(TRUE); } BOOL ApipEnumResTypeWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PFM_RESTYPE ResType, IN LPCWSTR Name ) /*++ Routine Description: Worker callback routine for the enumeration of resource types. Adds the specified resource type to the list that is being built up. Arguments: pEnum - Supplies a pointer to the current enumeration list. pAllocated - Supplies a pointer to a dword specifying the current allocation size of the ENUM_LIST. Node - Supplies the resource type to be added to the ENUM_LIST Name - Supplies the resource type's name Return Value: TRUE to indicate that enumeration should continue. --*/ { ApipAddToEnum(pEnum, pAllocated, Name, CLUSTER_ENUM_RESTYPE); return(TRUE); } BOOL ApipEnumGroupWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PFM_GROUP Group, IN LPCWSTR Name ) /*++ Routine Description: Worker callback routine for the enumeration of groups. Adds the specified group to the list that is being built up. Arguments: pEnum - Supplies a pointer to the current enumeration list. pAllocated - Supplies a pointer to a dword specifying the current allocation size of the ENUM_LIST. Group - Supplies the group to be added to the ENUM_LIST Name - Supplies the group's name Return Value: TRUE to indicate that enumeration should continue. --*/ { LPCWSTR RealName; RealName = OmObjectName(Group); if (RealName != NULL) { ApipAddToEnum(pEnum, pAllocated, RealName, CLUSTER_ENUM_GROUP); } return(TRUE); } BOOL ApipEnumNetworkWorker( IN PENUM_LIST *pEnum, IN DWORD *pAllocated, IN PVOID Object, IN LPCWSTR Name ) /*++ Routine Description: Worker callback routine for the enumeration of networks. Adds the specified network to the list that is being built up. Arguments: pEnum - Supplies a pointer to the current enumeration list. pAllocated - Supplies a pointer to a dword specifying the current allocation size of the ENUM_LIST. Object - Supplies the object to be added to the ENUM_LIST Name - Supplies the network's name Return Value: TRUE to indicate that enumeration should continue. --*/ { LPWSTR RealName; RealName = ApipGetObjectName(Object); if (RealName != NULL) { ApipAddToEnum(pEnum, pAllocated, RealName, CLUSTER_ENUM_NETWORK); MIDL_user_free( RealName ); } return(TRUE); } DWORD ApipEnumInternalNetworks( IN PENUM_LIST *pEnum, IN DWORD *pAllocated ) /*++ Routine Description: Enumerates all networks used for internal communication. Arguments: pEnum - Supplies a pointer to the current enumeration list. pAllocated - Supplies a pointer to a dword specifying the current allocation size of the ENUM_LIST. Return Value: ERROR_SUCCESS if successful Win32 error code otherwise. --*/ { DWORD Status; DWORD NetworkCount; PNM_NETWORK *NetworkList; DWORD i; LPWSTR RealName; Status = NmEnumInternalNetworks(&NetworkCount, &NetworkList); if (Status != ERROR_SUCCESS) { return(Status); } for (i=0; iEntryCount = 0; if (dwType & CLUSTER_NODE_ENUM_NETINTERFACES) { Status = NmEnumNodeInterfaces( Node, &InterfaceCount, &InterfaceList ); if (Status != ERROR_SUCCESS) { goto ErrorExit; } for (i=0; iEntryCount = 0; // // Enumerate all contained resources // if (dwType & CLUSTER_GROUP_ENUM_CONTAINS) { // // Enumerate all resources for the Group. // Status = FmEnumerateGroupResources(Group, ApipEnumGroupResourceWorker, &Enum, &Allocated); if ( Status != ERROR_SUCCESS ) { goto ErrorExit; } } if (dwType & CLUSTER_GROUP_ENUM_NODES) { LPWSTR Buffer=NULL; DWORD BufferSize=0; DWORD DataSize=0; DWORD i; HDMKEY GroupKey; LPCWSTR Next; PNM_NODE Node; // // Enumerate all preferred nodes for the group. // Just get this data right out of the registry. // GroupKey = DmOpenKey(DmGroupsKey, OmObjectId(Group), KEY_READ); if (GroupKey == NULL) { Status = GetLastError(); goto ErrorExit; } Status = DmQueryMultiSz(GroupKey, CLUSREG_NAME_GRP_PREFERRED_OWNERS, &Buffer, &BufferSize, &DataSize); DmCloseKey(GroupKey); if (Status != ERROR_FILE_NOT_FOUND) { if (Status != ERROR_SUCCESS) { // // Chittur Subbaraman (chitturs) - 10/05/98 // Fix memory leak // LocalFree(Buffer); goto ErrorExit; } for (i=0; ; i++) { Next = ClRtlMultiSzEnum(Buffer, DataSize/sizeof(WCHAR), i); if (Next == NULL) { Status = ERROR_SUCCESS; break; } Node = OmReferenceObjectById(ObjectTypeNode, Next); if (Node != NULL) { ApipAddToEnum(&Enum, &Allocated, OmObjectName(Node), CLUSTER_GROUP_ENUM_NODES); OmDereferenceObject(Node); } } } // // Chittur Subbaraman (chitturs) - 10/05/98 // Fix memory leak // LocalFree(Buffer); } *ReturnEnum = Enum; return(ERROR_SUCCESS); ErrorExit: if (Enum != NULL) { ApipFreeEnum(Enum); } *ReturnEnum = NULL; return(Status); } error_status_t s_ApiCreateNetworkEnum( IN HNETWORK_RPC hNetwork, IN DWORD dwType, OUT PENUM_LIST *ReturnEnum ) /*++ Routine Description: Enumerates all the interface objects contained in the specified network and returns them to the caller. The client-side is responsible for freeing the allocated memory. Arguments: hNetwork - Supplies the network to be enumerated dwType - Supplies a bitmask of the type of properties to be enumerated. ReturnEnum - Returns the requested objects. Return Value: ERROR_SUCCESS if successful Win32 error code otherwise. --*/ { DWORD Status; DWORD Allocated = 0; PENUM_LIST Enum = NULL; PNM_INTERFACE * InterfaceList; DWORD InterfaceCount; PNM_NETWORK Network; DWORD i; API_CHECK_INIT(); VALIDATE_NETWORK_EXISTS(Network, hNetwork); Allocated = INITIAL_ENUM_LIST_ALLOCATION; Enum = MIDL_user_allocate(ENUM_SIZE(Allocated)); if (Enum == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; goto ErrorExit; } Enum->EntryCount = 0; if (dwType & CLUSTER_NETWORK_ENUM_NETINTERFACES) { Status = NmEnumNetworkInterfaces( Network, &InterfaceCount, &InterfaceList ); if (Status != ERROR_SUCCESS) { goto ErrorExit; } for (i=0; iRootKey, ObjectId, KEY_READ); if (Key == NULL) { CL_UNEXPECTED_ERROR(GetLastError()); return(TRUE); } Size = Target->NameLength; Status = DmQueryValue(Key, L"Name", &Type, (UCHAR *)Target->NameBuffer, &Size); DmCloseKey(Key); if ((Status == ERROR_SUCCESS) && (lstrcmpiW(Target->NameBuffer, Target->FriendlyName)==0)) { // // Found a match. Reference it and return it. // OmReferenceObject(Object); *pObject = Object; return(FALSE); } // // Mismatch. // return(TRUE); } LPWSTR ApipGetObjectName( IN PVOID Object ) /*++ Routine Description: Allocates a string and fills in the object's name. Arguments: Object - A pointer to the object to get its name. Return Value: A pointer to a WSTR that contains the user-friendly name of the object. NULL on failure - use GetLastError to get the Win32 error code. --*/ { LPWSTR Name; DWORD NameSize; if ( OmObjectName(Object) == NULL ) { Name = MIDL_user_allocate(1 * sizeof(WCHAR)); if ( Name != NULL ) { *Name = (WCHAR)0; } else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } } else { NameSize = lstrlenW(OmObjectName(Object)); Name = MIDL_user_allocate((NameSize + 1) * sizeof(WCHAR)); if ( Name != NULL ) { lstrcpyW( Name, OmObjectName(Object) ); } else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } } return(Name); } // ApipGetObjectName