private/Expand-WinPEDriverPackageCab.ps1

#Requires -PSEdition Core

function Expand-WinPEDriverPackageCab {
    <#
    .SYNOPSIS
        Expands a cabinet archive by using expand.exe
 
    .DESCRIPTION
        Validates that the source cabinet exists, creates the destination directory when
        needed, and invokes the Windows expand.exe utility to extract every file from the
        archive. A missing source or nonzero expand.exe exit code causes a terminating error.
 
    .PARAMETER Path
        Specifies the path to the cabinet archive. The path must resolve before the
        destination directory is created.
 
    .PARAMETER DestinationPath
        Specifies the directory that receives the extracted files. The function creates
        the directory when it does not exist.
 
    .EXAMPLE
        PS> Expand-WinPEDriverPackageCab -Path 'C:\Drivers\WinPE.cab' -DestinationPath 'C:\Drivers\WinPE'
 
        Expands every file in WinPE.cab to C:\Drivers\WinPE and returns the destination
        directory.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.IO.DirectoryInfo. Returns the destination directory after expand.exe
        completes successfully.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-08-28
 
        Dependencies:
          Executables: expand.exe
          DotNet Classes: System.IO.DirectoryInfo, System.IO.FileNotFoundException,
                          System.Management.Automation.ErrorCategory,
                          System.Management.Automation.ErrorRecord
    #>

    [CmdletBinding()]
    [OutputType([System.IO.DirectoryInfo])]
    param (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Path,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$DestinationPath
    )

    # Fail before creating output when the source archive cannot be resolved.
    if (-not (Test-Path -Path $Path)) {
        $PSCmdlet.ThrowTerminatingError(
            [System.Management.Automation.ErrorRecord]::new(
                [System.IO.FileNotFoundException]::new("Cabinet file not found: $Path"),
                'CabFileNotFound',
                [System.Management.Automation.ErrorCategory]::ObjectNotFound,
                $Path
            )
        )
    }

    if (-not (Test-Path -Path $DestinationPath)) {
        New-Item -ItemType Directory -Path $DestinationPath -Force | Out-Null
    }

    Write-Verbose "[$($MyInvocation.MyCommand.Name)] Extracting cab: $Path -> $DestinationPath"
    $expandExe = Join-Path $env:SystemRoot 'System32\expand.exe'

    $process = Start-Process -FilePath $expandExe `
        -ArgumentList "`"$Path`"", '-F:*', "`"$DestinationPath`"" `
        -NoNewWindow -Wait -PassThru

    # Native extraction errors do not raise PowerShell exceptions, so inspect the exit code explicitly.
    if ($process.ExitCode -ne 0) {
        $PSCmdlet.ThrowTerminatingError(
            [System.Management.Automation.ErrorRecord]::new(
                [System.InvalidOperationException]::new(
                    "expand.exe failed with exit code $($process.ExitCode) for '$Path'"
                ),
                'CabExpandFailed',
                [System.Management.Automation.ErrorCategory]::InvalidResult,
                $Path
            )
        )
    }

    Write-Verbose "[$($MyInvocation.MyCommand.Name)] Cab extraction complete: $DestinationPath"
    Get-Item -Path $DestinationPath
}