595 lines
12 KiB
C
595 lines
12 KiB
C
/*++
|
||
|
||
Copyright (c) 1996-1999 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
network.c
|
||
|
||
Abstract:
|
||
|
||
Provides interface for managing cluster networks
|
||
|
||
Author:
|
||
|
||
John Vert (jvert) 30-Jan-1996
|
||
Charlie Wickham (charlwi) 5-Jun-1997
|
||
|
||
Revision History:
|
||
copied from group.c
|
||
|
||
--*/
|
||
|
||
#include "clusapip.h"
|
||
|
||
|
||
HNETWORK
|
||
WINAPI
|
||
OpenClusterNetwork(
|
||
IN HCLUSTER hCluster,
|
||
IN LPCWSTR lpszNetworkName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Opens a handle to the specified network
|
||
|
||
Arguments:
|
||
|
||
hCluster - Supplies a handle to the cluster
|
||
|
||
lpszNetworkName - Supplies the name of the network to be opened
|
||
|
||
Return Value:
|
||
|
||
non-NULL - returns an open handle to the specified network.
|
||
|
||
NULL - The operation failed. Extended error status is available
|
||
using GetLastError()
|
||
|
||
--*/
|
||
|
||
{
|
||
PCLUSTER Cluster;
|
||
PCNETWORK Network;
|
||
error_status_t Status = ERROR_SUCCESS;
|
||
|
||
//
|
||
// get a pointer to the cluster struct, alloocate space for the network
|
||
// structure and the supplied name.
|
||
//
|
||
|
||
Cluster = (PCLUSTER)hCluster;
|
||
|
||
Network = LocalAlloc(LMEM_FIXED, sizeof(CNETWORK));
|
||
if (Network == NULL) {
|
||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||
return(NULL);
|
||
}
|
||
|
||
Network->Name = LocalAlloc(LMEM_FIXED, (lstrlenW(lpszNetworkName)+1)*sizeof(WCHAR));
|
||
if (Network->Name == NULL) {
|
||
LocalFree(Network);
|
||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||
return(NULL);
|
||
}
|
||
|
||
//
|
||
// init the network struct and call clussvc to open the network
|
||
//
|
||
|
||
lstrcpyW(Network->Name, lpszNetworkName);
|
||
Network->Cluster = Cluster;
|
||
InitializeListHead(&Network->NotifyList);
|
||
|
||
WRAP_NULL(Network->hNetwork,
|
||
(ApiOpenNetwork(Cluster->RpcBinding,
|
||
lpszNetworkName,
|
||
&Status)),
|
||
&Status,
|
||
Cluster);
|
||
|
||
if ((Network->hNetwork == NULL) || (Status != ERROR_SUCCESS)) {
|
||
|
||
LocalFree(Network->Name);
|
||
LocalFree(Network);
|
||
SetLastError(Status);
|
||
return(NULL);
|
||
}
|
||
|
||
//
|
||
// Link newly opened network onto the cluster structure.
|
||
//
|
||
|
||
EnterCriticalSection(&Cluster->Lock);
|
||
InsertHeadList(&Cluster->NetworkList, &Network->ListEntry);
|
||
LeaveCriticalSection(&Cluster->Lock);
|
||
|
||
return ((HNETWORK)Network);
|
||
}
|
||
|
||
|
||
BOOL
|
||
WINAPI
|
||
CloseClusterNetwork(
|
||
IN HNETWORK hNetwork
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Closes a network handle returned from OpenClusterNetwork
|
||
|
||
Arguments:
|
||
|
||
hNetwork - Supplies the network handle
|
||
|
||
Return Value:
|
||
|
||
TRUE - The operation was successful.
|
||
|
||
FALSE - The operation failed. Extended error status is available
|
||
using GetLastError()
|
||
|
||
--*/
|
||
|
||
{
|
||
PCNETWORK Network;
|
||
PCLUSTER Cluster;
|
||
|
||
Network = (PCNETWORK)hNetwork;
|
||
Cluster = (PCLUSTER)Network->Cluster;
|
||
|
||
//
|
||
// Unlink network from cluster list.
|
||
//
|
||
EnterCriticalSection(&Cluster->Lock);
|
||
RemoveEntryList(&Network->ListEntry);
|
||
|
||
//
|
||
// Remove any notifications posted against this network.
|
||
//
|
||
RundownNotifyEvents(&Network->NotifyList, Network->Name);
|
||
|
||
//if the cluster is dead and the reconnect has failed,
|
||
//the Network->hNetwork might be NULL if s_apiopennetinterface for
|
||
//this network failed on a reconnect
|
||
//the cluster may be dead and hinterface may be non null, say
|
||
//if reconnectnetworks succeeded but say the reconnectgroups
|
||
//failed
|
||
// At reconnect, the old context is saved in the obsolete
|
||
// list for deletion when the cluster handle is closed or when
|
||
// the next call is made
|
||
if ((Cluster->Flags & CLUS_DEAD) && (Network->hNetwork))
|
||
{
|
||
RpcSmDestroyClientContext(&Network->hNetwork);
|
||
LeaveCriticalSection(&Cluster->Lock);
|
||
goto FnExit;
|
||
}
|
||
|
||
LeaveCriticalSection(&Cluster->Lock);
|
||
|
||
//
|
||
// Close RPC context handle
|
||
//
|
||
ApiCloseNetwork(&Network->hNetwork);
|
||
|
||
FnExit:
|
||
//
|
||
// Free memory allocations
|
||
//
|
||
LocalFree(Network->Name);
|
||
LocalFree(Network);
|
||
|
||
//
|
||
// Give the cluster a chance to clean up in case this
|
||
// network was the only thing keeping it around.
|
||
//
|
||
CleanupCluster(Cluster);
|
||
return(TRUE);
|
||
}
|
||
|
||
|
||
CLUSTER_NETWORK_STATE
|
||
WINAPI
|
||
GetClusterNetworkState(
|
||
IN HNETWORK hNetwork
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the network's current state
|
||
|
||
Arguments:
|
||
|
||
hNetwork - Supplies a handle to a cluster network
|
||
|
||
Return Value:
|
||
|
||
Returns the current state of the network.
|
||
If the function fails, the return value is -1. Extended error
|
||
status is available using GetLastError()
|
||
|
||
--*/
|
||
|
||
{
|
||
PCNETWORK Network;
|
||
CLUSTER_NETWORK_STATE State;
|
||
DWORD Status;
|
||
|
||
Network = (PCNETWORK)hNetwork;
|
||
|
||
WRAP(Status,
|
||
(ApiGetNetworkState( Network->hNetwork,
|
||
(LPDWORD)&State )), // cast for win64 warning
|
||
Network->Cluster);
|
||
|
||
if (Status == ERROR_SUCCESS) {
|
||
|
||
return(State);
|
||
} else {
|
||
|
||
SetLastError(Status);
|
||
return( ClusterNetworkStateUnknown );
|
||
}
|
||
}
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
SetClusterNetworkName(
|
||
IN HNETWORK hNetwork,
|
||
IN LPCWSTR lpszNetworkName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the friendly name of a cluster network
|
||
|
||
Arguments:
|
||
|
||
hNetwork - Supplies a handle to a cluster network
|
||
|
||
lpszNetworkName - Supplies the new name of the cluster network
|
||
|
||
cchName - ?
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful
|
||
|
||
Win32 error code otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
PCNETWORK Network;
|
||
DWORD Status;
|
||
|
||
Network = (PCNETWORK)hNetwork;
|
||
|
||
WRAP(Status,
|
||
(ApiSetNetworkName(Network->hNetwork, lpszNetworkName)),
|
||
Network->Cluster);
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
GetClusterNetworkId(
|
||
IN HNETWORK hNetwork,
|
||
OUT LPWSTR lpszNetworkId,
|
||
IN OUT LPDWORD lpcchName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the unique identifier of the specified network
|
||
|
||
Arguments:
|
||
|
||
hNetwork - Supplies the network whose unique ID is to be returned.
|
||
|
||
lpszNetworkId - Points to a buffer that receives the unique ID of the object,
|
||
including the terminating null character.
|
||
|
||
lpcchName - Points to a variable that specifies the size, in characters
|
||
of the buffer pointed to by the lpszNetworkId parameter. This size
|
||
should include the terminating null character. When the function
|
||
returns, the variable pointed to be lpcchName contains the number
|
||
of characters stored in the buffer. The count returned does not
|
||
include the terminating null character.
|
||
|
||
Return Value:
|
||
|
||
If the function succeeds, the return value is ERROR_SUCCESS.
|
||
|
||
If the function fails, the return value is an error value.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD Status;
|
||
DWORD Length;
|
||
PCNETWORK Network = (PCNETWORK)hNetwork;
|
||
LPWSTR Guid=NULL;
|
||
|
||
WRAP(Status,
|
||
(ApiGetNetworkId(Network->hNetwork,
|
||
&Guid)),
|
||
Network->Cluster);
|
||
|
||
if (Status != ERROR_SUCCESS) {
|
||
return(Status);
|
||
}
|
||
|
||
MylstrcpynW(lpszNetworkId, Guid, *lpcchName);
|
||
Length = lstrlenW(Guid);
|
||
|
||
if (Length >= *lpcchName) {
|
||
if (lpszNetworkId == NULL) {
|
||
Status = ERROR_SUCCESS;
|
||
} else {
|
||
Status = ERROR_MORE_DATA;
|
||
}
|
||
}
|
||
|
||
*lpcchName = Length;
|
||
MIDL_user_free(Guid);
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
HNETWORKENUM
|
||
WINAPI
|
||
ClusterNetworkOpenEnum(
|
||
IN HNETWORK hNetwork,
|
||
IN DWORD dwType
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initiates an enumeration of the existing cluster network objects.
|
||
|
||
Arguments:
|
||
|
||
hNetwork - Supplies a handle to the specific network.
|
||
|
||
dwType - Supplies a bitmask of the type of properties to be
|
||
enumerated.
|
||
|
||
Return Value:
|
||
|
||
If successful, returns a handle suitable for use with ClusterNetworkEnum
|
||
|
||
If unsuccessful, returns NULL and GetLastError() returns a more
|
||
specific error code.
|
||
|
||
--*/
|
||
|
||
{
|
||
PCNETWORK Network = (PCNETWORK)hNetwork;
|
||
PENUM_LIST Enum = NULL;
|
||
DWORD errorStatus;
|
||
|
||
//
|
||
// validate bitmask
|
||
//
|
||
|
||
if ((dwType & CLUSTER_NETWORK_ENUM_ALL) == 0) {
|
||
SetLastError(ERROR_INVALID_PARAMETER);
|
||
return(NULL);
|
||
}
|
||
|
||
if ((dwType & ~CLUSTER_NETWORK_ENUM_ALL) != 0) {
|
||
SetLastError(ERROR_INVALID_PARAMETER);
|
||
return(NULL);
|
||
}
|
||
|
||
//
|
||
// open connection to service for enum'ing
|
||
//
|
||
|
||
WRAP(errorStatus,
|
||
(ApiCreateNetworkEnum(Network->hNetwork,
|
||
dwType,
|
||
&Enum)),
|
||
Network->Cluster);
|
||
|
||
if (errorStatus != ERROR_SUCCESS) {
|
||
|
||
SetLastError(errorStatus);
|
||
return(NULL);
|
||
}
|
||
|
||
return((HNETWORKENUM)Enum);
|
||
}
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClusterNetworkGetEnumCount(
|
||
IN HNETWORKENUM hNetworkEnum
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Gets the number of items contained the the enumerator's collection.
|
||
|
||
Arguments:
|
||
|
||
hEnum - a handle to an enumerator returned by ClusterNetworkOpenEnum.
|
||
|
||
Return Value:
|
||
|
||
The number of items (possibly zero) in the enumerator's collection.
|
||
|
||
--*/
|
||
{
|
||
PENUM_LIST Enum = (PENUM_LIST)hNetworkEnum;
|
||
return Enum->EntryCount;
|
||
}
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClusterNetworkEnum(
|
||
IN HNETWORKENUM hNetworkEnum,
|
||
IN DWORD dwIndex,
|
||
OUT LPDWORD lpdwType,
|
||
OUT LPWSTR lpszName,
|
||
IN OUT LPDWORD lpcchName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the next enumerable resource object.
|
||
|
||
Arguments:
|
||
|
||
hNetworkEnum - Supplies a handle to an open cluster network enumeration
|
||
returned by ClusterNetworkOpenEnum
|
||
|
||
dwIndex - Supplies the index to enumerate. This parameter should be
|
||
zero for the first call to the ClusterEnum function and then
|
||
incremented for subsequent calls.
|
||
|
||
lpdwType - Returns the type of network.
|
||
|
||
lpszName - Points to a buffer that receives the name of the network
|
||
object, including the terminating null character.
|
||
|
||
lpcchName - Points to a variable that specifies the size, in characters,
|
||
of the buffer pointed to by the lpszName parameter. This size
|
||
should include the terminating null character. When the function
|
||
returns, the variable pointed to by lpcchName contains the
|
||
number of characters stored in the buffer. The count returned
|
||
does not include the terminating null character.
|
||
|
||
Return Value:
|
||
|
||
If the function succeeds, the return value is ERROR_SUCCESS.
|
||
|
||
If the function fails, the return value is an error value.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD Status;
|
||
DWORD NameLen;
|
||
PENUM_LIST Enum = (PENUM_LIST)hNetworkEnum;
|
||
|
||
if (dwIndex >= Enum->EntryCount) {
|
||
return(ERROR_NO_MORE_ITEMS);
|
||
}
|
||
|
||
NameLen = lstrlenW( Enum->Entry[dwIndex].Name );
|
||
|
||
MylstrcpynW(lpszName, Enum->Entry[dwIndex].Name, *lpcchName);
|
||
|
||
if (*lpcchName < (NameLen + 1)) {
|
||
if (lpszName == NULL) {
|
||
Status = ERROR_SUCCESS;
|
||
} else {
|
||
Status = ERROR_MORE_DATA;
|
||
}
|
||
} else {
|
||
Status = ERROR_SUCCESS;
|
||
}
|
||
|
||
*lpdwType = Enum->Entry[dwIndex].Type;
|
||
*lpcchName = NameLen;
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
DWORD
|
||
WINAPI
|
||
ClusterNetworkCloseEnum(
|
||
IN HNETWORKENUM hNetworkEnum
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Closes an open enumeration for a network.
|
||
|
||
Arguments:
|
||
|
||
hNetworkEnum - Supplies a handle to the enumeration to be closed.
|
||
|
||
Return Value:
|
||
|
||
If the function succeeds, the return value is ERROR_SUCCESS.
|
||
|
||
If the function fails, the return value is an error value.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD i;
|
||
PENUM_LIST Enum = (PENUM_LIST)hNetworkEnum;
|
||
|
||
//
|
||
// Walk through enumeration freeing all the names
|
||
//
|
||
for (i=0; i<Enum->EntryCount; i++) {
|
||
MIDL_user_free(Enum->Entry[i].Name);
|
||
}
|
||
MIDL_user_free(Enum);
|
||
return(ERROR_SUCCESS);
|
||
}
|
||
|
||
|
||
HCLUSTER
|
||
WINAPI
|
||
GetClusterFromNetwork(
|
||
IN HNETWORK hNetwork
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the cluster handle from the associated network handle.
|
||
|
||
Arguments:
|
||
|
||
hNetwork - Supplies the network.
|
||
|
||
Return Value:
|
||
|
||
Handle to the cluster associated with the network handle.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD nStatus;
|
||
PCNETWORK Network = (PCNETWORK)hNetwork;
|
||
HCLUSTER hCluster = (HCLUSTER)Network->Cluster;
|
||
|
||
nStatus = AddRefToClusterHandle( hCluster );
|
||
if ( nStatus != ERROR_SUCCESS ) {
|
||
SetLastError( nStatus );
|
||
hCluster = NULL;
|
||
}
|
||
return( hCluster );
|
||
|
||
} // GetClusterFromNetwork()
|