private/Save-WinPEDriverPackageVMwareAmd64.ps1

#Requires -PSEdition Core

function Save-WinPEDriverPackageVMwareAmd64 {
    <#
    .SYNOPSIS
        Downloads and prepares VMware pvscsi drivers for amd64
 
    .DESCRIPTION
        Downloads the VMware Tools Windows amd64 ISO to the OSDeployCore download cache.
        VMware does not publish a checksum for this ISO, so the download is not hash verified.
 
        Unless DownloadOnly is specified, the function expands the ISO into a temporary
        directory and copies only the Win10 amd64 pvscsi payload into the managed driver library.
        When the destination is incomplete or contains content other than pvscsi, all existing
        destination content is removed before it is rebuilt. The temporary directory is removed
        in a finally block.
 
    .PARAMETER DriverPackage
        Specifies the amd64 OSDeployWinPEDriver.Package object to download. The object supplies
        the package name, version, architecture, URIs, and filename.
 
    .PARAMETER Force
        Downloads the ISO again even when a cached file is available.
 
    .PARAMETER DownloadOnly
        Returns after downloading the ISO without expanding or replacing managed driver content.
 
    .EXAMPLE
        PS> $package = Get-WinPEDriverPackageCore | Where-Object { $_.Name -Match 'VMware' -and $_.Architecture -eq 'amd64' } | Select-Object -First 1; Save-WinPEDriverPackageVMwareAmd64 -DriverPackage $package
 
        Downloads the first amd64 VMware package and prepares only its pvscsi drivers.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.IO.FileInfo. Returns the downloaded ISO, or no object when the download fails.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-08-28
 
        Rebuilding recursively removes existing content from the package destination.
 
    .LINK
        Save-WinPEDriverPackageCore
    #>

    [CmdletBinding()]
    [OutputType([System.IO.FileInfo])]
    param (
        [Parameter(Mandatory)]
        [PSTypeName('OSDeployWinPEDriver.Package')]
        [PSCustomObject]$DriverPackage,

        [Parameter()]
        [switch]$Force,

        [Parameter()]
        [switch]$DownloadOnly
    )

    $package     = $DriverPackage
    $idPrefix    = ($package.Name -split '-')[0]
    $downloadDir = Join-Path $script:OSDeployCoreDownloadsPath $idPrefix
    $targetPath  = Join-Path $downloadDir $package.FileName
    $driverDir   = Join-Path $script:OSDeployBootAssetsPath "winpedrivers-$($package.Architecture)" |
                   Join-Path -ChildPath "$($package.Name)-$($package.Version)"
    $relativeSourcePath = 'Program Files\VMware\VMware Tools\Drivers\pvscsi\Win10\amd64'
    $targetDriverDir = Join-Path $driverDir 'pvscsi'

    # VMware ISOs do not have published checksums — download without hash verification
    $downloadedFile = Invoke-WinPEDriverPackageDownload `
        -Uri             $package.DownloadUri `
        -DestinationPath $targetPath `
        -SearchUri       $package.UpdateUri `
        -Force:$Force

    if (-not $downloadedFile) {
        return
    }

    if ($DownloadOnly) {
        return $downloadedFile
    }

    $targetFiles = Get-ChildItem -Path $targetDriverDir -Recurse -File -ErrorAction SilentlyContinue
    $extraContent = if (Test-Path -Path $driverDir -PathType Container) {
        Get-ChildItem -Path $driverDir -Force -ErrorAction SilentlyContinue |
            Where-Object { $_.Name -ne 'pvscsi' } |
            Select-Object -First 1
    }

    if ((-not $targetFiles) -or $extraContent) {
        $tempExpandDir = Join-Path ([System.IO.Path]::GetTempPath()) ("WinPEDrivers-VMwareAMD64-{0}" -f [guid]::NewGuid().Guid)

        try {
            if (Test-Path -Path $driverDir -PathType Container) {
                Write-Verbose "[$($MyInvocation.MyCommand.Name)] Resetting '$driverDir' before copying VMware pvscsi drivers."
                Get-ChildItem -Path $driverDir -Force -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force
            }
            else {
                New-Item -ItemType Directory -Path $driverDir -Force | Out-Null
            }

            New-Item -ItemType Directory -Path $tempExpandDir -Force | Out-Null
            Write-HostDateTimeDarkGray -Message "Expanding '$targetPath' to '$targetDriverDir'"
            Write-Verbose "[$($MyInvocation.MyCommand.Name)] Expanding '$($package.FileName)' to temporary directory '$tempExpandDir'"
            Expand-WinPEDriverPackageVMwareTools -Path $targetPath -DestinationPath $tempExpandDir | Out-Null

            $sourceDriverDir = Join-Path $tempExpandDir $relativeSourcePath
            if (-not (Test-Path -Path $sourceDriverDir -PathType Container)) {
                throw "Expected VMware pvscsi driver directory was not found: $sourceDriverDir"
            }

            New-Item -ItemType Directory -Path $targetDriverDir -Force | Out-Null
            Write-Verbose "[$($MyInvocation.MyCommand.Name)] Copying VMware pvscsi drivers from '$sourceDriverDir' to '$targetDriverDir'"
            Copy-Item -Path (Join-Path $sourceDriverDir '*') -Destination $targetDriverDir -Recurse -Force
        }
        finally {
            if (Test-Path -Path $tempExpandDir -PathType Container) {
                Write-Verbose "[$($MyInvocation.MyCommand.Name)] Removing temporary directory '$tempExpandDir'"
                Remove-Item -Path $tempExpandDir -Recurse -Force
            }
        }
    }
    else {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] '$targetDriverDir' already contains VMware pvscsi drivers. Skipping expansion."
    }

    $downloadedFile
}