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.
 
 
 
 
 
 

1032 lines
26 KiB

//***************************************************************************
//
// ENGINE.H
//
// Module: NLB Manager (client-side exe)
//
// Purpose: Engine used to operate on groups of NLB hosts.
// This file has no UI aspects.
//
// Copyright (c)2001 Microsoft Corporation, All Rights Reserved
//
// History:
//
// 07/25/01 JosephJ Created
//
//***************************************************************************
#pragma once
//
// This class deliberately causes the following errors...
// CNoCopy xx;
// CNoCopy yy = xx; << Will cause compiler error
// CNoCopy zz;
// zz = xx; << Will cause compiler error
//
// Inheret from it if you want your class to also forbid the above operations.
//
class CNoCopy
{
protected:
CNoCopy(void) {}
~CNoCopy() {}
private:
CNoCopy(const CNoCopy&);
CNoCopy& operator = (const CNoCopy&);
};
typedef ULONG ENGINEHANDLE;
//
// Specification, or settings of a cluster.
// This includes the list of interfacees (i.e., specific adapters on
// specific hosts) that constitute the cluster.
//
class CClusterSpec // : private CNoCopy
{
public:
CClusterSpec(void)
: m_fMisconfigured(FALSE),
m_fPending(FALSE),
m_ehDefaultInterface(NULL),
m_ehPendingOperation(NULL),
m_fNewRctPassword(NULL)
{
// can't do this (vector)! ZeroMemory(this, sizeof(*this));
ZeroMemory(&m_timeLastUpdate, sizeof(m_timeLastUpdate));
}
~CClusterSpec() {}
NLBERROR
Copy(const CClusterSpec &);
NLBERROR
UpdateClusterConfig(
const NLB_EXTENDED_CLUSTER_CONFIGURATION &refNewConfig
)
{
NLBERROR nerr = NLBERR_OK;
WBEMSTATUS wStat;
wStat = m_ClusterNlbCfg.Update(&refNewConfig);
if (FAILED(wStat))
{
nerr = NLBERR_INTERNAL_ERROR;
}
return nerr;
}
// _bstr_t m_bstrId; // Uniquely identifies this cluster in NLB Manager.
_bstr_t m_bstrDisplayName; // Name use for display only (eg: "Cluster1");
BOOL m_fMisconfigured; // Whether or not the cluster is misconfigured.
BOOL m_fPending; // Whether or not there is a pending operation on
// this cluster.
BOOL m_fNewRctPassword; // A new remote-control password is specified
// As long as it is set, the dwHashedPassword
// value can not be trusted.
//
// List of interfaces that form this cluster.
//
vector<ENGINEHANDLE> m_ehInterfaceIdList;
SYSTEMTIME m_timeLastUpdate;
//
// ClusterNlbCfg is the "official" NLB configuration for the cluster.
// It is obtained from one of the hosts.
//
NLB_EXTENDED_CLUSTER_CONFIGURATION m_ClusterNlbCfg;
//
// The host that was last used to get the cluster config.
//
ENGINEHANDLE m_ehDefaultInterface;
ENGINEHANDLE m_ehPendingOperation;
};
//
// Specification, or settings of a host. This includes the list of
// NLB compatible interfaces on the host, machine name, machine GUID,
// connection string, etc.
//
class CHostSpec // : private CNoCopy
{
public:
CHostSpec(void)
: m_fReal(FALSE),
m_fUnreachable(FALSE),
m_ConnectionIpAddress(0)
{
// can't do this! ZeroMemory(this, sizeof(*this));
}
~CHostSpec() {}
void Copy(const CHostSpec &);
BOOL m_fReal; // Whether or not this host is known to correspond
// to real hosts.
BOOL m_fUnreachable; // Whether or not this host is contactable.
// to real hosts.
//
// List of NLB-compatible interfaces (adapters) on this host.
//
vector<ENGINEHANDLE> m_ehInterfaceIdList;
//
// Connection info.
//
_bstr_t m_ConnectionString;
_bstr_t m_UserName;
_bstr_t m_Password;
ULONG m_ConnectionIpAddress; // in network byte order.
_bstr_t m_MachineName;
_bstr_t m_MachineGuid;
};
//
// Specification, or settings of a specific interface (adapter) on a specifc
// host. This includes the NLB configuration on that interface, ip addresses
// bound to the interface, friendly name of the interface, etc.
//
class CInterfaceSpec // : private CNoCopy
{
public:
CInterfaceSpec(void)
: m_fPending(FALSE),
m_fMisconfigured(FALSE),
m_fReal(FALSE),
m_ehHostId(NULL),
m_ehCluster(NULL),
m_fValidClusterState(FALSE),
m_ehPendingOperation(FALSE)
{
// can't do this! ZeroMemory(this, sizeof(*this));
}
~CInterfaceSpec() {}
void Copy(const CInterfaceSpec &);
ENGINEHANDLE m_ehHostId; // The ID of the host that owns this interface.
ENGINEHANDLE m_ehCluster; // The ID of the cluster that this interface is
// a part of, if any.
BOOL m_fPending; // Whether or not there is a pending operation on
// this host.
BOOL m_fMisconfigured; // Whether or not the cluster is misconfigured.
BOOL m_fReal; // Whether or not this cluster is known to correspond
// to real hosts.
BOOL m_fValidClusterState; // Whether or not the "m_dwClusterState" contains a valid value
DWORD m_dwClusterState; // Cluster State : If valid (ie. if m_fValidClusterState is TRUE)
// One of WLBS_CONVERGING/CONVERGED/DEFAULT/DRAINING/STOPPED/SUSPENDED
_bstr_t m_Guid;
_bstr_t m_bstrMachineName; // Cache of the host name -- so we don't have to
// keep looking up the host info just for getting
// the host's name.
NLB_EXTENDED_CLUSTER_CONFIGURATION m_NlbCfg;
_bstr_t m_bstrStatusDetails; // Details (if any) of ongoing updates or
// misconfiguration.
ENGINEHANDLE m_ehPendingOperation;
};
//
// Abstract class (interface) for callbacks to the UI to provide status
// updates and logging etc...
//
class IUICallbacks
{
public:
typedef enum
{
OBJ_INVALID=0,
OBJ_CLUSTER,
OBJ_HOST,
OBJ_INTERFACE,
OBJ_OPERATION
} ObjectType;
typedef enum
{
EVT_ADDED,
EVT_REMOVED,
EVT_STATUS_CHANGE,
EVT_INTERFACE_ADDED_TO_CLUSTER,
EVT_INTERFACE_REMOVED_FROM_CLUSTER
} EventCode;
typedef enum
{
LOG_ERROR,
LOG_WARNING,
LOG_INFORMATIONAL
} LogEntryType;
class LogEntryHeader
{
public:
LogEntryHeader(void)
: type(LOG_INFORMATIONAL),
szCluster(NULL),
szHost(NULL),
szInterface(NULL),
szDetails(NULL)
{}
LogEntryType type;
const wchar_t *szCluster; // OPTIONAL
const wchar_t *szHost; // OPTIONAL
const wchar_t *szInterface; // OPTIONAL
const wchar_t *szDetails; // OPTIONAL
};
//
// Asks the user to update user-supplied info about a host.
//
virtual
BOOL
UpdateHostInformation(
IN BOOL fNeedCredentials,
IN BOOL fNeedConnectionString,
IN OUT CHostSpec& host
) = NULL;
//
// Log a message in human-readable form.
//
virtual
void
Log(
IN LogEntryType Type,
IN const wchar_t *szCluster, OPTIONAL
IN const wchar_t *szHost, OPTIONAL
IN UINT ResourceID,
...
) = NULL;
virtual
void
LogEx(
IN const LogEntryHeader *pHeader,
IN UINT ResourceID,
...
) = NULL;
//
// Handle an event relating to a specific instance of a specific
// object type.
//
virtual
void
HandleEngineEvent(
IN ObjectType objtype,
IN ENGINEHANDLE ehClusterId, // could be NULL
IN ENGINEHANDLE ehObjId,
IN EventCode evt
) = NULL;
};
//
// Used internally by CNlbEngine
//
class CEngineCluster
{
public:
CEngineCluster(VOID)
{
}
~CEngineCluster() {};
CClusterSpec m_cSpec;
};
class CEngineOperation
{
public:
CEngineOperation(ENGINEHANDLE ehOp, ENGINEHANDLE ehObj, PVOID pvCtxt)
: ehOperation(ehOp),
ehObject(ehObj),
pvContext(pvCtxt),
fCanceled(FALSE)
{}
~CEngineOperation()
{
}
ENGINEHANDLE ehOperation;
ENGINEHANDLE ehObject;
_bstr_t bstrDescription;
BOOL fCanceled;
PVOID pvContext;
};
class CNlbEngine
{
public:
CNlbEngine(void)
: m_pCallbacks(NULL),
m_NewHandleValue(1),
m_fHandleOverflow(FALSE),
m_fDeinitializing(FALSE),
m_fPrepareToDeinitialize(FALSE),
m_WorkItemCount(0)
{
InitializeCriticalSection(&m_crit);
}
~CNlbEngine()
{
ASSERT(m_WorkItemCount > 0);
DeleteCriticalSection(&m_crit);
}
NLBERROR
Initialize(
IN IUICallbacks & ui,
BOOL fDemo,
BOOL fNoPing
); // logging, UI callbacks of various kinds.
void
Deinitialize(void);
//
// Called to indicate that deinitialization will soon follow.
// After return from this call, the engine will not create any new
// objects -- interface, host, cluster, operations or start operations.
// The engine may however continue to call the UI callback routines.
//
void
PrepareToDeinitialize(void)
{
m_fPrepareToDeinitialize = TRUE;
}
NLBERROR
ConnectToHost(
IN PWMI_CONNECTION_INFO pConnInfo,
IN BOOL fOverwriteConnectionInfo,
OUT ENGINEHANDLE &ehHost,
OUT _bstr_t &bstrError
);
NLBERROR
LookupClusterByIP(
IN LPCWSTR szIP,
IN const NLB_EXTENDED_CLUSTER_CONFIGURATION *pInitialConfig OPTIONAL,
OUT ENGINEHANDLE &ehCluster,
OUT BOOL &fIsNew
);
//
// if pInitialConfig is NULL we'll lookup and not try to create.
// if not NULL and we don't find an existing cluster, well create
// a new one and initialize it with the specified configuration.
//
NLBERROR
LookupInterfaceByIp(
IN ENGINEHANDLE ehHost, // OPTIONAL -- if NULL all hosts are looked
IN LPCWSTR szIpAddress,
OUT ENGINEHANDLE &ehIf
);
NLBERROR
LookupConnectionInfo(
IN LPCWSTR szConnectionString,
OUT _bstr_t &bstrUsername,
OUT _bstr_t &bstrPassword
);
void
DeleteCluster(IN ENGINEHANDLE ehCluster, BOOL fRemoveInterfaces);
NLBERROR
AutoExpandCluster(
IN ENGINEHANDLE ehCluster
);
NLBERROR
AddInterfaceToCluster(
IN ENGINEHANDLE ehCluster,
IN ENGINEHANDLE ehInterface
);
NLBERROR
RemoveInterfaceFromCluster(
IN ENGINEHANDLE ehCluster,
IN ENGINEHANDLE ehInterface
);
NLBERROR
RefreshAllHosts(
void
);
NLBERROR
RefreshCluster(
IN ENGINEHANDLE ehCluster
);
#if OBSOLETE
NLBERROR
RefreshInterfaceOld(
IN ENGINEHANDLE ehInterface,
IN BOOL fRemoveFromClusterIfUnbound,
IN OUT BOOL &fClusterPropertiesUpdated
);
#endif // OBSOLETE
//
// Queries the host that owns the interface for other
// cluster members, and connects to those and adds those
// members to the cluster.
//
// If (fSync) it will do this synchronously, else it will do it
// in the background.
//
VOID
AddOtherClusterMembers(
IN ENGINEHANDLE ehInterface,
IN BOOL fSync
);
//
// Only call this from the background thread work item thread
// (i.e., not really a public function, but I don't like using
// "friend").
//
VOID
AddOtherClusterMembersWorkItem(
IN ENGINEHANDLE ehInterface
);
NLBERROR
RefreshInterface(
IN ENGINEHANDLE ehInterface,
IN BOOL fNewOperation,
IN BOOL fClusterWide
);
NLBERROR
AnalyzeCluster(
const ENGINEHANDLE ehCluster
);
NLBERROR
GetHostSpec(
IN ENGINEHANDLE ehHost,
OUT CHostSpec& HostSpec
);
NLBERROR
GetHostConnectionInformation(
IN ENGINEHANDLE ehHost,
OUT ENGINEHANDLE &ehConnectionIF,
OUT _bstr_t &bstrConnectionString,
OUT UINT &uConnectionIp
);
NLBERROR
GetClusterSpec(
IN ENGINEHANDLE ehCluster,
OUT CClusterSpec& ClusterSpec
);
NLBERROR
GetInterfaceSpec(
IN ENGINEHANDLE ehInterface,
OUT CInterfaceSpec&
);
NLBERROR
UpdateInterface(
IN ENGINEHANDLE ehInterface,
IN NLB_EXTENDED_CLUSTER_CONFIGURATION &refNewConfig,
// IN OUT BOOL &fClusterPropertiesUpdated,
OUT CLocalLogger logConflict
);
NLBERROR
UpdateCluster(
IN ENGINEHANDLE ehCluster,
IN const NLB_EXTENDED_CLUSTER_CONFIGURATION *pNewConfig OPTIONAL,
IN OUT CLocalLogger &logConflict
);
NLBERROR
EnumerateClusters(
OUT vector <ENGINEHANDLE> & ehClusterList
);
NLBERROR
EnumerateHosts(
OUT vector <ENGINEHANDLE> & ehHostList
);
BOOL
GetObjectType(
IN ENGINEHANDLE ehObj,
OUT IUICallbacks::ObjectType &objType
);
//
// Return a bitmap of available host IDs for the specified cluster.
//
ULONG
GetAvailableHostPriorities(
ENGINEHANDLE ehCluster // OPTIONAL
);
//
// Fill in an array of bitmaps of available priorities for each specified
// port rule.
//
NLBERROR
GetAvailablePortRulePriorities(
IN ENGINEHANDLE ehCluster, OPTIONAL
IN UINT NumRules,
IN WLBS_PORT_RULE rgRules[],
IN OUT ULONG rgAvailablePriorities[] // At least NumRules
);
NLBERROR
GetAllHostConnectionStrings(
OUT vector <_bstr_t> & ConnectionStringList
);
NLBERROR
ControlClusterOnInterface(
IN ENGINEHANDLE ehInterfaceId,
IN WLBS_OPERATION_CODES Operation,
IN CString szVipArray[],
IN DWORD pdwPortNumArray[],
IN DWORD dwNumOfPortRules,
IN BOOL fNewOperation
);
NLBERROR
ControlClusterOnCluster(
IN ENGINEHANDLE ehClusterId,
IN WLBS_OPERATION_CODES Operation,
IN CString szVipArray[],
IN DWORD pdwPortNumArray[],
IN DWORD dwNumOfPortRules
);
NLBERROR
FindInterfaceOnHostByClusterIp(
IN ENGINEHANDLE ehHostId,
IN LPCWSTR szClusterIp, // OPTIONAL
OUT ENGINEHANDLE &ehInterfaceId, // first found
OUT UINT &NumFound
);
NLBERROR
InitializeNewHostConfig(
IN ENGINEHANDLE ehClusterId,
OUT NLB_EXTENDED_CLUSTER_CONFIGURATION &NlbCfg
);
static // TODO: move somewhere else -- more a utility function.
NLBERROR
ApplyClusterWideConfiguration(
IN const NLB_EXTENDED_CLUSTER_CONFIGURATION &ClusterConfig,
IN OUT NLB_EXTENDED_CLUSTER_CONFIGURATION &ConfigToUpdate
);
NLBERROR
GetInterfaceInformation(
IN ENGINEHANDLE ehInterface,
OUT CHostSpec& hSpec,
OUT CInterfaceSpec& iSpec,
OUT _bstr_t& bstrDisplayName,
OUT INT& iIcon,
OUT _bstr_t& bstrStatus
);
NLBERROR
GetInterfaceIdentification(
IN ENGINEHANDLE ehInterface,
OUT ENGINEHANDLE& ehHost,
OUT ENGINEHANDLE& ehCluster,
OUT _bstr_t & bstrFriendlyName,
OUT _bstr_t & bstrDisplayName,
OUT _bstr_t & bstrHostName
);
NLBERROR
GetClusterIdentification(
IN ENGINEHANDLE ehCluster,
OUT _bstr_t & bstrIpAddress,
OUT _bstr_t & bstrDomainName,
OUT _bstr_t & bstrDisplayName
);
//
// Verify that the specified ip address may be used as a new cluster IP
// address for the specified existing cluster ehCluster (or a new
// cluster, if ehCluster is NULL).
//
// If there is no conflict (i.e. address can be used), the function returns
// NLBERR_OK.
//
// If the IP address is already used for something, that "something"
// is specified in logConflict and the function returns
// NLBERR_INVALID_IP_ADDRESS_SPECIFICATION.
//
// If the IP address already exists on an interface that is NOT
// part of a cluster known to NLBManager, fExistOnRawInterface is set
// to TRUE, else fExistOnRawInterface is set to FALSE.
//
NLBERROR
ValidateNewClusterIp(
IN ENGINEHANDLE ehCluster, // OPTIONAL
IN LPCWSTR szIp,
OUT BOOL &fExistsOnRawIterface,
IN OUT CLocalLogger &logConflict
);
//
// Verify that the specified ip address may be used as the dedicated IP
// address for the specified existing interface.
//
// If there is no conflict (i.e. address can be used), the function returns
// NLBERR_OK.
//
// If the IP address is already used for something, that "something"
// is specified in logConflict and the function returns
// NLBERR_INVALID_IP_ADDRESS_SPECIFICATION.
//
NLBERROR
ValidateNewDedicatedIp(
IN ENGINEHANDLE ehIF,
IN LPCWSTR szIp,
IN OUT CLocalLogger &logConflict
);
//
// Updates the specified interface, assuming it has already been set up
// to do an update in the background -- this function is ONLY
// called from the work-item thread internally to CNlbEngine.
//
VOID
UpdateInterfaceWorkItem(
IN ENGINEHANDLE ehIF
);
//
// If it's possible to start an interface operation at this time,
// the function returns NLB_OK, setting fCanStart to TRUE.
//
// If it can't start an interface, because there is an existing interface
// operation or a cluster operation ongoing, the function returns NLB_OK,
// and sets fCanStart to FALSE.
//
// Otherwise (some kind of error) it returns an error value.
//
NLBERROR
CanStartInterfaceOperation(
IN ENGINEHANDLE ehIF,
OUT BOOL &fCanStart
);
//
// Similar to CanStartInterfaceOperation, except it applies to the specified
// cluster.
//
NLBERROR
CanStartClusterOperation(
IN ENGINEHANDLE ehCluster,
OUT BOOL &fCanStart
);
UINT
ListPendingOperations(
CLocalLogger &logOperations
);
//
// Mark all pending operations as cancelled.
// If (fBlock), will block until no more operations are pending.
//
void
CancelAllPendingOperations(
BOOL fBlock
);
//
// Attempts to connect to the specified host and manages
// the specified cluster (szClusterIp) under nlb manager.
// If szClusterIp is NULL, it will manage all clusters on the host.
//
NLBERROR
LoadHost(
IN PWMI_CONNECTION_INFO pConnInfo,
IN LPCWSTR szClusterIp OPTIONAL
);
VOID
AnalyzeInterface_And_LogResult(ENGINEHANDLE ehIID);
//
// Goes through all hosts, and deletes any that have no interface
// that is being managed as a cluster in Nlbmgr.exe. Will skip (not delete)
// hosts that have pending operations on them.
//
VOID
PurgeUnmanagedHosts(void);
VOID
UnmanageHost(ENGINEHANDLE ehHost);
private:
IUICallbacks *m_pCallbacks;
CRITICAL_SECTION m_crit;
void mfn_Lock(void) {EnterCriticalSection(&m_crit);}
void mfn_Unlock(void) {LeaveCriticalSection(&m_crit);}
NLBERROR
mfn_RefreshHost(
IN PWMI_CONNECTION_INFO pConnInfo,
IN ENGINEHANDLE ehHost,
IN BOOL fOverwriteConnectionInfo
);
NLBERROR
mfn_GetHostFromInterfaceLk(
IN ENGINEHANDLE ehIId,
OUT CInterfaceSpec* &pISpec,
OUT CHostSpec* &pHSpec
);
void
mfn_GetInterfaceHostNameLk(
ENGINEHANDLE ehIId,
_bstr_t &bstrHostName
);
NLBERROR
mfn_LookupHostByNameLk(
IN LPCWSTR szHostName,
IN BOOL fCreate,
OUT ENGINEHANDLE &ehHost,
OUT CHostSpec* &pHostSpec,
OUT BOOL &fIsNew
);
NLBERROR
mfn_LookupInterfaceByGuidLk(
IN LPCWSTR szInterfaceGuid,
IN BOOL fCreate,
OUT ENGINEHANDLE &ehInterface,
OUT CInterfaceSpec* &pISpec,
OUT BOOL &fIsNew
);
NLBERROR
mfn_LookupInterfaceByIpLk(
IN ENGINEHANDLE ehHost, // OPTIONAL -- if NULL all hosts are looked
IN LPCWSTR szIpAddress,
OUT ENGINEHANDLE &ehIf
);
VOID
CNlbEngine::mfn_NotifyHostInterfacesChange(ENGINEHANDLE ehHost);
VOID
mfn_ReallyUpdateInterface(
IN ENGINEHANDLE ehInterface,
IN NLB_EXTENDED_CLUSTER_CONFIGURATION &refNewConfig
// IN OUT BOOL &fClusterPropertiesUpdated
);
VOID
mfn_GetLogStrings(
IN WLBS_OPERATION_CODES Operation,
IN LPCWSTR szVip,
IN DWORD * pdwPortNum,
IN DWORD dwOperationStatus,
IN DWORD dwClusterOrPortStatus,
OUT IUICallbacks::LogEntryType & LogLevel,
OUT _bstr_t & OperationStr,
OUT _bstr_t & OperationStatusStr,
OUT _bstr_t & ClusterOrPortStatusStr
);
NLBERROR
mfn_AnalyzeInterfaceLk(
ENGINEHANDLE ehInterface,
CLocalLogger &logger
);
NLBERROR
mfn_ClusterOrInterfaceOperationsPendingLk(
IN CEngineCluster *pECluster,
OUT BOOL &fCanStart
);
VOID
mfn_DeleteHostIfNotManagedLk(
ENGINEHANDLE ehHost
);
map< ENGINEHANDLE, CEngineCluster* > m_mapIdToEngineCluster;
map< ENGINEHANDLE, CHostSpec* > m_mapIdToHostSpec;
map< ENGINEHANDLE, CInterfaceSpec* > m_mapIdToInterfaceSpec;
map< ENGINEHANDLE, CEngineOperation* > m_mapIdToOperation;
//
// Following is dummy...
//
map< _bstr_t, ENGINEHANDLE> m_mapHostNameToHostId;
//
// Used to create new handle values.
// Incremented using InterlockedIncrement each time
// a new handle value is reached.
// 0 is an invalid handle value,
//
LONG m_NewHandleValue;
BOOL m_fHandleOverflow;
BOOL m_fDeinitializing;
BOOL m_fPrepareToDeinitialize;
//
// Count of outstanding work items -- maintained by
// InterlockedIncrement/Decrement.
// CancelAllPendingOperations waits for this count to go to zero
// before returning.
//
// Also, the destructor blocks until this count goes to zero.
//
LONG m_WorkItemCount;
ENGINEHANDLE
mfn_NewHandleLk(IUICallbacks::ObjectType);
void
mfn_SetInterfaceMisconfigStateLk(
IN CInterfaceSpec *pIF,
IN BOOL fMisconfig,
IN LPCWSTR szMisconfigDetails
);
BOOL
mfn_HostHasManagedClustersLk(CHostSpec *pHSpec);
void
mfn_UpdateInterfaceStatusDetails(ENGINEHANDLE ehIF, LPCWSTR szDetails);
CEngineOperation *
mfn_NewOperationLk(ENGINEHANDLE ehObj, PVOID pvCtxt, LPCWSTR szDescription);
VOID
mfn_DeleteOperationLk(ENGINEHANDLE ehOperation);
CEngineOperation *
mfn_GetOperationLk(ENGINEHANDLE ehOp);
NLBERROR
mfn_StartInterfaceOperationLk(
IN ENGINEHANDLE ehIF,
IN PVOID pvCtxt,
IN LPCWSTR szDescription,
OUT ENGINEHANDLE *pExistingOperation
);
VOID
mfn_StopInterfaceOperationLk(
IN ENGINEHANDLE ehIF
);
NLBERROR
mfn_StartClusterOperationLk(
IN ENGINEHANDLE ehCluster,
IN PVOID pvCtxt,
IN LPCWSTR szDescription,
OUT ENGINEHANDLE *pExistingOperation
);
VOID
mfn_StopClusterOperationLk(
ENGINEHANDLE ehCluster
);
NLBERROR
mfn_RefreshInterface(
IN ENGINEHANDLE ehInterface
);
BOOL
mfn_UpdateClusterProps(
ENGINEHANDLE ehClusterId,
ENGINEHANDLE ehIId
);
//
// Waits for the count of pending operations on interfaces in this cluster
// got go to zero.
//
NLBERROR
mfn_WaitForInterfaceOperationCompletions(
IN ENGINEHANDLE ehCluster
);
//
// Verifies that all interfaces and the cluster have the same cluster mode.
//
// Will fail if any interface is marked misconfigured or is
// not bound to NLB.
//
// On returning success, fSameMode is set to TRUE iff all IFs and the
// cluster have the same mode.
//
NLBERROR
mfn_VerifySameModeLk(
IN ENGINEHANDLE ehCluster,
OUT BOOL &fSameMode
);
//
// Check connectivity to the host. If not available mark
// it as such. Update the UI.
//
NLBERROR
mfn_CheckHost(
IN PWMI_CONNECTION_INFO pConnInfo,
IN ENGINEHANDLE ehHost // OPTIONAL
);
VOID
mfn_UnlinkHostFromClusters(
IN ENGINEHANDLE ehHost
);
};