XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension.NetCore.InputSimulator

【DLL】XFE各类拓展的模拟键盘输入

公开
关注 0 Fork 0 Star 0
UTF-8
[CmdletBinding()]
param(
    [string]$PackageDirectory = (Join-Path $PSScriptRoot '..\artifacts\driver-umdf'),
    [switch]$AllowUnsigned,
    [Alias('AllowLocalDevelopment')][switch]$AllowSelfSigned,
    [switch]$RequireTimestamp
)
$ErrorActionPreference = 'Stop'
if ($AllowUnsigned -and ($AllowSelfSigned -or $RequireTimestamp)) { throw 'Choose unsigned or signed mode, not both.' }
$source = (Resolve-Path -LiteralPath $PackageDirectory).Path
$destination = Join-Path $PSScriptRoot 'payload\win-x64'
$files = @('XfeInputDriver.dll', 'XfeInput.inf', 'XfeInput.cat', 'XfeInputSetup.exe')
foreach ($file in $files) {
    if (!(Test-Path -LiteralPath (Join-Path $source $file) -PathType Leaf)) { throw "Missing driver payload: $file" }
}
$signed = !$AllowUnsigned
$kind = 'unsigned'
$certificate = $null
$timestamped = $signed
if ($signed) {
    foreach ($file in @('XfeInputDriver.dll', 'XfeInput.cat', 'XfeInputSetup.exe')) {
        $signature = Get-AuthenticodeSignature -LiteralPath (Join-Path $source $file)
        if ($signature.Status -ne 'Valid') { throw "Invalid or untrusted signature: $file ($($signature.Status)). Build signed packages on a machine that trusts the publisher." }
        if ($certificate -and $signature.SignerCertificate.Thumbprint -ne $certificate.Thumbprint) { throw 'All payload binaries must use the same publisher certificate.' }
        $certificate = $signature.SignerCertificate
        if (!$signature.TimeStamperCertificate) { $timestamped = $false }
    }
    if ($RequireTimestamp -and !$timestamped) { throw 'All signed payload files must have a verified timestamp.' }
    if ($certificate.NotAfter -le (Get-Date) -or $certificate.NotBefore -gt (Get-Date)) { throw 'Publisher certificate is not currently valid.' }
    $usage = @(($certificate.Extensions | Where-Object { $_.Oid.Value -eq '2.5.29.37' }).EnhancedKeyUsages | ForEach-Object { $_.Value })
    $constraints = $certificate.Extensions | Where-Object { $_.Oid.Value -eq '2.5.29.19' }
    if ($usage.Count -ne 1 -or $usage[0] -ne '1.3.6.1.5.5.7.3.3' -or !$constraints -or $constraints.CertificateAuthority) {
        throw 'Use a non-CA certificate restricted to code signing.'
    }
    $selfSigned = [Convert]::ToHexString($certificate.SubjectName.RawData) -eq [Convert]::ToHexString($certificate.IssuerName.RawData)
    if ($selfSigned -and !$AllowSelfSigned) { throw 'A self-signed publisher requires -AllowSelfSigned; it is not a publicly trusted release.' }
    $kind = if ($selfSigned) { 'self-signed' } else { 'trusted-publisher' }
    $assets = Get-Content -LiteralPath (Join-Path $PSScriptRoot 'obj\project.assets.json') -Raw | ConvertFrom-Json
    $signTool = $null
    foreach ($folder in $assets.packageFolders.PSObject.Properties.Name) {
        $candidate = Join-Path $folder 'microsoft.windows.sdk.cpp\10.0.26100.1\c\bin\10.0.26100.0\x64\signtool.exe'
        if (Test-Path -LiteralPath $candidate) { $signTool = $candidate; break }
    }
    if (!$signTool) { throw 'Run Build-Driver.ps1 first to restore verification tools.' }
    foreach ($file in @('XfeInputDriver.dll', 'XfeInput.inf')) {
        & $signTool verify /pa /c (Join-Path $source 'XfeInput.cat') (Join-Path $source $file)
        if ($LASTEXITCODE) { throw "Signed catalog membership validation failed: $file" }
    }
}
$null = New-Item -ItemType Directory -Path $destination -Force
$hashes = [ordered]@{}
foreach ($file in $files) {
    Copy-Item -LiteralPath (Join-Path $source $file) -Destination (Join-Path $destination $file) -Force
    $hashes[$file] = (Get-FileHash -LiteralPath (Join-Path $destination $file) -Algorithm SHA256).Hash
}
if ($signed) {
    [IO.File]::WriteAllBytes((Join-Path $destination 'publisher.cer'), $certificate.RawData)
    $hashes['publisher.cer'] = (Get-FileHash -LiteralPath (Join-Path $destination 'publisher.cer') -Algorithm SHA256).Hash
} elseif (Test-Path -LiteralPath (Join-Path $destination 'publisher.cer')) {
    Remove-Item -LiteralPath (Join-Path $destination 'publisher.cer')
}
# Remove only the obsolete generated KMDF payload, never arbitrary user files.
if (Test-Path -LiteralPath (Join-Path $destination 'XfeInput.sys')) { Remove-Item -LiteralPath (Join-Path $destination 'XfeInput.sys') }
$manifest = [ordered]@{
    protocol = 1; signed = $signed; signingKind = $kind; timestamped = $timestamped
    certificateExpires = if ($signed) { $certificate.NotAfter.ToUniversalTime().ToString('o') } else { $null }
    files = $hashes
}
[IO.File]::WriteAllText((Join-Path $destination 'payload.json'), ($manifest | ConvertTo-Json -Depth 3), [Text.UTF8Encoding]::new($false))
$properties = "<Project><PropertyGroup><DriverPayloadSigned>$($signed.ToString().ToLowerInvariant())</DriverPayloadSigned><DriverPayloadSigningKind>$kind</DriverPayloadSigningKind></PropertyGroup></Project>"
[IO.File]::WriteAllText((Join-Path $destination 'payload.props'), $properties, [Text.UTF8Encoding]::new($false))
Write-Host "Embedded payload prepared ($kind): $destination"