UninstallMarvellQLogicFCPowerKit.psm1

# Functions

$global:stopCmdLet = 0

Function Test-IfNano {
    # Check if OS is Nano or Non-Nano
    $envInfo = [Environment]::OSVersion.Version
    $envInfoCimInst = Get-CimInstance Win32_OperatingSystem
    return ( ($envInfo.Major -eq 10) -and ($envInfo.Minor -eq 0) -and ($envInfoCimInst.ProductType -eq 3) -and ($envInfoCimInst.SuiteMask -eq 272) )
}

Function Test-RegistryValue {
    Param (
        [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $Path,
        [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $Value
    )

    try {
        Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop 2>&1 | Out-Null
        return $true
    } catch {
        return $false
    }
}

Function Get-AppxPackageWrapper {
    Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $AppxName )

    $numAttempts = 3
    $numSecondsBetweenAttempts = 5
    for ($i=0; $i -lt $numAttempts; $i++) {
        $appxPkg = Get-AppxPackage | Where-Object { $_.name -eq $AppxName }
        if ($appxPkg -ne $null) { break }
        Write-Host "Couldn't find Appx package. Trying again in $numSecondsBetweenAttempts seconds (attempt $($i+1) of $numAttempts) ..." -ForegroundColor DarkRed
        Start-Sleep -Seconds $numSecondsBetweenAttempts
    }
    if ($appxPkg -eq $null) {
        Write-Host 'Failed to find Appx package. Please try running this script again.' -ForegroundColor Red
    }
    return $appxPkg
}

Function Remove-ProviderAppxProvisionedPackage {
    Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $AppxDisplayName )
    if ($Script:isNano) { return } # Skip if Nano
    $appxProvPkg = Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -eq $AppxDisplayName }
    if ($appxProvPkg -ne $null) {
        Remove-AppxProvisionedPackage -Online -PackageName $appxProvPkg.PackageName 2>&1 | Out-Null
        Write-Host "Removed AppxProvisionedPackage $($appxProvPkg.PackageName)"
    }
}

Function Remove-CmdletsPathFromPSModulePath {
    # This function removes cmdlet module path(s) from system PSModulePath environment variable.

    if ($Script:isServerCore) {
        $appxCmdletsPath = "$env:ProgramFiles\Marvell_Semiconductor_Inc\FC_PowerKit\Cmdlets"
    } else {
        $appxCmdletsPath = (Get-AppxPackageWrapper -AppxName 'MRVLFCProvider').InstallLocation + '\Cmdlets'
    }

    if (($appxCmdletsPath -ne $null) -and ($appxCmdletsPath -ne '\Cmdlets') ) {
        if (Test-RegistryValue -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Value 'PSModulePath') {
            $currPSModulePathArr = ((Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment').PSModulePath).Split(';')
            $newPSModulePathArr = @()
            # Remove any paths containing 'MRVLFCProvider' from PSModulePath
            foreach ($path in $currPSModulePathArr) {
                if (-not $path.Contains('MRVLFCProvider')) {
                    $newPSModulePathArr += $path
                } else {
                    Write-Host "Removed '$path' from PSModulePath."
                }
            }
            $newPSModulePathStr = $newPSModulePathArr -join ';'

            # Write PSModulePath to registry and set local session variable
            & setx /s $env:COMPUTERNAME PSModulePath $newPSModulePathStr /m 2>&1 | Out-Null
            $env:PSModulePath = $newPSModulePathStr
        }
    }
    else {
        $global:stopCmdLet = 1
    }

}

Function Remove-CLSIDRegistryPaths {
    if (Test-Path -Path "Registry::HKCR\CLSID\$Script:CLSID") {
        Remove-Item -Path "Registry::HKCR\CLSID\$Script:CLSID" -Recurse
        Write-Host "Removed HKCR:\CLSID\$Script:CLSID from registry."
    }
    if (Test-Path -Path "HKLM:\Software\Classes\CLSID\$Script:CLSID") {
        Remove-Item -Path "HKLM:\Software\Classes\CLSID\$Script:CLSID" -Recurse
        Write-Host "Removed HKLM:\Software\Classes\CLSID\$Script:CLSID from registry."
    }
}

Function Uninstall-MofComp {
    # TODO - Determine if this function is always necessary
    if ($Script:isServerCore) {
        $mofCompFilePath = "$env:ProgramFiles\Marvell_Semiconductor_Inc\FC_PowerKit\MRVLFCProvider_Uninstall.mof"
    } else {
        $mofCompFilePath = (Get-AppxPackageWrapper -AppxName 'MRVLFCProvider').InstallLocation
        if($mofCompFilePath -ne $null) {
            $mofCompFilePath += '\MRVLFCProvider_Uninstall.mof'
        }
    }

    if($mofCompFilePath -ne $null) {
        # $mofcompOutput = & mofcomp.exe -N:root\qlgcfc -class:forceupdate $appxPath\MRVLFCProvider_Uninstall.mof 2>&1
        $mofcompOutput = & mofcomp.exe -N:root\qlgcfc $mofCompFilePath 2>&1
        if ($mofcompOutput -match 'Error') {
            Write-Host "Failed to unregister `"$mofCompFilePath`": $($mofcompOutput -match 'Error')" -ForegroundColor Red
        } else {
            Write-Host "MRVLFCProvider unregistered."
        }
        if (Test-RegistryValue -Path 'HKLM:\Software\Microsoft\Wbem\CIMOM\SecuredHostProviders' -Value 'Root/qlgcfc:__Win32Provider.Name="MRVLFCProvider"') {
            Remove-ItemProperty -Path 'HKLM:\Software\Microsoft\Wbem\CIMOM\SecuredHostProviders' -Name 'Root/qlgcfc:__Win32Provider.Name="MRVLFCProvider"'
        }
    }
}

Function Remove-CmdletsFromProgramData {
    # Remove any ProgramData directories containing 'MRVLFCProvider'
    $progDataPaths = (Get-ChildItem $env:ProgramData | Where-Object { ($_.Name).StartsWith('MRVLFCProvider_') }).FullName
    foreach ($path in $progDataPaths) {
        Remove-Item $path -Recurse -Force
        Write-Host "Cmdlets removed from `"$path`"."
    }
}


Function Remove-RESTFilesFromProgramData {
    # Remove any ProgramData directories containing 'MRVLFCProviderREST_'
    $progDataPaths = (Get-ChildItem $env:ProgramData | Where-Object { ($_.Name).StartsWith('MRVLFCProviderREST_') }).FullName
    foreach ($path in $progDataPaths) {
        Remove-Item $path -Recurse -Force
        Write-Host "FC REST files removed from `"$path`"."
    }
}

Function Remove-AppxPackageWrapper {
    Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] $AppxDisplayName )
    $appxPkg = Get-AppxPackage | Where-Object { $_.Name -eq $AppxDisplayName }
    if ($appxPkg -ne $null) {
        $savedProgressPreference = $Global:ProgressPreference
        $Global:ProgressPreference = 'SilentlyContinue'
        Remove-AppxPackage -Package $appxPkg 2>&1 | Out-Null
        $Global:ProgressPreference = $savedProgressPreference
        Write-Host "Removed $AppxDisplayName AppxPackage."
        Write-Host "Successfully uninstalled MarvellQLogicFCPowerKit.`n" -ForegroundColor Green
    }
}

Function Remove-FromIIS {
    $appcmd = "$env:SystemRoot\system32\inetsrv\appcmd.exe"

    # Stop all sites
    $sites = (& $appcmd list site 2>&1)
    if ($sites -ne $null) {
        if ($sites.GetType() -eq [System.String]) {
            $siteName = $sites.Split('"')[1]
            $appcmdOutput = (& $appcmd stop site $siteName 2>&1)
        } else {
            foreach ($s in $sites) {
                $siteName = $s.Split('"')[1]
                $appcmdOutput = (& $appcmd stop site $siteName 2>&1)
            }
        }
    }

    # Stop DefaultAppPool and MOData apppool
    $appcmdOutput = (& $appcmd stop apppool /apppool.name:DefaultAppPool 2>&1)
    $appcmdOutput = (& $appcmd stop apppool /apppool.name:MOData 2>&1)

    # Delete MOData appool
    $appcmdOutput = (& $appcmd delete apppool /apppool.name:MOData 2>&1)

    # Delete MODataSvc app
    $appcmdOutput = (& $appcmd delete app MODataSvc/MODataSvc 2>&1)

    # Delete MODataSvc site
    $appcmdOutput = (& $appcmd delete site MODataSvc 2>&1)
    Remove-Item "$env:HOMEDRIVE\inetpub\wwwroot\MOData" -Recurse -Force

    # Start DefaultAppPool apppool
    $appcmdOutput = (& $appcmd start apppool /apppool.name:DefaultAppPool 2>&1)

    # Start all sites
    $sites = (& $appcmd list site 2>&1)
    if ($sites -ne $null) {
        if ($sites.GetType() -eq [System.String]) {
            $siteName = $sites.Split('"')[1]
            $appcmdOutput = (& $appcmd start site $siteName 2>&1)
        } else {
            foreach ($s in $sites) {
                $siteName = $s.Split('"')[1]
                $appcmdOutput = (& $appcmd start site $siteName 2>&1)
            }
        }
    }

    # Remove any existing firewall rules
    if ((Get-NetFirewallRule | Where-Object { ($_.DisplayName).StartsWith('MOData_IIS_Port') }) -ne $null) {
        Remove-NetFirewallRule -DisplayName 'MOData_IIS_Port'
    }

    Write-Host "Removed from IIS."
}

Function Kill-WMI-Provider-Hosts-Processes {
    TASKKILL /F /IM "WmiPrvSE.exe" | Out-Null
}

Function UnInstall-FCPowerKit {
    # Encapulate uninstaller logic here
    #--------------------------------------------------------------------------------------------------
    # Globals
    $Script:CLSID = '{A31B8A5E-8B6A-421C-8BB1-F85C9C34E659}'

    #--------------------------------------------------------------------------------------------------
    # Script - Cmdlets Uninstall
    Remove-ProviderAppxProvisionedPackage -AppxDisplayName 'MRVLFCProvider'
    if($global:stopCmdLet -eq 0) {
        Remove-CmdletsPathFromPSModulePath
        if($global:stopCmdLet -eq 0) {
            Remove-CLSIDRegistryPaths
            if($global:stopCmdLet -eq 0) {
                Uninstall-MofComp
                Remove-CmdletsFromProgramData
                Remove-AppxPackageWrapper -AppxDisplayName 'MRVLFCProvider'
                Kill-WMI-Provider-Hosts-Processes
            }
        }
    }

}

Export-ModuleMember -function UnInstall-FCPowerKit