DSCResources/DSC_DFSNamespaceRoot/DSC_DFSNamespaceRoot.psm1

$modulePath = Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath 'Modules'

# Import the DFSDsc.Common Module
Import-Module -Name (Join-Path -Path $modulePath -ChildPath 'DscResource.Common')

# Import Localization Strings
$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US'

<#
    .SYNOPSIS
    Returns the current state of a DFS Namespace Root.
 
    .PARAMETER Path
    Specifies a path for the root of a DFS namespace.
 
    .PARAMETER TargetPath
    Specifies a path for a root target of the DFS namespace.
 
    .PARAMETER Ensure
    Specifies if the DFS Namespace root should exist.
 
    .PARAMETER TargetState
    Specifies the state of the DFS namespace root target.
 
    .PARAMETER Type
    Specifies the type of a DFS namespace as a Type object.
#>

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $Path,

        [Parameter(Mandatory = $true)]
        [System.String]
        $TargetPath,

        [Parameter()]
        [ValidateSet('Present','Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [ValidateSet('Offline','Online')]
        [System.String]
        $TargetState = 'Online',

        [Parameter(Mandatory = $true)]
        [ValidateSet('Standalone','DomainV1','DomainV2')]
        [System.String]
        $Type
    )

    Write-Verbose -Message ( @(
            "$($MyInvocation.MyCommand): "
            $($script:localizedData.GettingNamespaceRootMessage) `
                -f $Type,$Path,$TargetPath
        ) -join '' )

    # Generate the return object assuming absent.
    $returnValue = @{
        Path = $Path
        TargetPath = $TargetPath
        Ensure = 'Absent'
        Type = $Type
    }

    # Lookup the existing Namespace root
    $root = Get-Root `
        -Path $Path

    if ($root)
    {
        # The namespace exists
        Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.NamespaceRootExistsMessage) `
                    -f $Type,$Path
            ) -join '' )
    }
    else
    {
        # The namespace does not exist
        Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.NamespaceRootDoesNotExistMessage) `
                    -f $Type,$Path
            ) -join '' )
        return $returnValue
    } # if

    $returnValue += @{
        TimeToLiveSec                = $root.TimeToLiveSec
        State                        = $root.State
        Description                  = $root.Description
        EnableSiteCosting            = ($root.Flags -contains 'Site Costing')
        EnableInsiteReferrals        = ($root.Flags -contains 'Insite Referrals')
        EnableAccessBasedEnumeration = ($root.Flags -contains 'AccessBased Enumeration')
        EnableRootScalability        = ($root.Flags -contains 'Root Scalability')
        EnableTargetFailback         = ($root.Flags -contains 'Target Failback')
    }

    # DFS Root exists but does target exist?
    $target = Get-RootTarget `
        -Path $Path `
        -TargetPath $TargetPath

    if ($target)
    {
        # The target exists in this namespace
        $returnValue.Ensure = 'Present'
        $returnValue += @{
            ReferralPriorityClass        = $target.ReferralPriorityClass
            ReferralPriorityRank         = $target.ReferralPriorityRank
            TargetState                  = $target.State
        }

        Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.NamespaceRootTargetExistsMessage) `
                    -f $Type,$Path,$TargetPath
            ) -join '' )
    }
    else
    {
        # The target does not exist in this namespace
        Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.NamespaceRootTargetDoesNotExistMessage) `
                    -f $Type,$Path,$TargetPath
            ) -join '' )
    } # if

    return $returnValue
} # Get-TargetResource

<#
    .SYNOPSIS
    Sets the current state of a DFS Namespace Folder.
 
    .PARAMETER Path
    Specifies a path for the root of a DFS namespace.
 
    .PARAMETER TargetPath
    Specifies a path for a root target of the DFS namespace.
 
    .PARAMETER Ensure
    Specifies if the DFS Namespace root should exist.
 
    .PARAMETER TargetState
    Specifies the state of the DFS namespace root target.
 
    .PARAMETER Type
    Specifies the type of a DFS namespace as a Type object.
 
    .PARAMETER Description
    The description of the DFS Namespace.
 
    .PARAMETER TimeToLiveSec
    Specifies a TTL interval, in seconds, for referrals.
 
    .PARAMETER EnableSiteCosting
    Indicates whether a DFS namespace uses cost-based selection.
 
    .PARAMETER EnableInsiteReferrals
    Indicates whether a DFS namespace server provides a client only with referrals that are in the same site as the client.
 
    .PARAMETER EnableAccessBasedEnumeration
    Indicates whether a DFS namespace uses access-based enumeration.
 
    .PARAMETER EnableRootScalability
    Indicates whether a DFS namespace uses root scalability mode.
 
    .PARAMETER EnableTargetFailback
    Indicates whether a DFS namespace uses target failback.
 
    .PARAMETER ReferralPriorityClass
    Specifies the target priority class for a DFS namespace root.
 
    .PARAMETER ReferralPriorityRank
    Specifies the priority rank, as an integer, for a root target of the DFS namespace.
#>

function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $Path,

        [Parameter(Mandatory = $true)]
        [System.String]
        $TargetPath,

        [Parameter()]
        [ValidateSet('Present','Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [ValidateSet('Offline','Online')]
        [System.String]
        $TargetState = 'Online',

        [Parameter(Mandatory = $true)]
        [ValidateSet('Standalone','DomainV1','DomainV2')]
        [System.String]
        $Type,

        [Parameter()]
        [System.String]
        $Description,

        [Parameter()]
        [System.UInt32]
        $TimeToLiveSec,

        [Parameter()]
        [System.Boolean]
        $EnableSiteCosting,

        [Parameter()]
        [System.Boolean]
        $EnableInsiteReferrals,

        [Parameter()]
        [System.Boolean]
        $EnableAccessBasedEnumeration,

        [Parameter()]
        [System.Boolean]
        $EnableRootScalability,

        [Parameter()]
        [System.Boolean]
        $EnableTargetFailback,

        [Parameter()]
        [ValidateSet('Global-High','SiteCost-High','SiteCost-Normal','SiteCost-Low','Global-Low')]
        [System.String]
        $ReferralPriorityClass,

        [Parameter()]
        [System.UInt32]
        $ReferralPriorityRank
    )

    Write-Verbose -Message ( @(
            "$($MyInvocation.MyCommand): "
            $($script:localizedData.SettingNamespaceRootMessage) `
                -f $Type,$Path,$TargetPath
        ) -join '' )

    # Lookup the existing Namespace root
    $root = Get-Root `
        -Path $Path

    if ($Ensure -eq 'Present')
    {
        # Set desired Configuration
        if ($root)
        {
            # Does the root need to be updated?
            [System.Boolean] $rootChange = $false

            # The root properties that will be updated
            $rootProperties = @{
                State = 'Online'
            }

            if (($Description) `
                -and ($root.Description -ne $Description))
            {
                $rootProperties += @{
                    Description = $Description
                }
                $rootChange = $true
            } # if

            if (($TimeToLiveSec) `
                -and ($root.TimeToLiveSec -ne $TimeToLiveSec))
            {
                $rootProperties += @{
                    TimeToLiveSec = $TimeToLiveSec
                }
                $rootChange = $true
            } # if

            if (($null -ne $EnableSiteCosting) `
                -and (($root.Flags -contains 'Site Costing') -ne $EnableSiteCosting))
            {
                $rootProperties += @{
                    EnableSiteCosting = $EnableSiteCosting
                }
                $rootChange = $true
            } # if

            if (($null -ne $EnableInsiteReferrals) `
                -and (($root.Flags -contains 'Insite Referrals') -ne $EnableInsiteReferrals))
            {
                $rootProperties += @{
                    EnableInsiteReferrals = $EnableInsiteReferrals
                }
                $rootChange = $true
            } # if

            if (($null -ne $EnableAccessBasedEnumeration) `
                -and (($root.Flags -contains 'AccessBased Enumeration') -ne $EnableAccessBasedEnumeration))
            {
                $rootProperties += @{
                    EnableAccessBasedEnumeration = $EnableAccessBasedEnumeration
                }
                $rootChange = $true
            } # if

            if (($null -ne $EnableRootScalability) `
                -and (($root.Flags -contains 'Root Scalability') -ne $EnableRootScalability))
            {
                $rootProperties += @{
                    EnableRootScalability = $EnableRootScalability
                }
                $rootChange = $true
            } # if

            if (($null -ne $EnableTargetFailback) `
                -and (($root.Flags -contains 'Target Failback') -ne $EnableTargetFailback))
            {
                $rootProperties += @{
                    EnableTargetFailback = $EnableTargetFailback
                }
                $rootChange = $true
            } # if

            if ($rootChange)
            {
                # Update root settings
                $null = Set-DfsnRoot `
                    -Path $Path `
                    @RootProperties `
                    -ErrorAction Stop

                $rootProperties.GetEnumerator() | ForEach-Object -Process {
                    Write-Verbose -Message ( @(
                        "$($MyInvocation.MyCommand): "
                        $($script:localizedData.NamespaceRootUpdateParameterMessage) `
                            -f $Type,$Path,$_.name, $_.value
                    ) -join '' )
                }
            } # if

            # Get target
            $target = Get-RootTarget `
                -Path $Path `
                -TargetPath $TargetPath

            # Does the target need to be updated?
            [System.Boolean] $targetChange = $false

            # The Target properties that will be updated
            $targetProperties = @{}

            # Check the target properties
            if (($TargetState) `
                -and ($target.State -ne $TargetState))
            {
                $targetProperties += @{
                    State = $TargetState
                }
                $targetChange = $true
            } # if

            if (($ReferralPriorityClass) `
                -and ($target.ReferralPriorityClass -ne $ReferralPriorityClass))
            {
                $targetProperties += @{
                    ReferralPriorityClass = ($ReferralPriorityClass -replace '-','')
                }
                $targetChange = $true
            } # if

            if (($ReferralPriorityRank) `
                -and ($target.ReferralPriorityRank -ne $ReferralPriorityRank))
            {
                $targetProperties += @{
                    ReferralPriorityRank = $ReferralPriorityRank
                }
                $targetChange = $true
            } # if

            # Is the target a member of the namespace?
            if ($target)
            {
                # Does the target need to be changed?
                if ($targetChange)
                {
                    # Update target settings
                    $null = Set-DfsnRootTarget `
                        -Path $Path `
                        -TargetPath $TargetPath `
                        @TargetProperties `
                        -ErrorAction Stop
                }
            }
            else
            {
                # Add target to Namespace
                $null = New-DfsnRootTarget `
                    -Path $Path `
                    -TargetPath $TargetPath `
                    @TargetProperties `
                    -ErrorAction Stop
            } # if

            # Output the target parameters that were changed/set
            $targetProperties.GetEnumerator() | ForEach-Object -Process {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootTargetUpdateParameterMessage) `
                        -f $Type,$Path,$TargetPath,$_.name, $_.value
                ) -join '' )
            }
        }
        else
        {
            <#
                Prepare to use the PSBoundParameters as a splat to created
                The new DFS Namespace root.
            #>

            $null = $PSBoundParameters.Remove('Ensure')

            # Correct the ReferralPriorityClass field
            if ($ReferralPriorityClass)
            {
                $PSBoundParameters.ReferralPriorityClass = ($ReferralPriorityClass -replace '-','')
            } # if

            # Create New-DfsnRoot
            $null = New-DfsnRoot `
                @PSBoundParameters `
                -ErrorAction Stop

            $PSBoundParameters.GetEnumerator() | ForEach-Object -Process {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootUpdateParameterMessage) `
                        -f $Type,$Path,$_.name, $_.value
                ) -join '' )
            }
        } # if
    }
    else
    {
        <#
            The Namespace Target should not exist
            Get root target
        #>

        $target = Get-RootTarget `
            -Path $Path `
            -TargetPath $TargetPath

        if ($target)
        {
            # Remove the target from the namespace
            $null = Remove-DfsnRootTarget `
                -Path $Path `
                -TargetPath $TargetPath `
                -Confirm:$false `
                -ErrorAction Stop

            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.NamespaceRootTargetRemovedMessage) `
                    -f $Type,$Path,$TargetPath
            ) -join '' )
        } # if
    } # if
} # Set-TargetResource

<#
    .SYNOPSIS
    Tests the current state of a DFS Namespace Folder.
 
    .PARAMETER Path
    Specifies a path for the root of a DFS namespace.
 
    .PARAMETER TargetPath
    Specifies a path for a root target of the DFS namespace.
 
    .PARAMETER Ensure
    Specifies if the DFS Namespace root should exist.
 
    .PARAMETER TargetState
    Specifies the state of the DFS namespace root target.
 
    .PARAMETER Type
    Specifies the type of a DFS namespace as a Type object.
 
    .PARAMETER Description
    The description of the DFS Namespace.
 
    .PARAMETER TimeToLiveSec
    Specifies a TTL interval, in seconds, for referrals.
 
    .PARAMETER EnableSiteCosting
    Indicates whether a DFS namespace uses cost-based selection.
 
    .PARAMETER EnableInsiteReferrals
    Indicates whether a DFS namespace server provides a client only with referrals that are in the same site as the client.
 
    .PARAMETER EnableAccessBasedEnumeration
    Indicates whether a DFS namespace uses access-based enumeration.
 
    .PARAMETER EnableRootScalability
    Indicates whether a DFS namespace uses root scalability mode.
 
    .PARAMETER EnableTargetFailback
    Indicates whether a DFS namespace uses target failback.
 
    .PARAMETER ReferralPriorityClass
    Specifies the target priority class for a DFS namespace root.
 
    .PARAMETER ReferralPriorityRank
    Specifies the priority rank, as an integer, for a root target of the DFS namespace.
#>

function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $Path,

        [Parameter(Mandatory = $true)]
        [System.String]
        $TargetPath,

        [Parameter()]
        [ValidateSet('Present','Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [ValidateSet('Offline','Online')]
        [System.String]
        $TargetState = 'Online',

        [Parameter(Mandatory = $true)]
        [ValidateSet('Standalone','DomainV1','DomainV2')]
        [System.String]
        $Type,

        [Parameter()]
        [System.String]
        $Description,

        [Parameter()]
        [System.UInt32]
        $TimeToLiveSec,

        [Parameter()]
        [System.Boolean]
        $EnableSiteCosting,

        [Parameter()]
        [System.Boolean]
        $EnableInsiteReferrals,

        [Parameter()]
        [System.Boolean]
        $EnableAccessBasedEnumeration,

        [Parameter()]
        [System.Boolean]
        $EnableRootScalability,

        [Parameter()]
        [System.Boolean]
        $EnableTargetFailback,

        [Parameter()]
        [ValidateSet('Global-High','SiteCost-High','SiteCost-Normal','SiteCost-Low','Global-Low')]
        [System.String]
        $ReferralPriorityClass,

        [Parameter()]
        [System.UInt32]
        $ReferralPriorityRank
    )

    Write-Verbose -Message ( @(
            "$($MyInvocation.MyCommand): "
            $($script:localizedData.TestingNamespaceRootMessage) `
                -f $Type,$Path,$TargetPath
        ) -join '' )

    # Flag to signal whether settings are correct
    [System.Boolean] $desiredConfigurationMatch = $true

    # Lookup the existing Namespace root
    $root = Get-Root `
        -Path $Path

    if ($Ensure -eq 'Present')
    {
        # The Namespace root should exist
        if ($root)
        {
            <#
                The Namespace root exists and should
                Changing the namespace type is not possible - the namespace
                can only be recreated if the type should change.
            #>

            if (($root.Type -replace ' ','') -ne $Type)
            {
                New-InvalidOperationException `
                    -Message ($($script:localizedData.NamespaceRootTypeConversionError) `
                        -f $Type,($root.Type -replace ' ',''))
            } # if

            # Check the Namespace parameters
            if (($Description) `
                -and ($root.Description -ne $Description))
            {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootParameterNeedsUpdateMessage) `
                        -f $Type,$Path,'Description'
                    ) -join '' )

                $desiredConfigurationMatch = $false
            } # if

            if (($TimeToLiveSec) `
                -and ($root.TimeToLiveSec -ne $TimeToLiveSec))
            {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootParameterNeedsUpdateMessage) `
                        -f $Type,$Path,'TimeToLiveSec'
                    ) -join '' )

                $desiredConfigurationMatch = $false
            } # if

            if (($null -ne $EnableSiteCosting) `
                -and (($root.Flags -contains 'Site Costing') -ne $EnableSiteCosting))
            {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootParameterNeedsUpdateMessage) `
                        -f $Type,$Path,'EnableSiteCosting'
                    ) -join '' )

                $desiredConfigurationMatch = $false
            } # if

            if (($null -ne $EnableInsiteReferrals) `
                -and (($root.Flags -contains 'Insite Referrals') -ne $EnableInsiteReferrals))
            {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootParameterNeedsUpdateMessage) `
                        -f $Type,$Path,'EnableInsiteReferrals'
                    ) -join '' )

                $desiredConfigurationMatch = $false
            } # if

            if (($null -ne $EnableAccessBasedEnumeration) `
                -and (($root.Flags -contains 'AccessBased Enumeration') -ne $EnableAccessBasedEnumeration))
            {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootParameterNeedsUpdateMessage) `
                        -f $Type,$Path,'EnableAccessBasedEnumeration'
                    ) -join '' )

                $desiredConfigurationMatch = $false
            } # if

            if (($null -ne $EnableRootScalability) `
                -and (($root.Flags -contains 'Root Scalability') -ne $EnableRootScalability))
            {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootParameterNeedsUpdateMessage) `
                        -f $Type,$Path,'EnableRootScalability'
                    ) -join '' )

                $desiredConfigurationMatch = $false
            } # if

            if (($null -ne $EnableTargetFailback) `
                -and (($root.Flags -contains 'Target Failback') -ne $EnableTargetFailback))
            {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootParameterNeedsUpdateMessage) `
                        -f $Type,$Path,'EnableTargetFailback'
                    ) -join '' )

                $desiredConfigurationMatch = $false
            } # if

            $target = Get-RootTarget `
                -Path $Path `
                -TargetPath $TargetPath

            if ($target)
            {
                if (($TargetState) `
                    -and ($target.State -ne $TargetState))
                {
                    Write-Verbose -Message ( @(
                        "$($MyInvocation.MyCommand): "
                        $($LocalizedData.NamespaceRootTargetParameterNeedsUpdateMessage) `
                            -f $Type,$Path,$TargetPath,'TargetState'
                        ) -join '' )
                    $desiredConfigurationMatch = $false
                } # if

                if (($ReferralPriorityClass) `
                    -and ($target.ReferralPriorityClass -ne $ReferralPriorityClass))
                {
                    Write-Verbose -Message ( @(
                        "$($MyInvocation.MyCommand): "
                        $($script:localizedData.NamespaceRootTargetParameterNeedsUpdateMessage) `
                            -f $Type,$Path,$TargetPath,'ReferralPriorityClass'
                        ) -join '' )
                    $desiredConfigurationMatch = $false
                } # if

                if (($ReferralPriorityRank) `
                    -and ($target.ReferralPriorityRank -ne $ReferralPriorityRank))
                {
                    Write-Verbose -Message ( @(
                        "$($MyInvocation.MyCommand): "
                        $($script:localizedData.NamespaceRootTargetParameterNeedsUpdateMessage) `
                            -f $Type,$Path,$TargetPath,'ReferralPriorityRank'
                        ) -join '' )
                    $desiredConfigurationMatch = $false
                } # if
            }
            else
            {
                # The Root target does not exist but should - change required
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootTargetDoesNotExistButShouldMessage) `
                        -f $Type,$Path,$TargetPath
                    ) -join '' )
                $desiredConfigurationMatch = $false
            } # if
        }
        else
        {
            # Ths Namespace root doesn't exist but should - change required
            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                 $($script:localizedData.NamespaceRootDoesNotExistButShouldMessage) `
                    -f $Type,$Path
                ) -join '' )
            $desiredConfigurationMatch = $false
        } # if
    }
    else
    {
        # The Namespace target should not exist
        if ($root)
        {
            $target = Get-RootTarget `
                -Path $Path `
                -TargetPath $TargetPath

            if ($target)
            {
                # The Root target exists but should not - change required
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootTargetExistsButShouldNotMessage) `
                        -f $Type,$Path,$TargetPath
                    ) -join '' )
                $desiredConfigurationMatch = $false
            }
            else
            {
                # The Namespace exists but the target doesn't - change not required
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.NamespaceRootTargetDoesNotExistAndShouldNotMessage) `
                        -f $Type,$Path,$TargetPath
                    ) -join '' )
            } # if
        }
        else
        {
            # The Namespace does not exist (so neither does the target) - change not required
            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                 $($script:localizedData.NamespaceRootDoesNotExistAndShouldNotMessage) `
                    -f $Type,$Path
                ) -join '' )
        } # if
    } # if

    return $desiredConfigurationMatch
} # Test-TargetResource

<#
    .SYNOPSIS
    Lookup the DFSN Root.
 
    .PARAMETER Path
    Specifies a path for the root of a DFS namespace.
#>

function Get-Root
{
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $Path
    )

    try
    {
        $dfsnRoot = Get-DfsnRoot `
            -Path $Path `
            -ErrorAction Stop
    }
    catch [Microsoft.Management.Infrastructure.CimException]
    {
        $dfsnRoot = $null
    }
    catch
    {
        throw $_
    }
    return $dfsnRoot
}

<#
    .SYNOPSIS
    Lookup the DFSN Root Target in a namespace.
 
    .PARAMETER Path
    Specifies a path for the root of a DFS namespace.
 
    .PARAMETER TargetPath
    Specifies a path for a root target of the DFS namespace.
#>

function Get-RootTarget
{
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $Path,

        [Parameter(Mandatory = $true)]
        [System.String]
        $TargetPath
    )

    try
    {
        $dfsnTarget = Get-DfsnRootTarget `
            -Path $Path `
            -TargetPath $TargetPath `
            -ErrorAction Stop
    }
    catch [Microsoft.Management.Infrastructure.CimException]
    {
        $dfsnTarget = $null
    }
    catch
    {
        throw $_
    }
    return $dfsnTarget
}

Export-ModuleMember -Function *-TargetResource