Skip to content

Latest commit

 

History

History
158 lines (116 loc) · 10.9 KB

README.md

File metadata and controls

158 lines (116 loc) · 10.9 KB

Dumplings.InstallerParsers

Dumplings.InstallerParsers provides process-isolated static parsers for Windows installer formats whose implementations use GPL-compatible licenses. It is consumed by Dumplings.PackageModule through a JSON command-line boundary.

The parsers inspect untrusted installer bytes through bounded reads. They return product metadata, scope, registry writes, associations, nested payload evidence, and structured diagnostics.

Requirements

  • Windows
  • PowerShell 7.4 or later
  • The pinned managed dependencies distributed with the submodule

CLI

The CLI loads only the requested family. Inno keeps format/catalog decoding, Pascal Script analysis, and payload extraction in nested InnoFormat, InnoScript, and InnoPayload modules. Setup Factory separates project records, action interpretation, and containers into SetupFactoryProject, SetupFactoryActions, and SetupFactoryContainer. Public commands stay in the original family modules. Nested commands are internal and are not added to the caller's global command table. Parsed contexts are passed explicitly, and each layer owns its streams and temporary resources.

Cli.ps1 is the stable integration boundary. It writes one compact JSON value to standard output, writes a failure message to standard error, and exits with code 0 on success or 1 on failure.

$Json = & pwsh -NoProfile -File .\Cli.ps1 `
  -Action NSIS.GetInfo `
  -Path C:\Installers\setup.exe

if ($LASTEXITCODE -ne 0) {
  throw 'Installer parsing failed'
}

$Info = $Json | ConvertFrom-Json

Expansion actions return extracted paths or expansion evidence as JSON and always enforce parser-specific output limits:

& pwsh -NoProfile -File .\Cli.ps1 `
  -Action NSIS.Expand `
  -Path C:\Installers\setup.exe `
  -DestinationPath C:\Analysis\NSIS `
  -Name '*.msi' `
  -ExternalDataPath C:\Installers\setup1.bin,C:\Installers\setup2.bin `
  -CollisionAction Rename `
  -MaximumExpandedBytes 1GB

Name is optional for every expansion action. Omitting it selects all catalogued files. The CLI defaults to non-interactive CollisionAction Rename (file (1).ext). Direct calls and interactive PackageModule bridge calls additionally accept Prompt. No question is shown until the parser encounters an existing or already-reserved output path. Interactive bridge calls inherit the parent console while returning JSON through a separate temporary result file. Paths are resolved against PowerShell's current filesystem location before crossing the JSON/.NET boundary.

Keep informational output off standard output to preserve the JSON contract. Return conditions through Diagnostics. Use the CLI error path only when an operation cannot return a valid result.

Actions

Action Purpose Additional parameters
NSIS.GetInfo Parse NSIS layout, commands, registry writes, payload evidence, and product metadata. Path, optional Architecture, Scope
NSIS.Expand Expand selected embedded or NSISBI external EW_EXTRACTFILE payload records from solid, non-solid, or MTW archives. Path, optional DestinationPath, Name, CollisionAction, ExternalDataPath, MaximumExpandedBytes
NSIS.GetInstallerSwitchInfo Extract explicit command-line switch handling evidence. Path
NSIS.TestElectronBuilder Test whether the NSIS installer was generated by electron-builder. Path
NSIS.GetElectronBuilderInfo Parse electron-builder architecture, scope, and package evidence. Path, optional Architecture
Inno.GetInfo Parse Inno Setup metadata, registry writes, architecture, scope, and payload evidence. Path, optional Architecture, IncludePascalScriptAnalysis, IncludeDisassembly, MaximumDisassemblyCharacters
Inno.GetFormatInfo Identify the Inno edition, character mode, structure version, and selected parser routes. Path
Inno.GetPascalScriptInfo Parse compiled IFPS types, globals, functions, call edges, imports, constants, and manifest-relevant effects, with optional bounded disassembly. Path, optional IncludeDisassembly, MaximumDisassemblyCharacters
Inno.Expand Expand selected Inno payload files statically, including external disk slices supplied by the caller. Path, optional DestinationPath, Name, Language, CollisionAction, DiskSourcePath, MaximumExpandedBytes
AdvancedInstaller.GetInfo Parse the Advanced Installer bootstrapper catalog and nested MSI selection evidence. Path
AdvancedInstaller.Expand Expand catalog-selected payloads. Path, optional DestinationPath, Name, CollisionAction
QtInstallerFramework.GetFormatInfo Identify the Qt IFW generation, framework version, media role, capabilities, and selected parser routes. Path
QtInstallerFramework.GetInfo Parse Qt Installer Framework trailer, metadata, packages, operations, scope, and identity. Path
QtInstallerFramework.Expand Expand selected Qt IFW resources and archives. Path, optional DestinationPath, Name, CollisionAction, MaximumExpandedBytes
SetupFactory.GetInfo Parse Setup Factory 3.1 Crusher companion media, Setup Factory 4-10 outer and installed-file catalogs, Setup Factory 5/6 product and built-in uninstall blocks, Setup Factory 7-10 session variables, literal registry evidence, and bundled prerequisites. Path
SetupFactory.Expand Expand selected installed files, or outer bootstrap records with RawEntries. Path, optional DestinationPath, Name, RawEntries, CollisionAction, MaximumExpandedBytes

The ValidateSet in Cli.ps1 is authoritative. Add a CLI action whenever a new public parser operation must cross the PackageModule boundary.

Architecture

PackageModule (Apache-2.0)
  InstallerBridge.psm1
      |
      | starts pwsh and exchanges JSON
      v
InstallerParsers
  Cli.ps1 (GPL-3.0-or-later)
      +-- Libraries/Infrastructure (shared MIT mechanics)
      `-- Libraries/Installers (one family loaded per action)

The CLI loads shared infrastructure before the selected parser:

  1. Runtime.psm1 loads pinned assemblies and auditable C# helpers once per process.
  2. Binary.psm1 provides bounded reads, ranges, pattern search, CRC, and stream copying.
  3. FileSystem.psm1 resolves PowerShell filesystem paths and rejects extraction-root escapes.
  4. Archive.psm1 provides bounded compression, archive entry access, and extraction.
  5. PE.psm1 resolves PE headers, sections, resources, overlays, and metadata.
  6. InstallerDiagnostics.psm1 validates, merges, resolves, and renders structured parser diagnostics.
  7. InstallerEvidence.psm1 evaluates bounded conditions and interprets explicit protocol and file-extension registry writes.
  8. The selected format module constructs its canonical identity, ARP, and diagnostic result properties directly.

Shared MIT files remain file-level MIT exceptions in PackageModule. Full mirrored files stay byte-identical. The two shared filesystem helper function bodies also stay identical even though PackageModule's filesystem module contains additional task utilities. Format-specific code stays in its parser module.

Parser Contract

  • Identify formats from validated magic, headers, tables, resources, and registry records. Filename extensions and arbitrary strings are insufficient.
  • Open the installer once per operation and pass bounded streams or parsed layouts to internal functions.
  • Validate every offset, size, count, pointer, decompressed length, and extraction path before use.
  • Preserve caller-owned stream position and ownership where a stream parameter is supported.
  • Return context-neutral structured diagnostics for unresolved, conditional, unsupported, ambiguous, or invalid evidence.
  • Keep Suggestions and SuggestedNextSteps for actions. Do not encode actions as diagnostics.
  • Never invoke an installer, extracted executable, external extractor, or network endpoint.

Aggregate Get-*Info results begin with Path, InstallerType, ProductCode, UpgradeCode, DisplayName, DisplayVersion, Publisher, Scope, DefaultInstallLocation, WritesAppsAndFeaturesEntry, AppsAndFeaturesProductCode, AppsAndFeaturesInstallerType, Diagnostics, and UnresolvedFields. Results omit duplicate aliases such as ProductName and ProductVersion. The caller assigns diagnostic scenarios, levels, and blocking decisions with Resolve-InstallerDiagnostics, then renders them with Write-InstallerDiagnostics at the workflow boundary.

Detailed binary layouts and parser workflows live in the Dumplings analyze-winget-installer skill.

Development

Add or change format behavior under Libraries/Installers. Mechanical operations that are useful to more than one parser belong in Libraries/Infrastructure and must be mirrored into PackageModule.

When adding a CLI action:

  1. Add it to Cli.ps1's ValidateSet.
  2. Import only the required parser in the action branch.
  3. Return a JSON-serializable object without incidental output.
  4. Add direct parser tests and PackageModule bridge contract tests.
  5. Document the action and its licensing.

Testing

From the Dumplings root:

Invoke-Pester .\Modules\InstallerParsers\Tests

Run a focused parser suite:

Invoke-Pester .\Modules\InstallerParsers\Tests\NSIS
Invoke-Pester .\Modules\InstallerParsers\Tests\Inno

Also run PackageModule bridge tests after changing the CLI contract:

Invoke-Pester .\Modules\PackageModule\Tests\WinGet\InstallerBridge.Contracts.Tests.ps1
Invoke-Pester .\Modules\PackageModule\Tests\WinGet\InstallerBridge.Regressions.Tests.ps1

Each implemented parser family owns one directory below Tests. Byte-identical fixture helpers and reusable generated-fixture builders live under non-discoverable Tests/Support. Downloaded fixtures use canonical paths below ../Dumplings-TestFixtures/Installers, curated media uses Builders, and synthetic or extracted output uses $TestDrive. Do not depend on user Downloads, temporary cleanup-sensitive paths, or executing installers.

Licensing

Licensing is file-specific:

Files License
Cli.ps1, Libraries/Installers/{NSIS,NSISFormat,NSISSimulation,Inno,QtInstallerFramework,SetupFactory}.psm1, Libraries/Installers/{NSIS,Inno,QtInstallerFramework,SetupFactory}FormatCatalog.psd1 GPL-3.0-or-later
Libraries/Installers/AdvancedInstaller.psm1 GPL-2.0
Libraries/Infrastructure/{Runtime,Binary,FileSystem,Archive,PE,InstallerEvidence}.psm1 and shared infrastructure sources MIT, as marked in each file

Third-party format references, included assemblies, and source-derived components are documented in Assets\THIRD-PARTY-NOTICES.md. The asset layout is described in Assets\README.md. Preserve file headers and license boundaries when moving or reusing code.