﻿<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <Manifest>
    <Identity>
      <ID>Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix</ID>
      <Version>6.0.6278.0</Version>
    </Identity>
    <Name>Microsoft Windows 2003 Cluster Quick Unofficial Discovery Fix</Name>
    <References>
      <Reference Alias="SC">
        <ID>Microsoft.SystemCenter.Library</ID>
        <Version>6.0.5000.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Clus2003Library">
        <ID>Microsoft.Windows.2003.Cluster.Management.Library</ID>
        <Version>6.0.6277.1</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Cluster">
        <ID>Microsoft.Windows.Cluster.Library</ID>
        <Version>6.0.6277.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="ClusLibrary">
        <ID>Microsoft.Windows.Cluster.Management.Library</ID>
        <Version>6.0.6277.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="ClusMonitoring">
        <ID>Microsoft.Windows.Cluster.Management.Monitoring</ID>
        <Version>6.0.6277.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>6.0.5000.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Server2003">
        <ID>Microsoft.Windows.Server.2003</ID>
        <Version>6.0.5000.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Server">
        <ID>Microsoft.Windows.Server.Library</ID>
        <Version>6.0.5000.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>6.0.5000.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        <ClassType ID="Microsoft.Windows.Cluster.Group.Fix" Accessibility="Internal" Abstract="false" Base="ClusLibrary!Microsoft.Windows.Cluster.Group" Hosted="false" Singleton="false">
          <Property ID="OriginalGroupName" Type="string" Key="false" CaseSensitive="false" Length="256" MinLength="0" />
        </ClassType>
      </ClassTypes>
    </EntityTypes>
    <ModuleTypes>
      <DataSourceModuleType ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.DataSource" Accessibility="Public" RunAs="Cluster!Microsoft.Windows.Cluster.PrivilegedAccount" Batching="false">
        <Configuration>
          <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" />
          <xsd:element minOccurs="1" name="SyncTime" type="xsd:string" />
          <xsd:element minOccurs="1" name="ProxyingEnabled" type="xsd:string" />
          <xsd:element minOccurs="1" name="DiscoverySourceId" type="xsd:string" />
          <xsd:element minOccurs="1" name="NetworkContainsInterfaceGuid" type="xsd:string" />
          <xsd:element minOccurs="1" name="NetworkInterfaceTypeGuid" type="xsd:string" />
          <xsd:element minOccurs="1" name="NetworkInterfacePropClusterNameGuid" type="xsd:string" />
          <xsd:element minOccurs="1" name="NetworkInterfacePropNameGuid" type="xsd:string" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <DataSource ID="DS" TypeID="System!System.Discovery.Scheduler">
                <Scheduler>
                  <SimpleReccuringSchedule>
                    <Interval>$Config/IntervalSeconds$</Interval>
                    <SyncTime>$Config/SyncTime$</SyncTime>
                  </SimpleReccuringSchedule>
                  <ExcludeDates />
                </Scheduler>
              </DataSource>
              <ProbeAction ID="Script" TypeID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.ScriptProbe">
                <DiscoverySourceId>$Config/DiscoverySourceId$</DiscoverySourceId>
                <NetworkContainsInterfaceGuid>$Config/NetworkContainsInterfaceGuid$</NetworkContainsInterfaceGuid>
                <NetworkInterfaceTypeGuid>$Config/NetworkInterfaceTypeGuid$</NetworkInterfaceTypeGuid>
                <NetworkInterfacePropClusterNameGuid>$Config/NetworkInterfacePropClusterNameGuid$</NetworkInterfacePropClusterNameGuid>
                <NetworkInterfacePropNameGuid>$Config/NetworkInterfacePropNameGuid$</NetworkInterfacePropNameGuid>
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="Script">
                <Node ID="DS" />
              </Node>
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.Discovery.Data</OutputType>
      </DataSourceModuleType>
      <ProbeActionModuleType ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.ScriptProbe" Accessibility="Internal" RunAs="Cluster!Microsoft.Windows.Cluster.PrivilegedAccount" Batching="false" PassThrough="false">
        <Configuration>
          <xsd:element minOccurs="1" name="DiscoverySourceId" type="xsd:string" />
          <xsd:element minOccurs="1" name="NetworkContainsInterfaceGuid" type="xsd:string" />
          <xsd:element minOccurs="1" name="NetworkInterfaceTypeGuid" type="xsd:string" />
          <xsd:element minOccurs="1" name="NetworkInterfacePropClusterNameGuid" type="xsd:string" />
          <xsd:element minOccurs="1" name="NetworkInterfacePropNameGuid" type="xsd:string" />
        </Configuration>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <ProbeAction ID="Script" TypeID="Windows!Microsoft.Windows.ScriptDiscoveryProbe">
                <ScriptName>DiscoverClusteringUnofficialFix.vbs</ScriptName>
                <Arguments>$Config/DiscoverySourceId$ $Target/Id$ $Target/Host/Property[Type='Windows!Microsoft.Windows.Computer']/PrincipalName$ $Target/Host/Property[Type='Windows!Microsoft.Windows.Computer']/NetbiosComputerName$ $Config/NetworkContainsInterfaceGuid$ $Config/NetworkInterfaceTypeGuid$ $Config/NetworkInterfacePropClusterNameGuid$ $Config/NetworkInterfacePropNameGuid$</Arguments>
                <ScriptBody>
                  <![CDATA[
Option Explicit

Const wbemCimtypeUseDefault = 0   'Use Default Type CIM type - Custom
Const wbemCimtypeSint16     = 2   'Signed 16-bit integer 
Const wbemCimtypeSint32     = 3   'Signed 32-bit integer 
Const wbemCimtypeReal32     = 4   '32-bit real number 
Const wbemCimtypeReal64     = 5   '64-bit real number 
Const wbemCimtypeString     = 8   'String 
Const wbemCimtypeBoolean    = 11  'Boolean value 
Const wbemCimtypeObject     = 13  'CIM object 
Const wbemCimtypeSint8      = 16  'Signed 8-bit integer 
Const wbemCimtypeUint8      = 17  'Unsigned 8-bit integer 
Const wbemCimtypeUint16     = 18  'Unsigned 16-bit integer 
Const wbemCimtypeUint32     = 19  'Unsigned 32-bit integer 
Const wbemCimtypeSint64     = 20  'Signed 64-bit integer  
Const wbemCimtypeUint64     = 21  'Unsigned 64-bit integer 
Const wbemCimtypeDatetime   = 101 'Date/time value 
Const wbemCimtypeReference  = 102 'Reference to a CIM object 
Const wbemCimtypeChar16     = 103 '16-bit character 

Const ErrAction_None = 0
Const ErrAction_Trace = 1
Const ErrAction_ThrowError = 16
Const ErrAction_Abort = 32
Const ErrAction_ThrowErrorAndAbort = 48

Dim g_oUtil
Set g_oUtil = New Util

Call g_oUtil.SetDebugLevel(g_oUtil.DBG_NONE)

Dim g_oClusterUtil
Set g_oClusterUtil = new ClusterUtil

Dim oArgs
Set oArgs = WScript.Arguments

If oArgs.Count <> 8 Then
    g_oUtil.LogMessage _
            g_oUtil.DBG_ERROR, _
            "Need to provide arguments"

    Wscript.Quit -1
End If

'==========================================================================
' Initialize the arguments in VBScript
'==========================================================================

Dim SourceId, ManagedEntityId, HealthServiceName, NetBiosName

SourceId = oArgs(0) ' this is always going to be same GUID to allow for multiple discoveries do updates at the same time
ManagedEntityId = oArgs(1)
HealthServiceName = oArgs(2)
NetBiosName = oArgs(3)

Dim discoverUnusedNetworks
discoverUnusedNetworks = false

Dim networkContainsInterfaceGuid
networkContainsInterfaceGuid = oArgs(4)

Dim networkInterfaceTypeGuid
networkInterfaceTypeGuid = oArgs(5)
Dim networkInterfacePropClusterNameGuid
networkInterfacePropClusterNameGuid = oArgs(6)
Dim networkInterfacePropNameGuid
networkInterfacePropNameGuid = oArgs(7)

g_oUtil.LogMessage _
        g_oUtil.DBG_TRACE, _
        "SourceId : " & SourceId  
g_oUtil.LogMessage _
        g_oUtil.DBG_TRACE, _
        "ManagedEntityId : " & ManagedEntityId  
g_oUtil.LogMessage _
        g_oUtil.DBG_TRACE, _
        "HealthServiceName : " & HealthServiceName  

'==========================================================================
' Main
'==========================================================================

Dim oAPI
Set oAPI = CreateObject("MOM.ScriptAPI")
If oAPI is Nothing Then
    g_oUtil.LogMessage _
            g_oUtil.DBG_ERROR, _
            "Failed to get Discovery API. MOM v3 must be installed to execute this script"

    if 0 <> Err.number then
        g_oUtil.LogMessage _
                g_oUtil.DBG_ERROR, _
                "Failed with error " & Err.number & " - " & Err.Description
    end if
End If

Call DiscoverInstances()

'==========================================================================
' FUNCTIONS
'==========================================================================

Sub ThrowEmptyDiscoveryData()
    Dim oDiscoveryDataTmp
    set oDiscoveryDataTmp = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
    Call oAPI.Return(oDiscoveryDataTmp)
End Sub

Sub DiscoverInstances()

    g_oUtil.LogMessage _
            g_oUtil.DBG_TRACE, _
            "Started dicovery at machine local time: " & CStr(Time) 

    Dim oDiscoveryData
    Set oDiscoveryData = oAPI.CreateDiscoveryData ( _
            0, _
            SourceId, _
            ManagedEntityId _
        )

    If oDiscoveryData is Nothing Then
        g_oUtil.LogMessage _
                g_oUtil.DBG_ERROR, _
                "Failed to get Discovery Data Object. MOM v3 must be installed to execute this script"

        if 0 <> Err.number then
            g_oUtil.LogMessage _
                    g_oUtil.DBG_ERROR, _
                    "Failed with error " & Err.number & " - " & Err.Description
        end if

        Exit Sub
    End If

    Dim winCluster
    Set winCluster = New WinCluster

    Call winCluster.Discover ( oDiscoveryData )
    Call oAPI.Return(oDiscoveryData)

    g_oUtil.LogMessageNewLine _
            g_oUtil.DBG_TRACE, _
            "Finished dicovery at machine local time: " & CStr(Time) 

End Sub

'==========================================================================
' Class:        WinClusterObject
' Description:  base holding object and its properties
'==========================================================================
Class WinClusterObject

    '==========================================================================
    ' Discover instance
    '==========================================================================
    Public Function DiscoverInstance( _
            ByVal hostKey, _
            ByRef oObject, _
            ByVal discoveryClass, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for " & discoveryClass & "." 

        Dim oInstance
        Set oInstance = oDiscoveryData.CreateClassInstance( _
                discoveryClass _
            )

        With oInstance

            Dim name
            name = g_oClusterUtil.WMIGetProperty ( oObject, "Name", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )

            .AddProperty _
                    "$MPElement[Name='System!System.Entity']/DisplayName$", _
                    name

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ClusterName$", _
                    hostKey

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ObjectName$", _
                    Trim(name)

        End With

        Set DiscoverInstance = oInstance

    End Function

End Class ' WinClusterObject

'==========================================================================
' Class:        WinCluster
' Description:  holding cluster object and its properties
'==========================================================================
Class WinCluster

    Private oClusters

    '======================================================================
    ' Method:       Class_Initialize
    ' Description:  This is the constructor 
    ' Parameters:
    '======================================================================
    Private Sub Class_Initialize()
        Set oClusters = g_oClusterUtil.WMIGetInstances("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "MSCluster_Cluster")
    End Sub

    '==========================================================================
    ' Discover cluster classes
    '==========================================================================
    Public Sub Discover( _
            ByRef oDiscoveryData _
        )

        Dim oCluster
        For Each oCluster in oClusters
            Dim oClusterInstance
            Set oClusterInstance = oDiscoveryData.CreateClassInstance( _
                    "$MPElement[Name='Cluster!Microsoft.Windows.Cluster']$" _
                )

            With oClusterInstance
                .AddProperty _
                        "$MPElement[Name='Cluster!Microsoft.Windows.Cluster']/Name$", _
                        oCluster.Name
            End With

            ' need to make sure that cluster was discovered as it is used in some relationships
            oDiscoveryData.AddInstance(oClusterInstance)

            ' cluster node helpers
            Dim winClusterNode
            Set winClusterNode = new WinClusterNode

            ' nodes
            Dim oNodes
            Set oNodes = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_ClusterToNode where Antecedent = ""MSCluster_Cluster.Name=\""" & oCluster.Name & "\""""")

            Dim oNode
            For Each oNode in oNodes
                Dim oRealNode
                Set oRealNode = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oNode.Dependent)

                Dim oNodeInstance
                Set oNodeInstance = winClusterNode.DiscoverInstance ( _
                        oCluster.Name, _
                        oRealNode, _
                        oDiscoveryData _
                    )

                If Not oNodeInstance Is Nothing Then
                    winClusterNode.DiscoverClusterContainsRelationship _
                            oClusterInstance, _
                            oDiscoveryData
                End If
            Next

            ' networks
            Dim oNetworks
            Set oNetworks = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_ClusterToNetwork where GroupComponent = ""MSCluster_Cluster.Name=\""" & oCluster.Name & "\""""")

            Dim oNetwork
            For Each oNetwork in oNetworks
                Dim oRealNetwork
                Set oRealNetwork = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oNetwork.PartComponent)

                ' cluster network helpers
                Dim winClusterNetwork
                Set winClusterNetwork = new WinClusterNetwork

                Dim oNetworkInstance
                Set oNetworkInstance = winClusterNetwork.DiscoverInstance ( _
                        oCluster.Name, _
                        oRealNetwork, _
                        oDiscoveryData _
                    )

                If Not oNetworkInstance Is Nothing Then
                    winClusterNetwork.DiscoverClusterContainsRelationship _
                            oClusterInstance, _
                            oCluster.Name, _
                            oRealNetwork.Name, _
                            oDiscoveryData
                End If
            Next

            ' cluster group helpers
            Dim winClusterGroup
            Set winClusterGroup = new WinClusterGroup

            ' groups
            Dim oGroups
            Set oGroups = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_ClusterToResourceGroup where GroupComponent = ""MSCluster_Cluster.Name=\""" & oCluster.Name & "\""""")

            Dim oGroup
            For Each oGroup in oGroups
                Dim oRealGroup
                Set oRealGroup = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oGroup.PartComponent)

                Dim autoFailbackType 
                Dim description 
                Dim failbackWindowEnd
                Dim failbackWindowStart
                Dim failoverPeriod
                Dim failoverThreshold
                Dim persistentState

                autoFailbackType = g_oClusterUtil.WMIGetProperty ( oRealGroup, "AutoFailbackType", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
                description = g_oClusterUtil.WMIGetProperty ( oRealGroup, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
                failbackWindowEnd = g_oClusterUtil.WMIGetProperty ( oRealGroup, "FailbackWindowEnd", wbemCimtypeSint32, ErrAction_ThrowErrorAndAbort )
                failbackWindowStart = g_oClusterUtil.WMIGetProperty ( oRealGroup, "FailbackWindowStart", wbemCimtypeSint32, ErrAction_ThrowErrorAndAbort )
                failoverPeriod = g_oClusterUtil.WMIGetProperty ( oRealGroup, "FailoverPeriod", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
                failoverThreshold = g_oClusterUtil.WMIGetProperty ( oRealGroup, "FailoverThreshold", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
                persistentState = g_oClusterUtil.WMIGetProperty ( oRealGroup, "PersistentState", wbemCimtypeBoolean, ErrAction_ThrowErrorAndAbort )

                ' undefined is empty string
                If failbackWindowEnd = "-1" Then failbackWindowEnd = ""
                If failbackWindowStart = "-1" Then failbackWindowStart = ""

                Dim oGroupInstance
                Set oGroupInstance = winClusterGroup.DiscoverInstance ( _
                        oCluster.Name, _
                        oRealGroup, _
                        autoFailbackType, _
                        description, _
                        failbackWindowEnd, _
                        failbackWindowStart, _
                        failoverPeriod, _
                        failoverThreshold, _
                        persistentState, _
                        oDiscoveryData _
                    )

                'cluster contains groups
                If Not oGroupInstance Is Nothing Then
                    winClusterGroup.DiscoverClusterContainsRelationship _
                            oClusterInstance, _
                            oCluster.Name, _
                            Trim(oRealGroup.Name), _
                            oDiscoveryData
                End If

                Dim oHostedGroupInstance
                Set oHostedGroupInstance = winClusterGroup.DiscoverInstanceForHosted ( _
                        oCluster.Name, _
                        oRealGroup, _
                        autoFailbackType, _
                        description, _
                        failbackWindowEnd, _
                        failbackWindowStart, _
                        failoverPeriod, _
                        failoverThreshold, _
                        persistentState, _
                        oDiscoveryData _
                    )

                ' group contains hosted group
                winClusterGroup.DiscoverClusterGroupContainsRelationship _
                        oCluster.Name, _
                        Trim(oRealGroup.Name), _
                        oDiscoveryData

            Next

        Next

    End Sub

End Class ' WinCluster

'==========================================================================
' Class:        WinClusterNode
' Description:  holding cluster node and its properties
'==========================================================================
Class WinClusterNode

    '==========================================================================
    ' Discover instance
    '==========================================================================
    Public Function DiscoverInstance( _
            ByVal hostKey, _
            ByRef oObject, _
            ByRef oDiscoveryData _
        )

        '======================================================================
        ' only on same computer
        '======================================================================

        Dim name
        Dim description
        Dim buildNumber 
        Dim cSDVersion 
        Dim majorVersion 
        Dim minorVersion 
        Dim nodeHighestVersion 
        Dim nodeLowestVersion 

        name = g_oClusterUtil.WMIGetProperty ( oObject, "Name", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
        description = g_oClusterUtil.WMIGetProperty ( oObject, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
        buildNumber = g_oClusterUtil.WMIGetProperty ( oObject, "BuildNumber", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        cSDVersion = g_oClusterUtil.WMIGetProperty ( oObject, "CSDVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        majorVersion = g_oClusterUtil.WMIGetProperty ( oObject, "MajorVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        minorVersion = g_oClusterUtil.WMIGetProperty ( oObject, "MinorVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        nodeHighestVersion = g_oClusterUtil.WMIGetProperty ( oObject, "NodeHighestVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        nodeLowestVersion = g_oClusterUtil.WMIGetProperty ( oObject, "NodeLowestVersion", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )

        If StrComp ( LCase(NetBiosName) , LCase(oObject.Name) ) = 0 Then

            g_oUtil.LogMessage _
                    g_oUtil.DBG_TRACE, _ 
                    "Creating DiscoveryData packet for Microsoft.Windows.Cluster.Node." 

            Dim oInstance
            Set oInstance = oDiscoveryData.CreateClassInstance( _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']$" _
                )

            With oInstance

                .AddProperty _
                        "$MPElement[Name='System!System.Entity']/DisplayName$", _
                        name

                .AddProperty _
                        "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                        HealthServiceName

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/ClusterName$", _
                        hostKey

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/NodeName$", _
                        Trim(name)

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/Description$", _
                        description

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/BuildNumber$", _
                        buildNumber

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/CSDVersion$", _
                        cSDVersion

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/MajorVersion$", _
                        majorVersion

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/MinorVersion$", _
                        minorVersion

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/NodeHighestVersion$", _
                        nodeHighestVersion

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']/NodeLowestVersion$", _
                        nodeLowestVersion

            End With

            Call oDiscoveryData.AddInstance(oInstance)
            Set DiscoverInstance = oInstance

            Call DiscoverClusterNodeHostsNodeRoleRelationship ( _
                    hostKey, _
                    oObject, _
                    oDiscoveryData _
                )

            Exit Function

        End If

        Set DiscoverInstance = Nothing

    End Function

    '==========================================================================
    ' Discover node hostinging role relationship instance
    '==========================================================================
    Private Sub DiscoverClusterNodeHostsNodeRoleRelationship( _
            ByVal hostKey, _
            ByRef oObject, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for node hosting roles." 

        Dim oNodeRoleInstance
        Set oNodeRoleInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.NodeRole']$" _
            )

        With oNodeRoleInstance

            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                    HealthServiceName

        End With

        Dim oInstance
        Set oInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']$" _
            )

        With oInstance

            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                    HealthServiceName

        End With

        Dim oRelationshipInstance
        Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
                "$MPElement[Name='Windows!Microsoft.Windows.ComputerHostsComputerRole']$" _
            )

        oRelationshipInstance.Source = oInstance
        oRelationshipInstance.Target = oNodeRoleInstance

        Call oDiscoveryData.AddInstance(oRelationshipInstance)

        With oNodeRoleInstance

            .AddProperty _
                    "$MPElement[Name='System!System.Entity']/DisplayName$", _
                    oObject.Name

        End With

        Call oDiscoveryData.AddInstance(oNodeRoleInstance)

    End Sub

    '==========================================================================
    ' Discover cluster contains relationship instance
    '==========================================================================
    Public Sub DiscoverClusterContainsRelationship( _
            ByRef oClusterInstance, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for cluster contains nodes." 

        Dim oInstance
        Set oInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Node']$" _
            )

        With oInstance

            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                    HealthServiceName

        End With

        g_oClusterUtil.DiscoverClusterContainsRelationship _
                oClusterInstance, _
                oInstance, _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Node']$", _
                oDiscoveryData

    End Sub

End Class ' WinClusterNode

'==========================================================================
' Class:        WinClusterNetwork
' Description:  holding cluster network and its properties
'==========================================================================
Class WinClusterNetwork

    Private roleNone

    '======================================================================
    ' Method:       Class_Initialize
    ' Description:  This is the constructor 
    ' Parameters:
    '======================================================================
    Private Sub Class_Initialize()
        roleNone = False
    End Sub

    '==========================================================================
    ' Discover instance
    '==========================================================================
    Public Function DiscoverInstance( _
            ByVal hostKey, _
            ByRef oObject, _
            ByRef oDiscoveryData _
        )

        Dim clusterHelper
        Set clusterHelper = new WinClusterObject

        Dim oInstance
        Set oInstance = clusterHelper.DiscoverInstance ( _
                hostKey, _
                oObject, _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Network']$", _
                oDiscoveryData _
            )

        Dim address 
        Dim addressMask 
        Dim role 
        Dim description 

        address = g_oClusterUtil.WMIGetProperty ( oObject, "Address", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
        addressMask = g_oClusterUtil.WMIGetProperty ( oObject, "AddressMask", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
        role = g_oClusterUtil.WMIGetProperty ( oObject, "Role", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        description = g_oClusterUtil.WMIGetProperty ( oObject, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )

        If role = "0" Then
            roleNone = True
        End If

        With oInstance

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Network']/Address$", _
                    address

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Network']/AddressMask$", _
                    addressMask

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Network']/Description$", _
                    description

        End With

        Dim discoverNetwork
        discoverNetwork = True

        If discoverUnusedNetworks = False Then
            If roleNone = True Then
                discoverNetwork = False
            End If
        End If

        If discoverNetwork = True Then
            Call oDiscoveryData.AddInstance(oInstance)
            Set DiscoverInstance = oInstance

            Dim name
            name = oObject.Name

            '====================================================
            ' discover contains network interfaces
            '====================================================

            Dim oNetworkItfs
            Set oNetworkItfs = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_NetworkToNetworkInterface where GroupComponent = ""MSCluster_Network.Name=\""" & name & "\""""")

            Dim oNetworkItf
            For Each oNetworkItf in oNetworkItfs
                Dim oRealNetworkItf
                Set oRealNetworkItf = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oNetworkItf.PartComponent)

                Dim e
                Set e = New Error
                On Error Resume Next

                Dim winClusterNetworkInterface
                Set winClusterNetworkInterface = new WinClusterNetworkInterface

                e.Save
                On Error Goto 0

                If g_oClusterUtil.IsValidObject ( winClusterNetworkInterface ) = False Then
                    g_oUtil.ThrowScriptError "Unable to create network interface helper.", e
                End If

                Dim strs
                strs = Split ( oRealNetworkItf.DeviceID, " - ", -1, 1 )

                Dim baseOSItfName
                If StrComp ( LCase(strs(1)) , LCase(oRealNetworkItf.SystemName) ) = 0 Then
                    baseOSItfName = strs(0)
                Else
                    baseOSItfName = strs(1)
                End If

                g_oUtil.LogMessage _
                        g_oUtil.DBG_TRACE, _ 
                        "Network: " & name & " interface: " & baseOSItfName

                Call winClusterNetworkInterface.Initialize ( baseOSItfName )

                Dim oNetworkItfInstance
                Set oNetworkItfInstance = winClusterNetworkInterface.DiscoverInstance ( _
                        hostKey, _
                        baseOSItfName, _
                        oRealNetworkItf, _
                        oDiscoveryData _
                    )

                ' discover that network contains interfaces
                Call DiscoverContainsNetworkInterfacesRelationship ( _
                        hostKey, _
                        name, _
                        winClusterNetworkInterface.deviceID, _
                        oRealNetworkItf, _
                        oDiscoveryData _
                    )

            Next

        Else
            Set DiscoverInstance = Nothing
        End If
    End Function

    '==========================================================================
    ' Discover cluster containing network interfaces relationship instance
    '==========================================================================
    Private Sub DiscoverContainsNetworkInterfacesRelationship( _
            ByVal hostKey, _
            ByVal networkKey, _
            ByVal networkItfKey, _
            ByRef oRealNetworkItf, _
            ByRef oDiscoveryData _
        )

        If StrComp ( LCase(NetBiosName) , LCase(oRealNetworkItf.SystemName) ) = 0 Then

            g_oUtil.LogMessage _
                    g_oUtil.DBG_TRACE, _ 
                    "Creating DiscoveryData packet for cluster network contains network interfaces." 

            Dim oNetworkInstance
            Set oNetworkInstance = oDiscoveryData.CreateClassInstance( _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Network']$" _
                )

            With oNetworkInstance

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ClusterName$", _
                        hostKey

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ObjectName$", _
                        networkKey

            End With

            Dim oInstance
            Set oInstance = oDiscoveryData.CreateClassInstance( _
                    NetworkInterfaceTypeGuid _
                )

            With oInstance

                .AddProperty _
                        "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                        HealthServiceName

                .AddProperty _
                        "$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/DeviceID$", _
                        networkItfKey

            End With

            Dim oRelationshipInstance
            Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
                    NetworkContainsInterfaceGuid _
                )

            oRelationshipInstance.Source = oNetworkInstance
            oRelationshipInstance.Target = oInstance

            Call oDiscoveryData.AddInstance(oRelationshipInstance)

        End If

    End Sub

    '==========================================================================
    ' Discover cluster contains relationship instance
    '==========================================================================
    Public Sub DiscoverClusterContainsRelationship( _
            ByRef oClusterInstance, _
            ByVal hostKey, _
            ByVal networkKey, _
            ByRef oDiscoveryData _
        )

        If roleNone = False Then
            g_oUtil.LogMessage _
                    g_oUtil.DBG_TRACE, _ 
                    "Creating DiscoveryData packet for cluster contains network." 

            Dim oInstance
            Set oInstance = oDiscoveryData.CreateClassInstance( _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Network']$" _
                )

            With oInstance

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ClusterName$", _
                        hostKey

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ObjectName$", _
                        networkKey

            End With

            g_oClusterUtil.DiscoverClusterContainsRelationship _
                    oClusterInstance, _
                    oInstance, _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Network']$", _
                    oDiscoveryData
        End If
    End Sub

End Class ' WinClusterNetwork

'==========================================================================
' Class:        WinClusterNetworkInterface
' Description:  holding cluster network interface its properties
'==========================================================================
Class WinClusterNetworkInterface

    Public deviceID
    Public adapterType
    Public index
    Public manufacturer
    Public macAddress
    Public serviceName

    '======================================================================
    ' Method:       Initialize
    ' Description:  This is the constructor 
    ' Parameters:
    '======================================================================
    Public Sub Initialize( ByVal NetworkName )
        deviceID = ""
        adapterType = ""
        index = ""
        manufacturer = ""
        macAddress = ""
        serviceName = ""

        Dim WMISet, owObj, owObj2, oInstance, sDeviceID
        If discoverUnusedNetworks= False Then
            Set WMISet = g_oClusterUtil.WMIGetInstances("winmgmts:\\" + HealthServiceName + "\root\cimv2", "Win32_NetworkAdapter Where NetConnectionID = '" & NetworkName & "' And NetConnectionStatus <> 0")
        Else
            Set WMISet = g_oClusterUtil.WMIGetInstances("winmgmts:\\" + HealthServiceName + "\root\cimv2", "Win32_NetworkAdapter Where NetConnectionID = '" & NetworkName & "'")
        End If

        For Each owObj In WMISet
            deviceID = g_oClusterUtil.WMIGetProperty(owObj, "DeviceID", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
            adapterType = g_oClusterUtil.WMIGetProperty(owObj, "AdapterType", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
            index = g_oClusterUtil.WMIGetProperty(owObj, "Index", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
            manufacturer = g_oClusterUtil.WMIGetProperty(owObj, "Manufacturer", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
            macAddress = g_oClusterUtil.WMIGetProperty(owObj, "MACAddress", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
            serviceName = g_oClusterUtil.WMIGetProperty(owObj, "ServiceName", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
        Next
    End Sub

    '==========================================================================
    ' Discover instance
    '==========================================================================
    Public Function DiscoverInstance( _
            ByVal clusterKey, _
            ByVal networkItfKey, _
            ByRef oObject, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for " & networkInterfaceTypeGuid

        Dim oInstance
        Set oInstance = oDiscoveryData.CreateClassInstance( _
                networkInterfaceTypeGuid _
            )

        With oInstance

            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                    HealthServiceName

            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/DeviceID$", _
                    deviceID

            Dim adapter 
            Dim address 
            Dim description 
            Dim name 

            adapter = g_oClusterUtil.WMIGetProperty ( oObject, "Adapter", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
            address = g_oClusterUtil.WMIGetProperty ( oObject, "Address", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
            description = g_oClusterUtil.WMIGetProperty ( oObject, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
            name = g_oClusterUtil.WMIGetProperty ( oObject, "DeviceID", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )

            .AddProperty _
                    "$MPElement[Name='System!System.Entity']/DisplayName$", _
                    networkItfKey

            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Name$", _
                    adapter

            If description = "" Then
                .AddProperty _
                        "$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Description$", _
                        adapter
            Else
                .AddProperty _
                        "$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Description$", _
                        description
            End If

            .AddProperty _
                    "$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/IPAddress$", _
                    address

            .AddProperty _
                    "$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/AdapterType$", _
                    adapterType
            .AddProperty _
                    "$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/Index$", _
                    index
            .AddProperty _
                    "$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/Manufacturer$", _
                    manufacturer
            .AddProperty _
                    "$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/MACAddress$", _
                    macAddress
            .AddProperty _
                    "$MPElement[Name='Server!Microsoft.Windows.Server.NetworkAdapter']/ServiceName$", _
                    serviceName

            .AddProperty _
                    networkInterfacePropClusterNameGuid, _
                    clusterKey
            .AddProperty _
                    networkInterfacePropNameGuid, _
                    name

        End With

        Call oDiscoveryData.AddInstance(oInstance)
        Set DiscoverInstance = oInstance

    End Function

End Class ' WinClusterNetworkInterface

'========='==========================================================================
' Class:        WinClusterGroup
' Description:  holding group object and its properties
'==========================================================================
Class WinClusterGroup

    '==========================================================================
    ' Discover instance
    '==========================================================================
    Public Function DiscoverInstance( _
            ByVal hostKey, _
            ByRef oObject, _
            ByVal autoFailbackType, _
            ByVal description, _
            ByVal failbackWindowEnd, _
            ByVal failbackWindowStart, _
            ByVal failoverPeriod, _
            ByVal failoverThreshold, _
            ByVal persistentState, _
            ByRef oDiscoveryData _
        )

        ' instance

        Dim clusterHelper
        Set clusterHelper = new WinClusterObject

        Dim oInstance
        Set oInstance = clusterHelper.DiscoverInstance ( _
                hostKey, _
                oObject, _
                "$MPElement[Name='Microsoft.Windows.Cluster.Group.Fix']$", _
                oDiscoveryData _
            )

        With oInstance

            .AddProperty _
                    "$MPElement[Name='Microsoft.Windows.Cluster.Group.Fix']/OriginalGroupName$", _
                    oObject.Name
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/AutoFailbackType$", _
                    autoFailbackType
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/Description$", _
                    description
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/FailbackWindowEnd$", _
                    failbackWindowEnd
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/FailbackWindowStart$", _
                    failbackWindowStart
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/FailoverPeriod$", _
                    failoverPeriod
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/FailoverThreshold$", _
                    failoverThreshold
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/PersistentState$", _
                    persistentState

            Dim e
            Set e = New Error
            On Error Resume Next

            Dim oService
            Set oService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & HealthServiceName & "\root\mscluster")

            e.Save
            On Error Goto 0
            If IsEmpty(oService) Or e.Number <> 0 Then
                g_oUtil.ThrowScriptError "Fail to connect to WMI.", e
            End If
            On Error Resume Next

            Dim oActiveNode
            Set oActiveNode = oService.ExecQuery("select * from MSCluster_NodeToActiveGroup where PartComponent = ""MSCluster_ResourceGroup.Name=\""" & g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oObject.Name)) & "\""""")

            e.Save
            On Error Goto 0
            If IsEmpty(oActiveNode) Or e.Number <> 0 Then
                g_oUtil.ThrowScriptError "The Query for active node returned an invalid result set.  Please check to see if this is a valid WMI Query.", e
            End If
            On Error Resume Next

            If Not oActiveNode Is Null Then
                Dim oNode
                For Each oNode in oActiveNode

                    Dim oActive
                    Set oActive = oService.Get(oNode.GroupComponent)

                    e.Save
                    On Error Goto 0
                    If IsNull(oActive) Then
                        g_oUtil.ThrowScriptError "Do not get a Node.  Please check to see if this is a valid WMI Query.", e
                    End If
                    On Error Resume Next

                    .AddProperty _
                            "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$", _
                            oActive.Name

                Next
            Else
                ' need to use current node

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$", _
                        NetBiosName

            End If

        End With

        Call oDiscoveryData.AddInstance(oInstance)
        Set DiscoverInstance = oInstance

        '====================================================
        ' discover resources
        '====================================================

        Dim oResources
        Set oResources = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_ResourceGroupToResource where GroupComponent = ""MSCluster_ResourceGroup.Name=\""" & g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oObject.Name)) & "\""""")

        Dim oResource
        For Each oResource in oResources
            Dim oRealResource
            Set oRealResource = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oResource.PartComponent)

            Dim winClusterResource
            Set winClusterResource = new WinClusterResource

            Dim oResourceInstance
            Set oResourceInstance = winClusterResource.DiscoverInstance ( _
                    hostKey, _
                    Trim(oObject.Name), _
                    oRealResource, _
                    oDiscoveryData _
                )

            ' discover that group hosts this resource
            Call winClusterResource.DiscoverClusterGroupHostsResourcesRelationship ( _
                    hostKey, _
                    Trim(oObject.Name), _
                    Trim(oRealResource.Name), _
                    oDiscoveryData _
                )

        Next
    End Function

    '==========================================================================
    ' Discover cluster contains relationship instance
    '==========================================================================
    Public Sub DiscoverClusterContainsRelationship( _
            ByRef oClusterInstance, _
            ByVal hostKey, _
            ByVal groupKey, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for cluster contains groups." 

        Dim oInstance
        Set oInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']$" _
            )

        With oInstance

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ClusterName$", _
                        hostKey
                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ObjectName$", _
                        Trim(groupKey)

        End With

        g_oClusterUtil.DiscoverClusterContainsRelationship _
                oClusterInstance, _
                oInstance, _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Group']$", _
                oDiscoveryData

    End Sub

    '==========================================================================
    ' Discover cluster node hosted group
    '==========================================================================
    Public Function DiscoverInstanceForHosted( _
            ByVal hostKey, _
            ByRef oObject, _
            ByVal autoFailbackType, _
            ByVal description, _
            ByVal failbackWindowEnd, _
            ByVal failbackWindowStart, _
            ByVal failoverPeriod, _
            ByVal failoverThreshold, _
            ByVal persistentState, _
            ByRef oDiscoveryData _
        )

        ' instance

        Dim oHostedGroupInstance
        Set oHostedGroupInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']$" _
            )

        oHostedGroupInstance.AddProperty _
                "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                HealthServiceName

        oHostedGroupInstance.AddProperty _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
                hostKey

        oHostedGroupInstance.AddProperty _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
                NetBiosName

        oHostedGroupInstance.AddProperty _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
                Trim(oObject.Name)

        oHostedGroupInstance.AddProperty _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/EscapedGroupName$", _
                g_oClusterUtil.EscapeString(oObject.Name)

        With oHostedGroupInstance

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/AutoFailbackType$", _
                    autoFailbackType
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/Description$", _
                    description
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/FailbackWindowEnd$", _
                    failbackWindowEnd
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/FailbackWindowStart$", _
                    failbackWindowStart
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/FailoverPeriod$", _
                    failoverPeriod
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/FailoverThreshold$", _
                    failoverThreshold
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/PersistentState$", _
                    persistentState

        End With

        Call oDiscoveryData.AddInstance(oHostedGroupInstance)

        Set DiscoverInstanceForHosted = oHostedGroupInstance

    End Function

    '==========================================================================
    ' Discover cluster contains relationship instance
    '==========================================================================
    Public Sub DiscoverClusterGroupContainsRelationship( _
            ByVal hostKey, _
            ByVal groupKey, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for cluster group contains hosted groups." 

        Dim oInstance
        Set oInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group']$" _
            )

        With oInstance

                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ClusterName$", _
                        hostKey
                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Component']/ObjectName$", _
                        Trim(groupKey)

        End With

        Dim oHostedInstance
        Set oHostedInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']$" _
            )

        With oHostedInstance

                .AddProperty _
                        "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                        HealthServiceName
                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
                        hostKey
                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
                        NetBiosName
                .AddProperty _
                        "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
                        groupKey

        End With

            Dim oRelationshipInstance
            Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Group.Contains.Microsoft.Windows.Cluster.HostedGroup']$" _
                )

            oRelationshipInstance.Source = oInstance
            oRelationshipInstance.Target = oHostedInstance

            Call oDiscoveryData.AddInstance(oRelationshipInstance)

    End Sub

End Class ' WinClusterGroup

'==========================================================================
' Class:        WinClusterResource
' Description:  holding cluster resource extension and its properties
'==========================================================================
Class WinClusterResource

    '==========================================================================
    ' Discover instance
    '==========================================================================
    Public Function DiscoverInstance( _
            ByVal clusterKey, _
            ByVal groupKey, _
            ByRef oObject, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for Microsoft.Windows.Cluster.Resource." 

        Dim name
        Dim typeName
        Dim description
        Dim isAlivePollInterval
        Dim LooksAlivePollInterval
        Dim pendingTimeout
        Dim persistentState
        Dim restartAction
        Dim restartPeriod
        Dim restartThreshold
        Dim retryPeriodOnFailure
        Dim separateMonitor

        name = g_oClusterUtil.WMIGetProperty ( oObject, "Name", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
        typeName = g_oClusterUtil.WMIGetProperty ( oObject, "Type", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
        description = g_oClusterUtil.WMIGetProperty ( oObject, "Description", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
        isAlivePollInterval = g_oClusterUtil.WMIGetProperty ( oObject, "IsAlivePollInterval", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        looksAlivePollInterval = g_oClusterUtil.WMIGetProperty ( oObject, "LooksAlivePollInterval", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        pendingTimeout = g_oClusterUtil.WMIGetProperty ( oObject, "PendingTimeout", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        persistentState = g_oClusterUtil.WMIGetProperty ( oObject, "PersistentState", wbemCimtypeBoolean, ErrAction_ThrowErrorAndAbort )
        restartAction = g_oClusterUtil.WMIGetProperty ( oObject, "RestartAction", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        restartPeriod = g_oClusterUtil.WMIGetProperty ( oObject, "RestartPeriod", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        restartThreshold = g_oClusterUtil.WMIGetProperty ( oObject, "RestartThreshold", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        retryPeriodOnFailure = g_oClusterUtil.WMIGetProperty ( oObject, "RetryPeriodOnFailure", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
        separateMonitor = g_oClusterUtil.WMIGetProperty ( oObject, "SeparateMonitor", wbemCimtypeBoolean, ErrAction_ThrowErrorAndAbort )

        Dim oInstance
        Set oInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']$" _
            )

        With oInstance

            .AddProperty _
                    "$MPElement[Name='System!System.Entity']/DisplayName$", _
                    name

            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                    HealthServiceName

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
                    clusterKey

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
                    NetBiosName

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
                    groupKey

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/ResourceName$", _
                    Trim(name)

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/EscapedResourceName$", _
                    g_oClusterUtil.EscapeString(name)

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/ResourceTypeName$", _
                    typeName

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/Description$", _
                    description
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/IsAlivePollInterval$", _
                    isAlivePollInterval
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/LooksAlivePollInterval$", _
                    looksAlivePollInterval
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/PendingTimeout$", _
                    pendingTimeout
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/PersistentState$", _
                    persistentState
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/RestartAction$", _
                    restartAction
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/RestartPeriod$", _
                    restartPeriod
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/RestartThreshold$", _
                    restartThreshold
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/RetryPeriodOnFailure$", _
                    retryPeriodOnFailure
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/SeparateMonitor$", _
                    separateMonitor

        End With

        Call oDiscoveryData.AddInstance(oInstance)

        Set DiscoverInstance = oInstance

    End Function

    '==========================================================================
    ' Discover group hostinging resources relationship instance
    '==========================================================================
    Public Sub DiscoverClusterGroupHostsResourcesRelationship( _
            ByVal hostKey, _
            ByVal groupKey, _
            ByVal resKey, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for group containing resources.." 

        Dim oInstance
        Set oInstance = oDiscoveryData.CreateClassInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']$" _
            )

        With oInstance
            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                    HealthServiceName
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
                    hostKey
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
                    NetBiosName
            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
                    groupKey
        End With

        Dim oClusterResourceInstance
        Set oClusterResourceInstance = oDiscoveryData.CreateClassInstance( _
            "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']$" _
        )

        With oClusterResourceInstance


            .AddProperty _
                    "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
                    HealthServiceName

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
                    hostKey

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
                    NetBiosName

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
                    groupKey

            .AddProperty _
                    "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.Resource']/ResourceName$", _
                    resKey

        End With

        Dim oRelationshipInstance
        Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
                "$MPElement[Name='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup.Hosts.Microsoft.Windows.Cluster.Resource']$" _
            )

        oRelationshipInstance.Source = oInstance
        oRelationshipInstance.Target = oClusterResourceInstance

        Call oDiscoveryData.AddInstance(oRelationshipInstance)

    End Sub

End Class ' WinClusterResource

'==========================================================================
' Description:  HELPERS
'==========================================================================

Class Error
  Public Description
  Public Number
  Public Source

  Sub Class_Initialize()
    Number = 0
  End Sub

  Sub Save
    Description = Err.Description
    Number = Err.Number
    Source = Err.Source
    Err.Clear
  End Sub

  Sub Raise(strDescription)
    Err.Raise Number, Source, strDescription & GetErrorString(Number, Description)
  End Sub
End Class

'==========================================================================
' Class:        ClusterUtil
' Description:  Utility methods for clustering
'==========================================================================
Class ClusterUtil

    '**********************************************************************
    Public Function EscapeString(ByVal sText)
        Const METACHARACTERS = """\"
        Dim sResult
        Dim i
        For i = 1 To Len(sText)
            Dim sCurrentChar
            sCurrentChar = Mid(sText, i, 1)
            If InStr(METACHARACTERS, sCurrentChar) <> 0 Then
                sResult = sResult & "\"
            End If
            sResult = sResult & sCurrentChar         
        Next
        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _
                "ESCAPEd string: " & sResult
        EscapeString = sResult
    End Function

    '**********************************************************************
    Function WMIExecQuery(ByVal sNamespace, ByVal sQuery)

        Dim oWMI, oQuery, nInstanceCount
        Dim e
        Set e = New Error
        On Error Resume Next
        Set oWMI = GetObject(sNamespace)
        e.Save
        On Error Goto 0
        If IsEmpty(oWMI) Then
            g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'.  Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
        End If

        On Error Resume Next
        Set oQuery = oWMI.ExecQuery(sQuery)
        e.Save
        On Error Goto 0
        If IsEmpty(oQuery) Or e.Number <> 0 Then
            g_oUtil.ThrowScriptError "The Query '" & sQuery & "' returned an invalid result set.  Please check to see if this is a valid WMI Query.", e
        End If

        'Determine if we queried a valid WMI class - Count will return 0 or empty
        On Error Resume Next
        nInstanceCount = oQuery.Count
        e.Save
        On Error Goto 0
        If e.Number <> 0 Then
            g_oUtil.ThrowScriptError "The Query '" & sQuery & "' did not return any valid instances.  Please check to see if this is a valid WMI Query.", e
        End If

        Set WMIExecQuery = oQuery

    End Function

    '**********************************************************************
    Function WMIGetInstances(ByVal sNamespace, ByVal sInstance)

        Dim oWMI, oInstance, nInstanceCount
        Dim e
        Set e = New Error
        On Error Resume Next
        Set oWMI = GetObject(sNamespace)
        e.Save
        On Error Goto 0
        If IsEmpty(oWMI) Then
            g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'.  Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
        End If

        On Error Resume Next
        Set oInstance = oWMI.InstancesOf(sInstance)
        e.Save
        On Error Goto 0
        If IsEmpty(oInstance) Or e.Number <> 0 Then
            g_oUtil.ThrowScriptError "The class name '" & sInstance & "' returned no instances.  Please check to see if this is a valid WMI class name.", e
        End If

        'Determine if we queried a valid WMI class - Count will return 0 or empty

        On Error Resume Next
        nInstanceCount = oInstance.Count
        e.Save
        On Error Goto 0
        If e.Number <> 0 Then
            g_oUtil.ThrowScriptError "The class name '" & sInstance & "' did not return any valid instances.  Please check to see if this is a valid WMI class name.", e
        End If

        Set WMIGetInstances = oInstance

    End Function

    '**********************************************************************
    Function WMIGetInstance(ByVal sNamespace, ByVal sInstancePath)

        Dim oWMI, oInstance, nInstanceCount
        Dim e
        Set e = New Error
        On Error Resume Next
        Set oWMI = GetObject(sNamespace)
        e.Save
        On Error Goto 0
        If IsEmpty(oWMI) Then
            g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'.  Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
        End If

        On Error Resume Next
        Set oInstance = oWMI.Get(sInstancePath)
        e.Save
        On Error Goto 0
        If IsNull(oInstance) Then
            g_oUtil.ThrowScriptError "The class name '" & sInstancePath & "' returned no instances.  Please check to see if this is a valid WMI class name.", e
        End If

        Set WMIGetInstance = oInstance

    End Function

    '**********************************************************************
    Function WMIGetProperty(oWmi, sPropName, nCIMType, ErrAction)
        Dim sValue, oWmiProp

        If Not IsValidObject(oWmi) Then
            If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
                g_oUtil.ThrowScriptErrorNoAbort "Accessing property on invalid WMI object.", Err

            If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
                g_oUtil.Quit
            End If

            WMIGetProperty = ""
            Exit Function
        End If

        On Error Resume Next
        Set oWmiProp = oWmi.Properties_.Item(sPropName)
        If Err.Number <> 0 Then
            If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
                g_oUtil.ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" & sPropName & "'.", Err

            If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
                g_oUtil.Quit
            End If

        End If
        On Error Goto 0
        
        If IsValidObject(oWmiProp) Then
            sValue = oWmiProp.Value

            If IsNull(sValue) Then
                '
                ' If value is null, return blank to avoid any issues
                '
                WMIGetProperty = ""

            Else

                Select Case (nCIMType)
                    Case wbemCimtypeString:
                        If Not oWmiProp.IsArray Then
                            WMIGetProperty = CStr(sValue)
                        Else
                            WMIGetProperty = Join(sValue, ", ")
                        End If
                    Case wbemCimtypeSint16, wbemCimtypeSint32, wbemCimtypeReal32, wbemCimtypeReal64, wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeUint16, wbemCimtypeUint32, wbemCimtypeSint64, wbemCimtypeUint64:
                        If Not oWmiProp.IsArray Then
                            WMIGetProperty = Trim(CStr(sValue))
                        Else
                            WMIGetProperty = Join(sValue, ", ")
                        End If
                    Case wbemCimtypeBoolean:
                        If sValue = 1 Or UCase(sValue) = "TRUE" Then
                            WMIGetProperty = "True"
                        Else
                            WMIGetProperty = "False"
                        End If	
                    Case wbemCimtypeDatetime:

                        Dim sTmpStrDate
                        '
                        ' First attempt to convert the whole wmi date string
                        '
                        sTmpStrDate = Mid(sValue, 5, 2) & "/" & _
                                Mid(sValue, 7, 2) & "/" & _
                                Left(sValue, 4) & " " & _
                                Mid (sValue, 9, 2) & ":" & _
                                Mid(sValue, 11, 2) & ":" & _
                                Mid(sValue, 13, 2)
                        If IsDate(sTmpStrDate) Then
                            WMIGetProperty = CDate(sTmpStrDate)
                        Else

                            '
                            ' Second, attempt just to convert the YYYYMMDD 
                            '
                            sTmpStrDate = Mid(sValue, 5, 2) & "/" & _
                                    Mid(sValue, 7, 2) & "/" & _
                                    Left(sValue, 4)
                            If IsDate(sTmpStrDate) Then
                                WMIGetProperty = CDate(sTmpStrDate)
                            Else
                                '
                                ' Nothing works - return passed in string 
                                '
                                WMIGetProperty = sValue
                            End If
                        End If
                    Case Else:
                        WMIGetProperty = ""
                End Select
            End If
        Else

            If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
                g_oUtil.ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" & sPropName & "'.", Err

            If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
                g_oUtil.Quit
            End If

            WMIGetProperty = ""

        End If

        If (ErrAction And ErrAction_Trace) = ErrAction_Trace Then _
            WScript.Echo "  + " & sPropName & " :: '" & WMIGetProperty & "'"

    End Function

    '**********************************************************************
    Public Function IsValidObject(ByVal oObject)
        IsValidObject = False
        If IsObject(oObject) Then
            If Not oObject Is Nothing Then
                IsValidObject = True
            End If
        End If
    End Function	

    '==========================================================================
    ' Discover cluster contains relationship instance
    '==========================================================================
    Public Sub DiscoverClusterContainsRelationship( _
            ByRef oSourceInstance, _
            ByRef oTargetInstance, _
            ByVal discoveryRelationshipClass, _
            ByRef oDiscoveryData _
        )

        g_oUtil.LogMessage _
                g_oUtil.DBG_TRACE, _ 
                "Creating DiscoveryData packet for cluster contains objects." 

        Dim oRelationshipInstance
        Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
                discoveryRelationshipClass _
            )

        oRelationshipInstance.Source = oSourceInstance
        oRelationshipInstance.Target = oTargetInstance

        Call oDiscoveryData.AddInstance(oRelationshipInstance)

    End Sub

End Class 'ClusterUtil

'==========================================================================
' Class:        Util
' Description:  Utility methods for logging
'==========================================================================
Class Util

    '**********************************************************************
    Public Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
        On Error Resume Next
        LogMessage _
                DBG_ERROR, _
                sMessage & vbCrLf & oErr.Description

        oAPI.LogScriptEvent "DiscoverClustering.vbs", 7001, 1, sMessage & " " & oErr.Description
    End Function

    '**********************************************************************
    Public Function ThrowScriptError(Byval sMessage, ByVal oErr)
        On Error Resume Next
        ThrowScriptErrorNoAbort sMessage, oErr
        Quit
    End Function

    Public Function Quit
        LogMessage _
              DBG_ERROR, _
              "Terminated on error!"

        Wscript.Quit -1
    End Function

    ' Used to say to LogMessage when/how to print the message.
    Public DBG_NONE
    Public DBG_ERROR 
    Public DBG_WARNING 
    Public DBG_TRACE

    'Internal Debug Level
    Private m_nDebugLevel   

    '======================================================================
    ' Method:       Class_Initialize
    ' Description:  This is the constructor 
    ' Parameters:
    '======================================================================
    Private Sub Class_Initialize()
        ' Initialize Debug level constants
        DBG_TRACE = 1
        DBG_WARNING = 2
        DBG_ERROR = 3
        DBG_NONE = 4

        'by default only errors are logged
        m_nDebugLevel = DBG_ERROR
        
    End Sub

    '======================================================================
    ' Method:       GetCurrentLevel
    ' Description:  retrieve current logging level.
    ' Parameters:
    '======================================================================
    Public Function GetCurrentLevel()
            GetCurrentLevel = m_nDebugLevel
    End Function

    '======================================================================
    ' Method:       SetDebugLevel
    ' Description:  To change the debugging output level of information 
    '               generated by this utility.
    ' Parameters:
    '               nLevel - DBG_NONE, DBG_TRACE, DBG_WARNING or DBG_ERROR
    '======================================================================
    Public Sub SetDebugLevel(ByVal nLevel)
            m_nDebugLevel = nLevel
    End Sub

    '======================================================================
    ' Method:       LogMessage
    ' Description:  Log a debug message to ScriptContext
    ' Parameters:
    '               nLevel      - Debug level for the message that
    '                             we're logging. 
    '               strMessage  - The message to write to the trace.
    '======================================================================
    Public Sub LogMessage( _
            ByVal nLevel, _
            ByVal strMessage _
        )
        If (nLevel >= GetCurrentLevel()) Then
            if (nLevel = DBG_ERROR) Then
                WScript.Echo "[Error]: " & strMessage
            ElseIf (nLevel = DBG_WARNING) Then
                WScript.Echo "[Warning]: " & strMessage
            ElseIf (nLevel = DBG_TRACE) Then
                WScript.Echo "[Trace]: " & strMessage
            End If
        End If
    End Sub
    Public Sub LogMessageNewLine( _
            ByVal nLevel, _
            ByVal strMessage _
        )
        If (nLevel >= GetCurrentLevel()) Then
            if (nLevel = DBG_ERROR) Then
                WScript.Echo vbCrLf & "[Error]: " & strMessage
            ElseIf (nLevel = DBG_WARNING) Then
                WScript.Echo vbCrLf & "[Warning]: " & strMessage
            ElseIf (nLevel = DBG_TRACE) Then
                WScript.Echo vbCrLf & "[Trace]: " & strMessage
            End If
        End If
    End Sub

End Class ' Util
]]>
                </ScriptBody>
                <TimeoutSeconds>300</TimeoutSeconds>
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="Script" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.Discovery.Data</OutputType>
        <InputType>System!System.BaseData</InputType>
      </ProbeActionModuleType>
      <WriteActionModuleType ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Action" Accessibility="Internal" RunAs="Cluster!Microsoft.Windows.Cluster.PrivilegedAccount" Batching="false">
        <Configuration>
          <xsd:element minOccurs="1" name="NodeName" type="xsd:string" />
          <xsd:element minOccurs="1" name="GroupName" type="xsd:string" />
          <xsd:element minOccurs="1" name="MethodName" type="xsd:string" />
        </Configuration>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <WriteAction ID="WA" TypeID="System!System.CommandExecuter">
                <ApplicationName />
                <WorkingDirectory />
                <CommandLine>cscript QFEClusterGroupMethod.vbs "$Config/NodeName$" "$Config/GroupName$" "$Config/MethodName$"</CommandLine>
                <TimeoutSeconds>300</TimeoutSeconds>
                <RequireOutput>true</RequireOutput>
                <Files>
                  <File>
                    <Name>QFEClusterGroupMethod.vbs</Name>
                    <Contents>
                      <![CDATA[
Option Explicit

Dim g_oUtil
Set g_oUtil = New Util

Call g_oUtil.SetDebugLevel(g_oUtil.DBG_NONE)

Dim g_oClusterUtil
Set g_oClusterUtil = new ClusterUtil

Dim oArgs
Set oArgs = WScript.Arguments

If oArgs.Count < 3 Then
    g_oUtil.LogMessage _
            g_oUtil.DBG_ERROR, _
            "Need to provide arguments"

    Wscript.Quit -1
End If

'==========================================================================
' Initialize the arguments in VBScript
'==========================================================================

Dim NodeName
NodeName = oArgs(0)

Dim GroupName
GroupName = oArgs(1)

Dim MethodName
MethodName = oArgs(2)

'==========================================================================
' Main
'==========================================================================

Call Main()

'==========================================================================
' FUNCTIONS
'==========================================================================

Sub Main()

    g_oUtil.LogMessage _
            g_oUtil.DBG_TRACE, _
            "Started at machine local time: " & CStr(Time) 

    Dim e
    Set e = New Error
    On Error Resume Next

    Dim Service
    Set Service = GetObject("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\" & NodeName & "\root\mscluster")

    e.Save
    On Error Goto 0
    If IsEmpty(Service) Or e.Number <> 0 Then
        g_oUtil.ThrowScriptError "Unable to connect.", e
    End If
    On Error Resume Next

    Dim oGroup
    Set oGroup = Service.ExecQuery("select * from MSCluster_ResourceGroup where Name = """ & g_oClusterUtil.EscapeString(GroupName) & """")

    e.Save
    On Error Goto 0
    If IsEmpty(oGroup) Or e.Number <> 0 Then
        g_oUtil.ThrowScriptError "The Query returned an invalid result set.  Please check to see if this is a valid WMI Query.", e
    End If
    On Error Resume Next

    Dim oRealGroup
    For Each oRealGroup in oGroup

        Select Case MethodName

            Case "Delete"   Call DeleteGroup(Service, oRealGroup)
            Case "Move"     Call MoveToNextNode(Service, oRealGroup)
            Case "Online"   oRealGroup.BringOnline
            Case "Offline"  oRealGroup.TakeOffline

            Case Else g_oUtil.LogMessage _
                        g_oUtil.DBG_ERROR, _
                        "Unrecognized method " & MethodName & " used"

        End Select

    Next

    g_oUtil.LogMessageNewLine _
            g_oUtil.DBG_TRACE, _
            "Finished at machine local time: " & CStr(Time) 

End Sub

Sub DeleteGroup ( _
        ByRef oService, _
        ByRef oGroup _
    )

    Dim e
    Set e = New Error
    On Error Resume Next

    Dim DoLoop
    DoLoop = True

    While DoLoop
        Dim oResources
        Set oResources = oService.ExecQuery("select * from MSCluster_ResourceGroupToResource where GroupComponent = ""MSCluster_ResourceGroup.Name=\""" & g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oGroup.Name))) & "\""""")

        e.Save
        On Error Goto 0
        If e.Number <> 0 Then
            g_oUtil.ThrowScriptError "The Query for resources returned an error.  Please check to see if this is a valid WMI Query.", e
        End If
        On Error Resume Next

        If IsEmpty(oResources) Or oResources.Count = 0 Then
            g_oUtil.LogMessage _
                    g_oUtil.DBG_TRACE, _
                    "No more resources in group " & oGroup.Name

            DoLoop = False
        Else

            g_oUtil.LogMessage _
                    g_oUtil.DBG_TRACE, _
                    oResources.Count & " resources in group " & oGroup.Name

            Dim oResource
            For Each oResource in oResources

                Dim oRes
                Set oRes = oService.Get(oResource.PartComponent)

                e.Save
                On Error Goto 0
                If IsNull(oRes) Then
                    Exit For
                End If
                If e.Number <> 0 Then
                    g_oUtil.ThrowScriptError "Did not get a resource.  Please check to see if this is a valid WMI Query.", e
                End If
                On Error Resume Next

                Dim oDepResources
                Set oDepResources = oService.ExecQuery("select * from MSCluster_ResourceToDependentResource where Dependent = ""MSCluster_Resource.Name=\""" & g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oRes.Name))) & "\""""")

                e.Save
                On Error Goto 0
                If e.Number <> 0 Then
                    g_oUtil.ThrowScriptError "The Query for dependent resources returned an error.  Please check to see if this is a valid WMI Query.", e
                End If
                On Error Resume Next

                If IsEmpty(oDepResources) Or oDepResources.Count = 0 Then
                    DeleteResource (oRes)
                End If

            Next

        End If

    Wend

    oGroup.DeleteGroup
    e.Save
    On Error Goto 0
    If e.Number <> 0 Then
        g_oUtil.ThrowScriptError "Unable to delete resource group.", e
    End If
    On Error Resume Next

End Sub

Sub DeleteResource (_
        ByRef oRes _
    )

    Dim e
    Set e = New Error
    On Error Resume Next

    If Not ( oRes.State = 4 ) Then
        oRes.TakeOffline 32,767
        e.Save
        On Error Goto 0
        If e.Number <> 0 Then
            g_oUtil.ThrowScriptError "Unable to take resource " & oRes.Name & " offline.", e
        End If
        On Error Resume Next
    End If

    oRes.DeleteResource
    e.Save
    On Error Goto 0
    If e.Number <> 0 Then
        g_oUtil.ThrowScriptError "Unable to delete resource " & oRes.Name & "." , e
    End If
    On Error Resume Next

End Sub

Sub MoveToNextNode ( _
        ByRef oService, _
        ByRef oGroup _
    )

    Dim e
    Set e = New Error
    On Error Resume Next

    Dim oActiveNode
    Set oActiveNode = oService.ExecQuery("select * from MSCluster_NodeToActiveGroup where PartComponent = ""MSCluster_ResourceGroup.Name=\""" & g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oGroup.Name))) & "\""""")

    e.Save
    On Error Goto 0
    If IsEmpty(oActiveNode) Or e.Number <> 0 Then
        g_oUtil.ThrowScriptError "The Query for active node returned an invalid result set.  Please check to see if this is a valid WMI Query.", e
    End If
    On Error Resume Next

    Dim newNodeName
    newNodeName = NodeName

    If oActiveNode.Count > 0 Then
        Dim oNode
        For Each oNode in oActiveNode

            Dim oActive
            Set oActive = oService.Get(oNode.GroupComponent)

            e.Save
            On Error Goto 0
            If IsNull(oActive) Then
                Exit For
            End If
            If e.Number <> 0 Then
                g_oUtil.ThrowScriptError "Did not get a Node.  Please check to see if this is a valid WMI Query.", e
            End If
            On Error Resume Next

            Dim oNodes
            Set oNodes = oService.ExecQuery("select * from MSCluster_Node where Name != '" & oActive.Name & "'")

            e.Save
            On Error Goto 0
            If IsEmpty(oNodes) Or e.Number <> 0 Then
                g_oUtil.ThrowScriptError "The Query for nodes returned an invalid result set.  Please check to see if this is a valid WMI Query.", e
            End If
            On Error Resume Next

            Dim oNextNode
            For Each oNextNode in oNodes

                newNodeName = oNextNode.Name

                e.Save
                On Error Goto 0
                If IsEmpty(oNodes) Or e.Number <> 0 Then
                    g_oUtil.ThrowScriptError "Get node name failed.", e
                End If
                On Error Resume Next

                Call oGroup.MoveToNewNode ( newNodeName, 32,767 )

                e.Save
                On Error Goto 0
                If IsEmpty(oNodes) Or e.Number <> 0 Then
                    g_oUtil.ThrowScriptError "Move to new node failed.", e
                End If
                On Error Resume Next

                Exit Sub
            Next

            Exit For
        Next
    End If

End Sub

'==========================================================================
' Description:  HELPERS
'==========================================================================

Class Error
  Public Description
  Public Number
  Public Source

  Sub Class_Initialize()
    Number = 0
  End Sub

  Sub Save
    Description = Err.Description
    Number = Err.Number
    Source = Err.Source
    Err.Clear
  End Sub

  Sub Raise(strDescription)
    Err.Raise Number, Source, strDescription & GetErrorString(Number, Description)
  End Sub
End Class

'==========================================================================
' Class:        ClusterUtil
' Description:  Utility methods for clustering
'==========================================================================
Class ClusterUtil

    '**********************************************************************
    Public Function EscapeString(ByVal sText)
        Const METACHARACTERS = """"
        Dim sResult
        Dim i
        For i = 1 To Len(sText)
            Dim sCurrentChar
            sCurrentChar = Mid(sText, i, 1)
            If InStr(METACHARACTERS, sCurrentChar) <> 0 Then
                sResult = sResult & "\"
            End If
            sResult = sResult & sCurrentChar         
        Next
        EscapeString = sResult
    End Function

End Class 'ClusterUtil

'==========================================================================
' Class:        Util
' Description:  Utility methods for logging
'==========================================================================
Class Util

    '**********************************************************************
    Public Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
        LogMessage _
                DBG_ERROR, _
                sMessage & vbCrLf & oErr.Description

        Set ThrowScriptErrorNoAbort = Nothing
    End Function

    '**********************************************************************
    Public Function ThrowScriptError(Byval sMessage, ByVal oErr)
        ThrowScriptErrorNoAbort sMessage, oErr
        Quit
        Set ThrowScriptError = Nothing
    End Function

    Public Function Quit
        LogMessage _
              DBG_ERROR, _
              "Terminated on error!"

        Wscript.Quit -1
    End Function

    ' Used to say to LogMessage when/how to print the message.
    Public DBG_NONE
    Public DBG_ERROR 
    Public DBG_WARNING 
    Public DBG_TRACE

    'Internal Debug Level
    Private m_nDebugLevel   

    '======================================================================
    ' Method:       Class_Initialize
    ' Description:  This is the constructor 
    ' Parameters:
    '======================================================================
    Private Sub Class_Initialize()
        ' Initialize Debug level constants
        DBG_TRACE = 1
        DBG_WARNING = 2
        DBG_ERROR = 3
        DBG_NONE = 4

        'by default only errors are logged
        m_nDebugLevel = DBG_ERROR
        
    End Sub

    '======================================================================
    ' Method:       GetCurrentLevel
    ' Description:  retrieve current logging level.
    ' Parameters:
    '======================================================================
    Public Function GetCurrentLevel()
            GetCurrentLevel = m_nDebugLevel
    End Function

    '======================================================================
    ' Method:       SetDebugLevel
    ' Description:  To change the debugging output level of information 
    '               generated by this utility.
    ' Parameters:
    '               nLevel - DBG_NONE, DBG_TRACE, DBG_WARNING or DBG_ERROR
    '======================================================================
    Public Sub SetDebugLevel(ByVal nLevel)
            m_nDebugLevel = nLevel
    End Sub

    '======================================================================
    ' Method:       LogMessage
    ' Description:  Log a debug message to ScriptContext
    ' Parameters:
    '               nLevel      - Debug level for the message that
    '                             we're logging. 
    '               strMessage  - The message to write to the trace.
    '======================================================================
    Public Sub LogMessage( _
            ByVal nLevel, _
            ByVal strMessage _
        )
        If (nLevel >= GetCurrentLevel()) Then
            if (nLevel = DBG_ERROR) Then
                WScript.Echo "[Error]: " & strMessage
            ElseIf (nLevel = DBG_WARNING) Then
                WScript.Echo "[Warning]: " & strMessage
            ElseIf (nLevel = DBG_TRACE) Then
                WScript.Echo "[Trace]: " & strMessage
            End If
        End If
    End Sub
    Public Sub LogMessageNewLine( _
            ByVal nLevel, _
            ByVal strMessage _
        )
        If (nLevel >= GetCurrentLevel()) Then
            if (nLevel = DBG_ERROR) Then
                WScript.Echo vbCrLf & "[Error]: " & strMessage
            ElseIf (nLevel = DBG_WARNING) Then
                WScript.Echo vbCrLf & "[Warning]: " & strMessage
            ElseIf (nLevel = DBG_TRACE) Then
                WScript.Echo vbCrLf & "[Trace]: " & strMessage
            End If
        End If
    End Sub

End Class ' Util
                        ]]>
                    </Contents>
                    <Unicode>false</Unicode>
                  </File>
                </Files>
              </WriteAction>
            </MemberModules>
            <Composition>
              <Node ID="WA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <InputType>System!System.BaseData</InputType>
      </WriteActionModuleType>
    </ModuleTypes>
  </TypeDefinitions>
  <Monitoring>
    <Discoveries>
      <Discovery ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Discovery" Enabled="true" Target="Clus2003Library!Microsoft.Windows.2003.Cluster.Monitoring.Service" ConfirmDelivery="false" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="Cluster!Microsoft.Windows.Cluster">
            <Property TypeID="Cluster!Microsoft.Windows.Cluster" PropertyID="Name" />
          </DiscoveryClass>
          <DiscoveryClass TypeID="ClusLibrary!Microsoft.Windows.Cluster.Network">
            <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Component" PropertyID="ClusterName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Component" PropertyID="ObjectName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Network" PropertyID="Address" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Network" PropertyID="AddressMask" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Network" PropertyID="Description" />
          </DiscoveryClass>
          <DiscoveryClass TypeID="Clus2003Library!Microsoft.Windows.2003.Cluster.NetworkInterface">
            <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
            <Property TypeID="Windows!Microsoft.Windows.LogicalDevice" PropertyID="DeviceID" />
            <Property TypeID="Windows!Microsoft.Windows.LogicalDevice" PropertyID="Name" />
            <Property TypeID="Windows!Microsoft.Windows.LogicalDevice" PropertyID="Description" />
            <Property TypeID="Clus2003Library!Microsoft.Windows.2003.Cluster.NetworkInterface" PropertyID="ClusterName" />
            <Property TypeID="Clus2003Library!Microsoft.Windows.2003.Cluster.NetworkInterface" PropertyID="NetworkInterfaceName" />
          </DiscoveryClass>
          <DiscoveryClass TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node">
            <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
            <Property TypeID="Windows!Microsoft.Windows.Computer" PropertyID="PrincipalName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="ClusterName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="NodeName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="Description" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="BuildNumber" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="CSDVersion" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="MajorVersion" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="MinorVersion" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="NodeHighestVersion" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Node" PropertyID="NodeLowestVersion" />
          </DiscoveryClass>
          <DiscoveryClass TypeID="Microsoft.Windows.Cluster.Group.Fix">
            <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Component" PropertyID="ClusterName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Component" PropertyID="ObjectName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Group" PropertyID="Description" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Group" PropertyID="AutoFailbackType" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Group" PropertyID="FailbackWindowEnd" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Group" PropertyID="FailbackWindowStart" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Group" PropertyID="FailoverPeriod" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Group" PropertyID="FailoverThreshold" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Group" PropertyID="PersistentState" />
            <Property TypeID="Microsoft.Windows.Cluster.Group.Fix" PropertyID="OriginalGroupName" />
          </DiscoveryClass>
          <DiscoveryClass TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup">
            <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
            <Property TypeID="Windows!Microsoft.Windows.Computer" PropertyID="PrincipalName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="ClusterName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="NodeName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="GroupName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="EscapedGroupName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="Description" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="AutoFailbackType" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="FailbackWindowEnd" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="FailbackWindowStart" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="FailoverPeriod" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="FailoverThreshold" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="PersistentState" />
          </DiscoveryClass>
          <DiscoveryClass TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource">
            <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
            <Property TypeID="Windows!Microsoft.Windows.Computer" PropertyID="PrincipalName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="ClusterName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="NodeName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" PropertyID="GroupName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="ResourceName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="EscapedResourceName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="ResourceTypeName" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="Description" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="IsAlivePollInterval" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="LooksAlivePollInterval" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="PendingTimeout" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="PersistentState" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="RestartAction" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="RestartPeriod" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="RestartThreshold" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="RetryPeriodOnFailure" />
            <Property TypeID="ClusLibrary!Microsoft.Windows.Cluster.Resource" PropertyID="SeparateMonitor" />
          </DiscoveryClass>
          <DiscoveryClass TypeID="ClusLibrary!Microsoft.Windows.Cluster.NodeRole">
            <Property TypeID="System!System.Entity" PropertyID="DisplayName" />
            <Property TypeID="Windows!Microsoft.Windows.Computer" PropertyID="PrincipalName" />
          </DiscoveryClass>
          <DiscoveryRelationship TypeID="ClusLibrary!Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Network" />
          <DiscoveryRelationship TypeID="ClusLibrary!Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Node" />
          <DiscoveryRelationship TypeID="ClusLibrary!Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Group" />
          <DiscoveryRelationship TypeID="ClusLibrary!Microsoft.Windows.Cluster.Group.Contains.Microsoft.Windows.Cluster.HostedGroup" />
          <DiscoveryRelationship TypeID="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup.Hosts.Microsoft.Windows.Cluster.Resource" />
          <DiscoveryRelationship TypeID="Windows!Microsoft.Windows.ComputerHostsComputerRole" />
        </DiscoveryTypes>
        <DataSource ID="DiscoveryDataSource" TypeID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.DataSource">
          <IntervalSeconds>1800</IntervalSeconds>
          <SyncTime />
          <ProxyingEnabled>$Target/Property[Type='Cluster!Microsoft.Windows.Cluster.Service']/ProxyingEnabled$</ProxyingEnabled>
          <DiscoverySourceId>$MPElement$</DiscoverySourceId>
          <NetworkContainsInterfaceGuid>$MPElement[Name='Clus2003Library!Microsoft.Windows.Cluster.Network.Contains.Microsoft.Windows.2003.Cluster.NetworkInterface']$</NetworkContainsInterfaceGuid>
          <NetworkInterfaceTypeGuid>$MPElement[Name='Clus2003Library!Microsoft.Windows.2003.Cluster.NetworkInterface']$</NetworkInterfaceTypeGuid>
          <NetworkInterfacePropClusterNameGuid>$MPElement[Name='Clus2003Library!Microsoft.Windows.2003.Cluster.NetworkInterface']/ClusterName$</NetworkInterfacePropClusterNameGuid>
          <NetworkInterfacePropNameGuid>$MPElement[Name='Clus2003Library!Microsoft.Windows.2003.Cluster.NetworkInterface']/NetworkInterfaceName$</NetworkInterfacePropNameGuid>
        </DataSource>
      </Discovery>
    </Discoveries>
    <Tasks>
      <Task ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Group.BringOnline" Accessibility="Public" Enabled="true" Target="Microsoft.Windows.Cluster.Group.Fix" Timeout="300" Remotable="true">
        <Category>Maintenance</Category>
        <WriteAction ID="WA" TypeID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Action">
          <NodeName>$Target/Property[Type='ClusLibrary!Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$</NodeName>
          <GroupName>$Target/Property[Type='Microsoft.Windows.Cluster.Group.Fix']/OriginalGroupName$</GroupName>
          <MethodName>Online</MethodName>
        </WriteAction>
      </Task>
      <Task ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Group.Delete" Accessibility="Public" Enabled="true" Target="Microsoft.Windows.Cluster.Group.Fix" Timeout="300" Remotable="true">
        <Category>Maintenance</Category>
        <WriteAction ID="WA" TypeID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Action">
          <NodeName>$Target/Property[Type='ClusLibrary!Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$</NodeName>
          <GroupName>$Target/Property[Type='Microsoft.Windows.Cluster.Group.Fix']/OriginalGroupName$</GroupName>
          <MethodName>Delete</MethodName>
        </WriteAction>
      </Task>
      <Task ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Group.Move" Accessibility="Public" Enabled="true" Target="Microsoft.Windows.Cluster.Group.Fix" Timeout="300" Remotable="true">
        <Category>Maintenance</Category>
        <WriteAction ID="WA" TypeID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Action">
          <NodeName>$Target/Property[Type='ClusLibrary!Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$</NodeName>
          <GroupName>$Target/Property[Type='Microsoft.Windows.Cluster.Group.Fix']/OriginalGroupName$</GroupName>
          <MethodName>Move</MethodName>
        </WriteAction>
      </Task>
      <Task ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Group.TakeOffline" Accessibility="Public" Enabled="true" Target="Microsoft.Windows.Cluster.Group.Fix" Timeout="300" Remotable="true">
        <Category>Maintenance</Category>
        <WriteAction ID="WA" TypeID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Action">
          <NodeName>$Target/Property[Type='ClusLibrary!Microsoft.Windows.Cluster.Group']/GroupActiveOnNodeDuringDiscovery$</NodeName>
          <GroupName>$Target/Property[Type='Microsoft.Windows.Cluster.Group.Fix']/OriginalGroupName$</GroupName>
          <MethodName>Offline</MethodName>
        </WriteAction>
      </Task>
      <Task ID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.HostedGroup.BringOnline" Accessibility="Public" Enabled="true" Target="ClusLibrary!Microsoft.Windows.Cluster.HostedGroup" Timeout="300" Remotable="true">
        <Category>Maintenance</Category>
        <WriteAction ID="WA" TypeID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Action">
          <NodeName>$Target/Property[Type='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/NodeName$</NodeName>
          <GroupName>$Target/Property[Type='ClusLibrary!Microsoft.Windows.Cluster.HostedGroup']/EscapedGroupName$</GroupName>
          <MethodName>Online</MethodName>
        </WriteAction>
      </Task>
    </Tasks>
  </Monitoring>
  <Presentation>
    <ImageReferences>
      <ImageReference ElementID="Microsoft.Windows.Cluster.Group.Fix" ImageID="ClusLibrary!Microsoft.Windows.Cluster.Group.Image" />
    </ImageReferences>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix">
          <Name>Windows 2003 Cluster Quick Unofficial Discovery Fix</Name>
          <Description>Microsoft Windows 2003 Cluster Quick Unofficial Discovery Fix: This management pack contains discovery workaround/fix.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.DataSource">
          <Name>Cluster Discovery (UNOFFICIAL)</Name>
          <Description>Provides and unofficial QFE for discovery of cluster infrastructure. Helps to address problem with "trailing space" in cluster resource or cluster resource group name.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.DataSource" SubElementID="IntervalSeconds">
          <Name>Interval Seconds</Name>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.DataSource" SubElementID="SyncTime">
          <Name>Synchronization Time</Name>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Discovery">
          <Name>Discover cluster infrastructure (UNOFFICIAL)</Name>
          <Description>Unofficial script that corrects issue with trailing space in name. New class had to be created, because official class could not be extended with new property that is needed to hold string with trailing spaces.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.ScriptProbe">
          <Name>Cluster Discovery Script (UNOFFICIAL)</Name>
          <Description>Performs discovery using WMI cluster provider in VB Script.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Group.BringOnline">
          <Name>Bring Online (UNOFFICIAL - execute for group with trailing spaces in the name)</Name>
          <Description>Brings cluster resource group online.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Group.Delete">
          <Name>Delete Group (UNOFFICIAL - execute for group with trailing spaces in the name)</Name>
          <Description>Deletes cluster resource group.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Group.Move">
          <Name>Move Group (UNOFFICIAL - execute for group with trailing spaces in the name)</Name>
          <Description>Moves cluster resource group.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Group.TakeOffline">
          <Name>Take Offline (UNOFFICIAL - execute for group with trailing spaces in the name)</Name>
          <Description>Takes cluster resource group offline.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.HostedGroup.BringOnline">
          <Name>Bring Online (UNOFFICIAL - execute for group with trailing spaces in the name)</Name>
          <Description>Brings cluster resource group online.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Action">
          <Name>Group resource action (UNOFFICIAL)</Name>
          <Description>Serves as a discovery for tasks.</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.Cluster.Group.Fix">
          <Name>Cluster Resource Group (UNOFFICIAL)</Name>
          <Description>Class representing cluster resource group. It had to be created as "Original group name" is required in case when possible trailing spaces is present</Description>
        </DisplayString>
        <DisplayString ElementID="Microsoft.Windows.Cluster.Group.Fix" SubElementID="OriginalGroupName">
          <Name>Original Group Name</Name>
          <Description>Original value returned by cluster WMI provider.</Description>
        </DisplayString>
      </DisplayStrings>
      <KnowledgeArticles>
        <KnowledgeArticle ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix" Visible="true">
          <MamlContent>
            <maml:section xmlns:maml="http://schemas.microsoft.com/maml/2004/10">
              <maml:title>Summary</maml:title>
              <maml:para>The Windows 2003 Cluster Quick Unofficial Discovery Fix Management Pack provides the discovery workaround when Resource group contains trailing spaces.</maml:para>
            </maml:section>
          </MamlContent>
        </KnowledgeArticle>
        <KnowledgeArticle ElementID="Microsoft.Windows.2003.Cluster.Quick.Unofficial.Discovery.Fix.Discovery" Visible="true">
          <MamlContent>
            <maml:section xmlns:maml="http://schemas.microsoft.com/maml/2004/10">
              <maml:title>Summary</maml:title>
              <maml:para>This Discovery Rule discovers and populates the instances of Cluster service for Windows 2003.</maml:para>
              <maml:para />
              <maml:para>Unsupported script that corrects issue with trailing space in resource or resource group name is used. New class had to be created/defined, because official class could not be extended with new property that is needed to hold string with trailing spaces.</maml:para>
              <maml:para />
              <maml:para>THIS WILL BE CORRECTED WITH UPCOMMING RELEASE OF WIN2K8 CLUSTER MP!!!.</maml:para>
            </maml:section>
          </MamlContent>
        </KnowledgeArticle>
      </KnowledgeArticles>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>