private/Save-WinPEDriverPackageHp.ps1

#Requires -PSEdition Core

function Save-WinPEDriverPackageHp {
    <#
    .SYNOPSIS
        Downloads and expands an HP WinPE driver package
 
    .DESCRIPTION
        Downloads an HP SoftPaq executable to the OSDeployCore download cache and verifies
        its SHA256 checksum through Invoke-WinPEDriverPackageDownload. Unless DownloadOnly
        is specified, the function silently extracts the package into the architecture-specific
        managed architecture-specific winpedrivers folder when that folder contains no files. A nonzero
        extractor exit code is treated as an error only when no files were extracted.
 
    .PARAMETER DriverPackage
        Specifies the OSDeployWinPEDriver.Package object to download. The object supplies
        the package name, version, architecture, URIs, filename, and SHA256 checksum.
 
    .PARAMETER Force
        Downloads the package again even when a cached file passes checksum validation.
 
    .PARAMETER DownloadOnly
        Returns after downloading the executable without running the self-extractor.
 
    .EXAMPLE
        PS> $package = Get-WinPEDriverPackageCore | Where-Object Name -Match '^HP' | Select-Object -First 1; Save-WinPEDriverPackageHp -DriverPackage $package
 
        Downloads the first HP package and extracts it when its managed driver folder contains no files.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.IO.FileInfo. Returns the downloaded executable, or no object when the download fails.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-08-28
 
        Assumes the SoftPaq supports the /s, /e, and /f extraction arguments.
 
    .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)"

    # Download
    $downloadedFile = Invoke-WinPEDriverPackageDownload `
        -Uri             $package.DownloadUri `
        -DestinationPath $targetPath `
        -SearchUri       $package.UpdateUri `
        -ExpectedSHA256  $package.Checksums.SHA256 `
        -Force:$Force

    if (-not $downloadedFile) {
        return
    }

    if ($DownloadOnly) {
        return $downloadedFile
    }

    # Expand via self-extractor (/s = silent, /e = extract, /f = folder)
    $expandedFiles = Get-ChildItem -Path $driverDir -Recurse -File -ErrorAction SilentlyContinue
    if (-not $expandedFiles) {
        if (-not (Test-Path -Path $driverDir)) {
            New-Item -ItemType Directory -Path $driverDir -Force | Out-Null
        }
        Write-HostDateTimeDarkGray -Message "Expand: $targetPath"
        Write-HostDateTimeDarkGray -Message "Output: $driverDir"
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Running self-extractor '$($package.FileName)'"
        $proc = Start-Process -FilePath $targetPath `
            -ArgumentList "/s /e /f `"$driverDir`"" `
            -NoNewWindow -Wait -PassThru
        if ($proc.ExitCode -ne 0) {
            # Self-extractors often return non-zero even on success; verify by checking files
            $expandedAfter = Get-ChildItem -Path $driverDir -Recurse -File -ErrorAction SilentlyContinue
            if (-not $expandedAfter) {
                Write-Error "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Self-extractor exited $($proc.ExitCode) and no files found in '$driverDir'"
            }
            else {
                Write-Verbose "[$($MyInvocation.MyCommand.Name)] Self-extractor exited $($proc.ExitCode) but files found. Continuing."
            }
        }
    }
    else {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] '$driverDir' already contains expanded files. Skipping expansion."
    }

    $downloadedFile
}