Files
pebrel/scripts/prepare-windows-runtime.ps1
T

100 lines
4.4 KiB
PowerShell

[CmdletBinding()]
param(
[Parameter(Mandatory = $true)][string] $Destination,
[string] $ArchivePath,
[ValidateSet('x64', 'arm64')][string] $Architecture = 'x64'
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
$OutputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
# Reuse the Microsoft 1.22 runtime pair already shipped with Pebrel's predecessor.
# Only these two redistributables are extracted, never the older application.
$archiveHash = '9B2413144C0434E29749CCBD5C2B0F93E930DAFD22634DD70D34B763037E0DA4'
$sourceUrl = 'https://github.com/Kuddev/pebrel/releases/download/v1.5.0/NebulaTerminal-v1.5.0-windows-x64.zip'
$expected = [ordered]@{
'conpty.dll' = '375BFB0479B6C53836AB307E3F9FD17BEDBD733F2E9690943D0F12E72FB80777'
'OpenConsole.exe' = '55B18996761C88C351820E82508E05AB0EC2194AEEAD20724FDFAEEDEC076EF4'
}
$entries = @{
'conpty.dll' = 'runtime\conpty.dll'
'OpenConsole.exe' = 'runtime\OpenConsole.exe'
}
$archiveName = 'pebrel-conpty-source-v1.5.0.zip'
$machine = 0x8664
if ($Architecture -eq 'arm64') {
# Microsoft MIT-licensed redistributables; the NuGet declares build 17763+.
# Keep the previously shipped x64 runtime unchanged.
$sourceUrl = 'https://api.nuget.org/v3-flatcontainer/microsoft.windows.console.conpty/1.24.260710001/microsoft.windows.console.conpty.1.24.260710001.nupkg'
$archiveName = 'pebrel-conpty-source-1.24.260710001.nupkg'
$archiveHash = '175640566A3B59C4B132070EE96C2C77E5AB7EDD2E92732A5EB3610BBF63D90E'
$expected = [ordered]@{
'conpty.dll' = 'DB3D173640B172BAFD42D5B541B638A9AEEC1C7D0E40DD636BF02822A32C912C'
'OpenConsole.exe' = 'ED7622FD0D3BEDC9AB9F122F5E58EDF0DEF9E7999224F52DD395BA9F54EDBE09'
}
$entries = @{
'conpty.dll' = 'runtimes/win-arm64/native/conpty.dll'
'OpenConsole.exe' = 'build/native/runtimes/arm64/OpenConsole.exe'
}
$machine = 0xAA64
}
function Assert-RuntimeMachine([string] $Path) {
$bytes = [IO.File]::ReadAllBytes($Path)
if ($bytes.Length -lt 64 -or $bytes[0] -ne 0x4D -or $bytes[1] -ne 0x5A) {
throw "Invalid PE runtime: $Path"
}
$offset = [BitConverter]::ToInt32($bytes, 0x3C)
if ($offset -lt 64 -or $offset -gt $bytes.Length - 6 -or
[BitConverter]::ToUInt32($bytes, $offset) -ne 0x4550 -or
[BitConverter]::ToUInt16($bytes, $offset + 4) -ne $machine) {
throw "Runtime PE architecture does not match $Architecture`: $Path"
}
}
if ([string]::IsNullOrWhiteSpace($ArchivePath)) {
$ArchivePath = Join-Path ([System.IO.Path]::GetTempPath()) $archiveName
if (-not (Test-Path -LiteralPath $ArchivePath -PathType Leaf)) {
Invoke-WebRequest -Uri $sourceUrl -OutFile $ArchivePath -UseBasicParsing -TimeoutSec 120
}
}
if ((Get-FileHash -LiteralPath $ArchivePath -Algorithm SHA256).Hash -ne $archiveHash) {
throw 'The pinned runtime source archive failed SHA256 verification.'
}
Add-Type -AssemblyName System.IO.Compression.FileSystem
$archive = [System.IO.Compression.ZipFile]::OpenRead((Resolve-Path $ArchivePath).Path)
try {
New-Item -ItemType Directory -Path $Destination -Force | Out-Null
foreach ($name in $expected.Keys) {
$target = Join-Path $Destination $name
if ((Test-Path -LiteralPath $target -PathType Leaf) -and
(Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash -eq $expected[$name]) {
Assert-RuntimeMachine $target
continue
}
$entry = $archive.GetEntry($entries[$name])
if ($null -eq $entry) { throw "Runtime archive is missing $($entries[$name])" }
$temporary = "$target.$([guid]::NewGuid().ToString('N')).tmp"
try {
$inputStream = $entry.Open()
try {
$outputStream = [System.IO.File]::Create($temporary)
try { $inputStream.CopyTo($outputStream) } finally { $outputStream.Dispose() }
} finally { $inputStream.Dispose() }
if ((Get-FileHash -LiteralPath $temporary -Algorithm SHA256).Hash -ne $expected[$name]) {
throw "The pinned $name failed SHA256 verification."
}
Assert-RuntimeMachine $temporary
Move-Item -LiteralPath $temporary -Destination $target -Force
} finally {
if (Test-Path -LiteralPath $temporary) { Remove-Item -LiteralPath $temporary }
}
}
} finally { $archive.Dispose() }
foreach ($name in $expected.Keys) {
Write-Output "$name SHA256 $($expected[$name])"
}