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()
|