From 63ae7540e0bdc2faf1f799f6d1c1348bab8178f0 Mon Sep 17 00:00:00 2001 From: Simone Date: Wed, 29 Apr 2026 23:20:16 +0200 Subject: [PATCH] initial: nsParser plugin 1.0.1 --- .editorconfig | 24 + .gitattributes | 52 ++ .github/ISSUE_TEMPLATE/bug_report.yml | 76 +++ .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.yml | 32 + .github/PULL_REQUEST_TEMPLATE.md | 31 + .github/workflows/build.yml | 66 ++ .github/workflows/release.yml | 99 +++ .gitignore | 63 ++ CHANGELOG.md | 19 + CONTRIBUTING.md | 137 +++++ LICENSE | 21 + README.md | 129 ++++ README_IT.md | 288 +++++++++ SECURITY.md | 40 ++ VERSION | 1 + build_plugin.py | 679 +++++++++++++++++++++ dist/amd64-unicode/nsParser.dll | Bin 0 -> 103424 bytes dist/x86-ansi/nsParser.dll | Bin 0 -> 85504 bytes dist/x86-unicode/nsParser.dll | Bin 0 -> 85504 bytes src/api.h | 83 +++ src/nsParser.c | 144 +++++ src/nsParser.def | 4 + src/nsParser.h | 9 + src/nsParser.vcxproj | 211 +++++++ src/nsis_tchar.h | 229 +++++++ src/pluginapi.c | 294 +++++++++ src/pluginapi.h | 104 ++++ tools/build.cmd | 179 ++++++ 29 files changed, 3022 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 README_IT.md create mode 100644 SECURITY.md create mode 100644 VERSION create mode 100644 build_plugin.py create mode 100644 dist/amd64-unicode/nsParser.dll create mode 100644 dist/x86-ansi/nsParser.dll create mode 100644 dist/x86-unicode/nsParser.dll create mode 100644 src/api.h create mode 100644 src/nsParser.c create mode 100644 src/nsParser.def create mode 100644 src/nsParser.h create mode 100644 src/nsParser.vcxproj create mode 100644 src/nsis_tchar.h create mode 100644 src/pluginapi.c create mode 100644 src/pluginapi.h create mode 100644 tools/build.cmd diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..55629c5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,24 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +[*.{yml,yaml,json}] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[*.{cmd,bat,ps1}] +end_of_line = crlf + +[*.{nsi,nsh,sln,vcxproj,filters}] +end_of_line = crlf + +[Makefile] +indent_style = tab diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..20b175b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,52 @@ +# Normalizzazione line endings +* text=auto eol=lf + +# File di codice +*.c text eol=lf +*.cpp text eol=lf +*.h text eol=lf +*.hpp text eol=lf +*.def text eol=lf +*.py text eol=lf +*.ps1 text eol=lf +*.cmd text eol=crlf +*.bat text eol=crlf + +# NSIS +*.nsi text eol=crlf +*.nsh text eol=crlf + +# Markdown / docs / config +*.md text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.json text eol=lf +*.txt text eol=lf +*.xml text eol=lf + +# Visual Studio (CRLF richiesto) +*.sln text eol=crlf +*.vcxproj text eol=crlf merge=union +*.filters text eol=crlf merge=union +*.rc binary +*.rc2 binary + +# Binari +*.dll binary +*.exe binary +*.lib binary +*.obj binary +*.pdb binary +*.zip binary +*.7z binary +*.png binary +*.ico binary +*.gif binary +*.jpg binary +*.jpeg binary +*.bmp binary +*.pdf binary + +# Linguistic detection (GitHub Linguist / Gitea analogo) +*.nsi linguist-language=NSIS +*.nsh linguist-language=NSIS diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..7599f2a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,76 @@ +name: Bug Report +description: Segnala un bug riproducibile +title: "[Bug]: " +labels: ["bug", "triage"] +body: + - type: markdown + attributes: + value: | + Grazie per la segnalazione. Compila i campi sotto per aiutarci a riprodurre il problema. + + - type: input + id: plugin-version + attributes: + label: Versione plugin + description: Contenuto del file VERSION o tag della release scaricata + placeholder: "1.6.0" + validations: + required: true + + - type: dropdown + id: architecture + attributes: + label: Architettura DLL usata + options: + - x86-ansi + - x86-unicode + - amd64-unicode + - non so / multiple + validations: + required: true + + - type: input + id: nsis-version + attributes: + label: Versione NSIS + placeholder: "3.10" + validations: + required: true + + - type: input + id: os + attributes: + label: Sistema operativo + placeholder: "Windows 11 23H2 x64" + validations: + required: true + + - type: textarea + id: repro + attributes: + label: Passi per riprodurre + description: Script .nsi minimale che riproduce il problema + render: nsis + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Comportamento atteso + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Comportamento osservato + description: Includi messaggi di errore esatti, output del log NSIS, screenshot + validations: + required: true + + - type: textarea + id: additional + attributes: + label: Note aggiuntive + description: Qualunque altra informazione utile (workaround tentati, ecc.) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..085f54c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Domande generali + url: https://gitea.emulab.it/Simone/nsis-plugin-nsparser/issues?type=question + about: Per domande di utilizzo che non sono bug, apri una issue con label "question" + - name: Security + url: https://gitea.emulab.it/Simone/nsis-plugin-nsparser/security/advisories/new + about: Segnala vulnerabilità di security in privato (non aprire issue pubbliche) diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..fae6d8d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,32 @@ +name: Feature Request +description: Suggerisci una nuova funzionalità o miglioramento +title: "[Feature]: " +labels: ["enhancement"] +body: + - type: textarea + id: problem + attributes: + label: Problema / Caso d'uso + description: Quale problema vorresti risolvere? Quale workflow vuoi abilitare? + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposta + description: Come dovrebbe funzionare? Includi esempio di API/uso negli script NSIS se possibile. + render: nsis + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternative considerate + description: Altri approcci che hai valutato e perché sono stati scartati + + - type: textarea + id: additional + attributes: + label: Note aggiuntive diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..3758b50 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,31 @@ +## Descrizione + + + +## Tipo di Modifica + +- [ ] Bug fix (modifica non breaking che risolve un problema) +- [ ] Feature (modifica non breaking che aggiunge funzionalità) +- [ ] Breaking change (fix o feature che rompe la compatibilità) +- [ ] Documentazione +- [ ] Build / CI + +## Architetture Testate + +- [ ] `x86-ansi` +- [ ] `x86-unicode` +- [ ] `amd64-unicode` + +## Checklist + +- [ ] Build completa senza warning: `python build_plugin.py` +- [ ] CHANGELOG.md aggiornato (sezione `[Unreleased]`) +- [ ] README / docs aggiornati se l'API è cambiata +- [ ] Esempi aggiornati se l'API è cambiata +- [ ] Conventional Commits rispettato +- [ ] Nessun file in `dist/` o `__pycache__/` committato +- [ ] Self-review completata + +## Note Aggiuntive + + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..7438999 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,66 @@ +# Build (GitHub) — pipeline CI primaria +# +# Strategia hosting: +# - Repo primario su Gitea (push iniziale) +# - Push mirror automatico Gitea -> GitHub +# - GitHub esegue TUTTA la CI (Gitea non esegue Actions) +# +# Trigger: +# - push su main (incluso quello propagato dal mirror Gitea) +# - PR aperte su GitHub +# - run manuale via UI + +name: Build + +on: + push: + branches: [main] + paths-ignore: + - '**.md' + - 'docs/**' + - 'examples/**' + pull_request: + branches: [main] + workflow_dispatch: + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + build: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + config: [x86-ansi, x86-unicode, x64-unicode] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Read VERSION + id: version + shell: pwsh + run: | + $v = (Get-Content VERSION -Raw).Trim() + "version=$v" | Out-File -FilePath $env:GITHUB_OUTPUT -Append + + - name: Build ${{ matrix.config }} + run: python build_plugin.py --configs ${{ matrix.config }} --verbosity minimal + + - name: Upload DLL + uses: actions/upload-artifact@v4 + with: + name: ${{ github.event.repository.name }}-${{ steps.version.outputs.version }}-${{ matrix.config }} + path: dist/** + if-no-files-found: error + retention-days: 30 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e4cf67d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,99 @@ +# Release (GitHub) — pipeline release primaria +# +# Triggerata quando un tag v* viene propagato dal mirror Gitea. +# Costruisce gli artifact per tutte le architetture e crea la GitHub Release. + +name: Release + +on: + push: + tags: ['v*'] + workflow_dispatch: + inputs: + tag: + description: 'Tag versione (es. v1.7.0)' + required: true + +permissions: + contents: write + +jobs: + build: + runs-on: windows-latest + strategy: + fail-fast: true + matrix: + config: [x86-ansi, x86-unicode, x64-unicode] + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - uses: microsoft/setup-msbuild@v2 + + - name: Build ${{ matrix.config }} + run: python build_plugin.py --config ${{ matrix.config }} + + - name: Determine version & arch + id: meta + shell: pwsh + run: | + $tag = "${{ github.ref_name }}" + if ([string]::IsNullOrEmpty($tag) -or $tag -eq "main") { $tag = "${{ inputs.tag }}" } + $v = $tag -replace '^v','' + $map = @{ 'x86-ansi' = 'x86-ansi'; 'x86-unicode' = 'x86-unicode'; 'x64-unicode' = 'amd64-unicode' } + $dir = $map['${{ matrix.config }}'] + echo "version=$v" >> $env:GITHUB_OUTPUT + echo "tag=$tag" >> $env:GITHUB_OUTPUT + echo "dir=$dir" >> $env:GITHUB_OUTPUT + + - name: Package + shell: pwsh + run: | + $name = "${{ github.event.repository.name }}-${{ steps.meta.outputs.version }}-${{ steps.meta.outputs.dir }}" + $stage = "stage/$name" + New-Item -ItemType Directory -Force -Path $stage | Out-Null + Copy-Item "dist/${{ steps.meta.outputs.dir }}/*" $stage -Recurse + Copy-Item README.md, LICENSE, VERSION, CHANGELOG.md $stage + if (Test-Path "include") { Copy-Item "include" $stage -Recurse } + if (Test-Path "examples") { Copy-Item "examples" $stage -Recurse } + Compress-Archive -Path "$stage/*" -DestinationPath "$name.zip" -Force + + - uses: actions/upload-artifact@v4 + with: + name: pkg-${{ matrix.config }} + path: '*.zip' + + publish: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + path: artifacts + merge-multiple: true + + - name: SHA256SUMS + run: | + cd artifacts + sha256sum *.zip > SHA256SUMS.txt + cat SHA256SUMS.txt + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + files: | + artifacts/*.zip + artifacts/SHA256SUMS.txt + generate_release_notes: true + body: | + **Repository primario**: vedi link Gitea nel README. + + Il mirror GitHub è generato automaticamente dal repo Gitea (sorgente di verità). + Per issue e PR aprire ticket sul repository primario Gitea. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c3a730 --- /dev/null +++ b/.gitignore @@ -0,0 +1,63 @@ +# Build output (src/ subdirs only — dist/ is tracked, contains pre-built DLLs) +bin/ +obj/ +Build/ +build/ + +# Visual Studio +*.user +*.suo +*.ncb +*.sdf +.vs/ +ipch/ +*.VC.db +*.VC.VC.opendb +*.opendb +*.aps +*.tlog +*.idb +*.pdb +*.ilk +*.exp +*.lib +*.obj + +# Python +__pycache__/ +*.pyc +*.pyo +.pytest_cache/ +*.egg-info/ +.venv/ +venv/ + +# Editor / IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +Thumbs.db +desktop.ini +.DS_Store + +# NSIS +*.nsh.bak + +# Logs +*.log +.logs/ + +# Sensitive +.env +.env.local +*.pem +*.key + +# Migration/automation scripts (temporary, contain tokens — never commit) +tools/t*.py +tools/check_*.py +tools/legacy/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..07b59de --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,19 @@ +# Changelog + +Tutte le modifiche rilevanti a questo progetto sono documentate in questo file. + +Il formato segue [Keep a Changelog](https://keepachangelog.com/it/1.0.0/), +e il progetto aderisce al [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [1.0.0] — 2026-04-29 + +### Added +- Prima release come repository indipendente +- Build script unificato (`build_plugin.py`) con CLI canonica +- CI/CD via GitHub Actions (mirror automatico Gitea → GitHub) +- Documentazione completa (README, CONTRIBUTING, SECURITY) + +[Unreleased]: https://gitea.emulab.it/Simone/nsis-plugin-nsparser/compare/v1.0.0...HEAD +[1.0.0]: https://gitea.emulab.it/Simone/nsis-plugin-nsparser/releases/tag/v1.0.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d22ef21 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,137 @@ +# Contribuire a nsParser + +Grazie per il tuo interesse a contribuire! + +> Repository primario: [https://gitea.emulab.it/Simone/nsis-plugin-nsparser](https://gitea.emulab.it/Simone/nsis-plugin-nsparser) +> Mirror GitHub: [https://github.com/systempal/nsis-plugin-nsparser](https://github.com/systempal/nsis-plugin-nsparser) (read-only — apri PR su Gitea) + +## Prerequisiti + +| Strumento | Versione | Note | +|-----------|----------|------| +| Visual Studio | 2022 / 2026 | Workload: Desktop development with C++ (toolset v143/v145) | +| Python | 3.7+ | Per `build_plugin.py` | +| Git | 2.30+ | Con supporto submoduli se applicabile | + +## Quick Start + +```powershell +git clone https://gitea.emulab.it/Simone/nsis-plugin-nsparser.git +cd nsis-plugin-nsparser +python build_plugin.py +``` + +Output in `dist/{x86-ansi,x86-unicode,amd64-unicode}/`. + +## Workflow Sviluppo + +### 1. Branch + +```powershell +git checkout -b feat/nome-feature # nuova feature +git checkout -b fix/descrizione-bug # bugfix +git checkout -b docs/aggiornamento # solo doc +git checkout -b chore/manutenzione # build, dipendenze +``` + +### 2. Commit + +Segui [Conventional Commits](https://www.conventionalcommits.org/it/v1.0.0/): + +``` +feat: aggiunge supporto per formato XYZ +fix: corregge crash su Windows 11 ARM +docs: aggiorna esempio di utilizzo +chore: aggiorna toolset MSVC +refactor: estrae logica parsing in funzione separata +test: aggiunge test per edge case +build: aggiorna script di build +ci: aggiorna workflow GitHub Actions +``` + +Breaking changes: + +``` +feat!: rinomina API Foo() in Bar() + +BREAKING CHANGE: Foo() rinominata in Bar(); aggiornare tutti i chiamanti. +``` + +### 3. Pull Request + +PR aperte verso il branch `main` su Gitea. Verifica: + +- [ ] Build completa senza warning per tutte le architetture: `python build_plugin.py` +- [ ] Esempi aggiornati se cambia l'API +- [ ] `CHANGELOG.md` aggiornato (sezione `[Unreleased]`) +- [ ] Documentazione aggiornata (README, docs/API.md se esiste) +- [ ] Conventional Commits rispettato +- [ ] Nessun file in `dist/` o `__pycache__/` committato + +## Build Script + +``` +python build_plugin.py [opzioni] +``` + +| Opzione | Default | Descrizione | +|---------|---------|-------------| +| `--config` | `all` | Architettura: `x86-ansi`, `x86-unicode`, `x64-unicode`, `all` | +| `--toolset` | `auto` | Visual Studio: `2022`, `2026`, `auto` (rileva il più recente) | +| `--jobs` | numero CPU | Thread paralleli per la build | +| `--clean` | false | Pulisce `dist/` prima di compilare | +| `--install-dir` | none | Copia DLL anche in `/{arch}/` (es. NSIS plugin folder) | +| `--verbose` | false | Output dettagliato (mostra comandi MSBuild) | + +Exit codes: +- `0` — Successo +- `1` — Errore di build +- `2` — Prerequisiti mancanti +- `3` — Argomenti invalidi + +## Release Workflow + +Le release sono automatiche via tag Git: + +```powershell +# 1. Aggiorna VERSION e CHANGELOG.md +echo "1.7.0" > VERSION +# (modifica CHANGELOG.md spostando entry da [Unreleased] a [1.7.0]) + +# 2. Commit +git add VERSION CHANGELOG.md +git commit -m "chore(release): v1.7.0" + +# 3. Tag annotato +git tag -a v1.7.0 -m "Release v1.7.0" + +# 4. Push +git push origin main +git push origin v1.7.0 +``` + +Il workflow `.github/workflows/release.yml` compilerà tutte le architetture +e creerà la release su Gitea con gli artifact ZIP allegati. Il mirror GitHub +riceverà automaticamente il tag. + +## Code Style + +- C/C++: stile coerente con il file modificato +- Python: PEP 8 (4 spazi indent, line length flessibile) +- Header file: `#include` ordinati: stdlib → Win32 → progetto +- Encoding: UTF-8 senza BOM (eccetto `.rc` che richiede UTF-16 LE) +- Line endings: LF in repo (`.gitattributes` normalizza) + +## Reporting Bug + +Apri una [issue](https://gitea.emulab.it/Simone/nsis-plugin-nsparser/issues/new) usando il template "Bug Report". +Includi: +- Versione plugin e architettura DLL usata +- Versione NSIS +- Sistema operativo +- Script `.nsi` minimale che riproduce il problema +- Output / errore esatto + +## Domande + +Per domande generali, apri una [issue](https://gitea.emulab.it/Simone/nsis-plugin-nsparser/issues) con label `question`. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e05be1c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Simone + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..83a7ea1 --- /dev/null +++ b/README.md @@ -0,0 +1,129 @@ +# nsParser NSIS Plugin + +Native C plugin for NSIS to extract values from large files, bypassing the NSIS_MAX_STRLEN limit (1 KB). + +--- + +## Problem Solved + +NSIS's built-in string functions are limited to `NSIS_MAX_STRLEN` (typically 1024 bytes). When reading configuration files, JSON, or INI files larger than this limit, the string is silently truncated. + +`nsParser` solves this by reading only the specific value requested, without loading the entire file into a string. + +--- + +## Build + +### Prerequisites + +- **Visual Studio 2022** (with "Desktop development with C++" workload) +- **Python 3.x** + +### Build script + +```powershell +python build_plugin.py +``` + +### Build options + +```powershell +python build_plugin.py --configs x86-unicode # Single architecture (x86-ansi|x86-unicode|x64-unicode|all) +python build_plugin.py --vs-version 2026 # Specific toolset (auto|2022|2026) +python build_plugin.py --clean # Clean dist/ before build +python build_plugin.py --rebuild # Force full rebuild +python build_plugin.py --verbosity detailed # Extended MSBuild output +python build_plugin.py --install-dir "C:\NSIS\Plugins" # Copy to additional NSIS directory +python build_plugin.py --list # List available configurations +``` + +--- + +## Usage in NSIS + +```nsis +!addplugindir "plugins\x86-unicode" + +Section + nsParser::Extract "C:\config.ini" "key" $0 + DetailPrint "Value: $0" +SectionEnd +``` + +--- + +## API + +### `nsParser::Extract` + +```nsis +nsParser::Extract "FilePath" "Key" $OutputVar +``` + +**Parameters:** + +| Parameter | Description | +|-----------|-------------| +| `FilePath` | Full path to the file to parse | +| `Key` | Key to search for (e.g. `version`, `path`) | +| `$OutputVar` | Variable to receive the extracted value | + +**Search logic:** + +The plugin searches for the pattern `Key=Value` or `Key = Value` in the file. If found, returns the value trimmed of leading/trailing whitespace. If not found, returns an empty string. + +**Buffer:** + +The value is extracted with a buffer of 32768 bytes, well beyond the NSIS_MAX_STRLEN limit. This allows reading long paths and embedded JSON strings. + +--- + +## Advantages + +- No dependency on the NSIS string size limit +- Reads only the requested value (efficient on large files) +- Handles `key=value` and `key = value` formats +- Thread-safe (no global state) +- Small binary size + +--- + +## Technical Implementation + +The plugin is written in C and uses a direct file reader via `ReadFile` (Win32). The algorithm: + +1. Opens the file with `CreateFile` (read-only, shared) +2. Reads the file in 8192-byte blocks +3. Scans each block for the pattern `Key=` or `Key =` +4. Extracts the value up to the first newline (`\n` or `\r\n`) +5. Trims leading/trailing whitespace +6. Returns the result via the NSIS stack + +### Visual Studio configurations + +| Configuration | Architecture | Output | +|---------------|--------------|--------| +| Release-x86-ansi | x86 ANSI | `plugins/x86-ansi/nsParser.dll` | +| Release-x86-unicode | x86 Unicode | `plugins/x86-unicode/nsParser.dll` | +| Release-amd64-unicode | x64 Unicode | `plugins/amd64-unicode/nsParser.dll` | + +--- + +## File Structure + +``` +nsParser/ + build_plugin.py # Unified build script + src/ + nsParser.c # Plugin source code + nsParser.vcxproj # VS2022 project (x86-ansi, x86-unicode, amd64-unicode) + nsParser.sln # VS2022 solution + dist/ + x86-ansi/ + x86-unicode/ + amd64-unicode/ +``` + +--- + +*See [README_IT.md](README_IT.md) for the Italian version.* diff --git a/README_IT.md b/README_IT.md new file mode 100644 index 0000000..0b63ed9 --- /dev/null +++ b/README_IT.md @@ -0,0 +1,288 @@ +# nsParser NSIS Plugin + +Plugin NSIS nativo in C per estrarre velocemente valori da file di grandi dimensioni, bypassando i limiti di NSIS_MAX_STRLEN (1KB). + +## Problema Risolto + +NSIS ha un limite di **1024 byte** per le stringhe (`NSIS_MAX_STRLEN`). File HTML/JSON con linee molto lunghe (>1KB) non possono essere processati con `FileRead` o operazioni su stringhe native NSIS. + +**Esempio**: Il file HTML di Remote Desktop Manager contiene una linea di 39.830 caratteri (135KB totali) che causa il troncamento di `FileRead` a 1KB, impedendo l'estrazione della versione. + +**Soluzioni fallite**: +- `FileRead` → Tronca a 1KB +- Concatenazione stringhe → Limite 1023 byte totali +- `NScurl /MEMORY` → Limite ~8KB +- Lettura byte-by-byte → Troppo lenta (10-30 secondi per 135KB) + +**Soluzione nsParser**: Plugin nativo in C che legge file in chunk di 8KB con buffer sliding window di 16KB, parsing in <1 secondo. + +## Compilazione + +### Requisiti +- Visual Studio 2022 (MSBuild 17.x, PlatformToolset v143) +- Python 3.x (per build automation) + +### Build Automatica + +```cmd +cd nsParser +python build_plugin.py +``` + +Compila tutte le configurazioni e copia i DLL finali in `../plugins/`: +- `x86-ansi` → 85-87 KB +- `x86-unicode` → 85-87 KB +- `x64-ansi` → 104 KB +- `amd64-unicode` → 104 KB + +File intermedi (`.lib`, `.exp`, `.obj`) rimangono in `nsParser/Plugins/{platform}/` per debugging. + +### Opzioni build + +```powershell +python build_plugin.py --config x86-unicode # Solo un'architettura (x86-ansi|x86-unicode|amd64-unicode|all) +python build_plugin.py --toolset 2026 # Toolset specifico (2022|2026|auto) +python build_plugin.py --jobs 4 # Numero di job MSBuild paralleli (default: CPU count) +python build_plugin.py --clean # Pulizia dist/ prima della build +python build_plugin.py --install-dir "C:\NSIS\Plugins" # Copia in directory NSIS aggiuntiva +python build_plugin.py --verbose # Output MSBuild esteso +python build_plugin.py --version # Stampa versione ed esce +``` + +### Build Manuale + +```cmd +cd nsParser +build.cmd +``` + +O con MSBuild direttamente: +```cmd +msbuild nsParser.vcxproj /p:Configuration="Release" /p:Platform="Win32" +msbuild nsParser.vcxproj /p:Configuration="Release Unicode" /p:Platform="Win32" +msbuild nsParser.vcxproj /p:Configuration="Release" /p:Platform="x64" +msbuild nsParser.vcxproj /p:Configuration="Release Unicode" /p:Platform="x64" +``` + +## Utilizzo in NSIS + +```nsis +!addplugindir "plugins\x86-unicode" + +Section + ; Download HTML file + NScurl::http GET "https://devolutions.net/..." "$PLUGINSDIR\rdm.html" /END + Pop $0 + + ; Extract version from HTML + nsParser::Extract "$PLUGINSDIR\rdm.html" "RDM7zX64.Version" + Pop $0 ; Status: "OK" or "ERROR" + Pop $1 ; Version string (es: "2025.3.21.0") + + ${If} $0 == "OK" + DetailPrint "Version found: $1" + ${Else} + DetailPrint "Version not found" + ${EndIf} +SectionEnd +``` + +### Esempio Reale: RDM_Functions.nsh + +```nsis +!macro _GetLatestVersion + NScurl::http GET "https://devolutions.net/..." "$R8" /END + Pop $0 + + ${If} $0 == "OK" + nsParser::Extract "$R8" "RDM7zX64.Version" + Pop $0 ; Status + Pop $1 ; Version: "2025.3.21.0" + + ${If} $0 == "OK" + StrCpy $Latest_Version "$1" + StrCpy $DOWNLOAD_LINK "https://cdn.devolutions.net/download/Devolutions.RemoteDesktopManager.win-x64.$Latest_Version.7z" + ${EndIf} + ${EndIf} +!macroend +``` + +## API + +### nsParser::Extract + +```nsis +nsParser::Extract +``` + +**Parametri**: +- ``: Percorso assoluto del file da analizzare +- ``: Pattern da cercare (es: "RDM7zX64.Version") + +**Stack Output**: +1. Status: `"OK"` o `"ERROR"` +2. Value: Stringa estratta (o vuota se errore) + +**Logica di estrazione**: +1. Cerca `` nel file +2. Trova il primo `:` dopo il pattern +3. Trova il primo `"` dopo i due punti +4. Estrae tutto fino al `"` di chiusura +5. Restituisce il valore trovato + +**Esempio**: Nel file con contenuto `{"RDM7zX64.Version":"2025.3.21.0"}`, il pattern `"RDM7zX64.Version"` estrae `"2025.3.21.0"`. + +## Vantaggi + +- **Veloce**: ~1000x più veloce del byte-reading NSIS (<1s vs 10-30s per 135KB) +- **No Limiti**: Bypassa NSIS_MAX_STRLEN, gestisce file di qualsiasi dimensione +- **Efficiente**: Lettura in chunk di 8KB con sliding window buffer di 16KB +- **Pattern Spanning**: Buffer sliding window preserva pattern tra chunk (ultimi 2KB) +- **Multi-Arch**: 4 configurazioni (x86/x64, ANSI/Unicode) +- **Semplice**: Singola funzione `Extract` parametrica +- **Generico**: Non specifico per RDM, usabile per qualsiasi estrazione pattern + +## Implementazione Tecnica + +### Algoritmo + +```c +1. CreateFile() → Apre file in lettura +2. Loop: + a. ReadFile() → Legge 8KB chunk + b. Append a search buffer (16KB max) + c. strstr() → Cerca pattern + d. Se trovato: + - Trova ':' dopo pattern + - Trova '"' dopo ':' + - Estrae fino a '"' chiusura + - Return value + e. Se buffer pieno: + - Copia ultimi 2KB all'inizio (sliding window) + - Azzera resto buffer + - Continue reading +3. CloseHandle() +``` + +### Caratteristiche + +- **Buffer Size**: 16KB totale (8KB chunk + 8KB overlap) +- **Sliding Window**: Preserva ultimi 2KB per pattern spanning +- **String Search**: Native `strstr()` su dati ANSI +- **Unicode Support**: `MultiByteToWideChar()` per output Unicode +- **Windows API**: `CreateFile`, `ReadFile`, `CloseHandle` +- **No CRT**: Runtime library statica (MultiThreaded) + +### Configurazioni Visual Studio + +| Configuration | Platform | CharacterSet | Output Size | Plugin Dir | +|---------------|----------|--------------|-------------|------------| +| Release | Win32 | MultiByte | 85-87 KB | x86-ansi | +| Release Unicode | Win32 | Unicode | 85-87 KB | x86-unicode | +| Release | x64 | MultiByte | 104 KB | x64-ansi | +| Release Unicode | x64 | Unicode | 104 KB | amd64-unicode | + +### Struttura File + +``` +nsParser/ +├── nsParser.c # Implementazione plugin (140 righe) +├── nsParser.h # Header NSISFUNC macro +├── nsParser.def # Export definitions +├── nsParser.vcxproj # Visual Studio project (4 configs) +├── build_plugin.py # Build automation + DLL copy +├── build.cmd # Batch wrapper +├── .gitignore # Ignora Plugins/*, .user, __pycache__ +├── README.md # Questa documentazione +└── Plugins/ # Build intermedi (gitignored) + ├── x86-ansi/ # DLL + .lib + .exp + .obj + ├── x86-unicode/ + ├── x64-ansi/ + └── amd64-unicode/ + +../plugins/ # Output finale (copiato da Python) +├── x86-ansi/nsParser.dll +├── x86-unicode/nsParser.dll +├── x64-ansi/nsParser.dll +└── amd64-unicode/nsParser.dll +``` + +## Note Tecniche + +### NSIS_MAX_STRLEN Limit + +Il limite di 1KB è **assoluto** in NSIS Unicode e non può essere aumentato senza ricompilare NSIS stesso. Questo plugin è l'unica soluzione pratica per processare file con linee >1KB. + +### VersionCompare Bug + +**ATTENZIONE**: `${VersionCompare}` ha un bug noto con versioni a 4 parti. Esempio: + +```nsis +${VersionCompare} "2024.3.18.0" "2025.3.21.0" $R0 +; $R0 = "2" (SBAGLIATO! Dovrebbe essere "1") +``` + +**Workaround** (usato in `RDM_Installer.nsi`): + +```nsis +${VersionCompare} "$Current_Version" "$Latest_Version" $R0 + +${If} $R0 == "2" + ; Estrai anno e confronta numericamente + ${WordFind} "$Current_Version" "." "+1{" $R1 ; Anno corrente + ${WordFind} "$Latest_Version" "." "+1{" $R2 ; Anno remoto + + ${If} $R1 < $R2 + ; Anno vecchio → forzare selezione + !insertmacro SelectSection 0 + ${Else} + !insertmacro UnselectSection 0 + ${EndIf} +${EndIf} +``` + +**Nota**: In `RDM.nsi` (launcher) il workaround non serve perché si verifica solo uguaglianza (`$R0 == "0"`), non maggiore/minore. + +## Performance + +### Benchmark: File HTML 135KB (linea 39.830 caratteri) + +| Metodo | Tempo | Note | +|--------|-------|------| +| NSIS FileRead | ❌ Fallisce | Tronca a 1KB | +| NSIS Byte-reading | 10-30 secondi | Troppo lento | +| NScurl /MEMORY | ❌ Fallisce | Limite ~8KB | +| **nsParser plugin** | **<1 secondo** | ✅ Soluzione ottimale | + +### Perché è così veloce? + +1. **Native C**: Compiled code vs NSIS interpreted +2. **Bulk Reading**: 8KB chunks vs 1-byte iterations +3. **Efficient Search**: `strstr()` CPU-optimized vs NSIS string ops +4. **No String Limits**: Direct memory access vs NSIS_MAX_STRLEN + +## Casi d'Uso + +- ✅ Estrazione versioni da HTML/JSON con linee lunghe +- ✅ Parsing file di configurazione con valori embedded +- ✅ Lettura metadata da file generati (build info, manifests) +- ✅ Download + parsing di risorse remote in un unico passaggio +- ✅ Qualsiasi pattern `"key":"value"` o `key: "value"` + +## Licenza + +Sviluppato per uso interno nel workspace Launchers. + +## Changelog + +### v1.0 (2025-11-10) +- ✅ Rinominato da RDMVersion a nsParser (generico) +- ✅ Supporto multi-architettura (4 configurazioni) +- ✅ Build automation con Python +- ✅ Struttura directory pulita (Plugins/ + ../plugins/) +- ✅ Fixed amd64-unicode configuration bug +- ✅ Integrato in RDM_Installer.nsi e RDM_Functions.nsh +- ✅ Performance validated: <1s per 135KB file + +### v0.1 (Initial) +- Plugin iniziale RDMVersion specifico per Remote Desktop Manager diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..6374b2d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,40 @@ +# Security Policy + +## Versioni Supportate + +Solo l'ultima versione minor riceve fix di security. + +| Versione | Supporto | +|----------|----------| +| Latest minor (es. 1.0.0) | ✅ | +| Versioni precedenti | ❌ | + +## Reporting di una Vulnerabilità + +**Non aprire issue pubbliche per vulnerabilità di security.** + +Per segnalare una vulnerabilità: + +1. **Preferito**: usa la funzione [Security Advisory privato](https://gitea.emulab.it/Simone/nsis-plugin-nsparser/security/advisories/new) di Gitea +2. **Alternativa**: invia email a `security@example.com` (sostituire con email reale prima del primo release) + +Includi: +- Descrizione della vulnerabilità +- Passi per riprodurla +- Versione/i affette +- Possibile mitigazione (se nota) + +## Tempo di Risposta + +- Acknowledgment iniziale: entro 7 giorni +- Valutazione: entro 14 giorni +- Patch (se confermata): tempistiche dipendono dalla severità + +## Hardening + +Questo plugin gira con i permessi del processo NSIS chiamante (tipicamente +l'utente che esegue l'installer). Non richiede privilegi elevati per la +compilazione né per l'esecuzione, salvo dove esplicitamente documentato. + +DLL distribuite tramite Releases sono compilate da CI GitHub Actions con +toolchain pinnata. Verificare hash SHA256 pubblicati nelle release. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..0d1d711 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.0.1 \ No newline at end of file diff --git a/build_plugin.py b/build_plugin.py new file mode 100644 index 0000000..09aec5b --- /dev/null +++ b/build_plugin.py @@ -0,0 +1,679 @@ +#!/usr/bin/env python3 +""" +Build script for nsParser plugin - All configurations +Supports multiple build configurations with flexible parameters +""" + +import argparse +import errno +import multiprocessing +import os +import shutil +import stat +import subprocess +import sys +import threading +import time +import xml.etree.ElementTree as ET +from concurrent.futures import ThreadPoolExecutor, as_completed +from pathlib import Path +from typing import List, Optional, Tuple + +# Ensure stdout/stderr handle Unicode on Windows CI (cp1252 default breaks non-ASCII) +if sys.stdout.encoding and sys.stdout.encoding.lower() not in ('utf-8', 'utf_8'): + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace') + + +# --------------------------------------------------------------------------- +# Filesystem helpers +# --------------------------------------------------------------------------- + +def _on_rmtree_error(func, path, exc_info): + if func in (os.unlink, os.rmdir) and exc_info[1].errno == errno.EACCES: + try: + os.chmod(path, stat.S_IWRITE) + func(path) + return + except Exception: + pass + for i in range(5): + try: + time.sleep(0.1 * (i + 1)) + if os.path.isdir(path): + shutil.rmtree(path) + else: + os.unlink(path) + return + except Exception: + pass + raise exc_info[1] + + +def robust_rmtree(path): + if not os.path.exists(path): + return + try: + shutil.rmtree(path, onexc=_on_rmtree_error) + except TypeError: + try: + shutil.rmtree(path, onerror=_on_rmtree_error) + except Exception: + pass + except Exception: + try: + shutil.rmtree(path, ignore_errors=True) + except Exception: + pass + + +# --------------------------------------------------------------------------- +# Colors & Spinner +# --------------------------------------------------------------------------- + +class Colors: + CYAN = "\033[36m" + GREEN = "\033[32m" + YELLOW = "\033[33m" + RED = "\033[31m" + GRAY = "\033[90m" + BLUE = "\033[34m" + RESET = "\033[0m" + BOLD = "\033[1m" + BRIGHT_GREEN = "\033[92m" + BRIGHT_CYAN = "\033[96m" + BRIGHT_WHITE = "\033[97m" + BRIGHT_YELLOW = "\033[93m" + BRIGHT_RED = "\033[91m" + + +class Spinner: + def __init__(self, message: str = "Building...", delay: float = 0.1, total: int = 0): + self.spinner = ['\u280b', '\u2819', '\u2839', '\u2838', '\u283c', '\u2834', '\u2826', '\u2827', '\u2807', '\u280f'] + self.delay = delay + self.message = message + self.running = False + self.thread = None + self.start_time = time.time() + + def update(self, current=None): + pass + + def _spin(self): + idx = 0 + _block = '\u28ff' + while self.running: + elapsed = time.time() - self.start_time + n_blocks = int(elapsed // 2) + time_blocks = f"{Colors.YELLOW}{_block * n_blocks}{Colors.RESET}" + spin_char = f"{Colors.YELLOW}{self.spinner[idx % len(self.spinner)]}{Colors.RESET}" + msg = f"{Colors.BOLD}{Colors.CYAN}{self.message}{Colors.RESET}" + time_str = f"{Colors.GREEN}{int(elapsed)}s{Colors.RESET}" + sys.stdout.write(f"\r{msg} {time_str} {time_blocks}{spin_char} ") + sys.stdout.flush() + idx += 1 + time.sleep(self.delay) + sys.stdout.write("\r" + " " * (len(self.message) + 80) + "\r") + sys.stdout.flush() + + def __enter__(self): + if sys.stdout.isatty(): + self.running = True + self.thread = threading.Thread(target=self._spin, daemon=True) + self.thread.start() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.running: + self.running = False + if self.thread: + self.thread.join() + + +# --------------------------------------------------------------------------- +# Build configuration +# --------------------------------------------------------------------------- + +class BuildConfig: + def __init__(self, name: str, config: str, platform: str, dest_dir: str): + self.name = name + self.config = config + self.platform = platform + self.dest_dir = dest_dir + + +CONFIGS = { + 'x86-ansi': BuildConfig('x86-ansi', 'Release', 'Win32', 'x86-ansi'), + 'x86-unicode': BuildConfig('x86-unicode', 'Release Unicode', 'Win32', 'x86-unicode'), + 'x64-unicode': BuildConfig('x64-unicode', 'Release Unicode', 'x64', 'amd64-unicode'), +} + +DLL_NAME = 'nsParser.dll' +_VSWHERE = Path(r'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe') +_VS_RANGES = {'2026': '[18.0,19.0)', '2022': '[17.0,18.0)'} +_VS_TOOLSETS = {'2026': 'v145', '2022': 'v143'} + + +# --------------------------------------------------------------------------- +# MSBuild discovery +# --------------------------------------------------------------------------- + +def _find_msbuild_vswhere(vs_version: str) -> Optional[Tuple[Path, str, str]]: + if not _VSWHERE.exists(): + return None + to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version] + for ver in to_try: + if ver not in _VS_RANGES: + continue + try: + result = subprocess.run( + [str(_VSWHERE), '-version', _VS_RANGES[ver], '-latest', + '-requires', 'Microsoft.Component.MSBuild', + '-find', r'MSBuild\**\Bin\MSBuild.exe'], + capture_output=True, text=True, timeout=15, + ) + if result.returncode == 0: + lines = [ln.strip() for ln in result.stdout.splitlines() if ln.strip()] + if lines: + p = Path(lines[0]) + if p.exists(): + return p, _VS_TOOLSETS[ver], ver + except Exception: + pass + return None + + +def find_msbuild(vs_version: str = 'auto') -> Optional[Tuple[Path, str, str]]: + result = _find_msbuild_vswhere(vs_version) + if result: + return result + # Fallback: well-known paths + to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version] + for ver in to_try: + for edition in ('Community', 'Professional', 'Enterprise', 'BuildTools'): + p = Path(rf'C:\Program Files\Microsoft Visual Studio\{ver}\{edition}\MSBuild\Current\Bin\MSBuild.exe') + if p.exists(): + return p, _VS_TOOLSETS[ver], ver + return None + + +# --------------------------------------------------------------------------- +# Project paths & version +# --------------------------------------------------------------------------- + +def get_project_paths() -> Tuple[Path, Path, Path]: + script_dir = Path(__file__).parent.absolute() + project_dir = script_dir / 'src' + project_file = project_dir / 'nsParser.vcxproj' + dist_dir = script_dir / 'dist' + return project_dir, project_file, dist_dir + + +def get_plugins_dir() -> Optional[Path]: + """Return workspace-level plugins/ dir (4 levels above src/modules//).""" + p = Path(__file__).parent.parent.parent.parent / 'plugins' + return p if p.is_dir() else None + + +def read_version() -> str: + vf = Path(__file__).parent / 'VERSION' + try: + return vf.read_text(encoding='utf-8-sig').strip() + except Exception: + return '0.0.0' + + +# --------------------------------------------------------------------------- +# CPU info & build optimizations +# --------------------------------------------------------------------------- + +def get_cpu_info() -> dict: + try: + import psutil + logical = psutil.cpu_count(logical=True) + physical = psutil.cpu_count(logical=False) + return {'logical_cores': logical, 'physical_cores': physical, + 'has_hyperthreading': logical > physical, 'has_psutil': True} + except ImportError: + n = multiprocessing.cpu_count() + return {'logical_cores': n, 'physical_cores': n, + 'has_hyperthreading': False, 'has_psutil': False} + + +def get_optimal_threads() -> int: + info = get_cpu_info() + return info['physical_cores'] if info['has_hyperthreading'] and info['physical_cores'] > 1 else info['logical_cores'] + + +def get_build_optimizations() -> List[str]: + return [ + '/p:BuildInParallel=true', + '/p:MultiProcessorCompilation=true', + '/p:PreferredToolArchitecture=x64', + '/p:UseSharedCompilation=true', + '/nodeReuse:true', + '/p:GenerateResourceUsePreserializedResources=true', + ] + + +def get_memory_optimizations() -> List[str]: + try: + import psutil + gb = psutil.virtual_memory().total / (1024 ** 3) + if gb >= 16: + return ['/p:DisableFastUpToDateCheck=false', '/p:BuildProjectReferences=true', + '/p:UseCommonOutputDirectory=false'] + elif gb >= 8: + return ['/p:DisableFastUpToDateCheck=false'] + return [] + except ImportError: + return ['/p:DisableFastUpToDateCheck=false'] + + +def print_cpu_info(use_parallel: bool, use_optimizations: bool = True) -> None: + if not use_parallel: + print(f"{Colors.CYAN}Build mode: {Colors.RESET} {Colors.BOLD}Single-threaded{Colors.RESET}") + if use_optimizations: + print(f"{Colors.CYAN}Optimizations: {Colors.RESET} {Colors.GREEN}ENABLED{Colors.RESET} {Colors.GRAY}(memory, caching){Colors.RESET}") + return + + info = get_cpu_info() + optimal = get_optimal_threads() + print(f"{Colors.CYAN}Build mode: {Colors.RESET} {Colors.BRIGHT_WHITE}{'Parallel' if use_parallel else 'Sequential'}{Colors.RESET}") + print(f"{Colors.CYAN}Logical cores: {Colors.RESET} {Colors.BRIGHT_WHITE}{info['logical_cores']}{Colors.RESET}") + print(f"{Colors.CYAN}Physical cores: {Colors.RESET} {Colors.BRIGHT_WHITE}{info['physical_cores']}{Colors.RESET}") + if info['has_hyperthreading']: + print(f"{Colors.CYAN}Hyperthreading: {Colors.RESET} {Colors.BRIGHT_GREEN}ENABLED{Colors.RESET}") + print(f"{Colors.CYAN}Optimal threads: {Colors.RESET} {Colors.BRIGHT_WHITE}{optimal}{Colors.RESET} {Colors.GRAY}(using physical cores){Colors.RESET}") + else: + print(f"{Colors.CYAN}Hyperthreading: {Colors.RESET} {Colors.GRAY}NOT AVAILABLE{Colors.RESET}") + print(f"{Colors.CYAN}Optimal threads: {Colors.RESET} {Colors.BRIGHT_WHITE}{optimal}{Colors.RESET}") + print(f"{Colors.CYAN}MSBuild threads: {Colors.RESET} {Colors.BRIGHT_WHITE}{optimal}{Colors.RESET}") + if use_optimizations: + print(f"{Colors.CYAN}Optimizations: {Colors.RESET} {Colors.BRIGHT_GREEN}ENABLED{Colors.RESET} {Colors.GRAY}(parallel, memory, caching){Colors.RESET}") + try: + import psutil + gb = psutil.virtual_memory().total / (1024 ** 3) + print(f"{Colors.CYAN}Available memory: {Colors.RESET} {Colors.BRIGHT_WHITE}{gb:.1f} GB{Colors.RESET}") + except ImportError: + print(f"{Colors.CYAN}Available memory: {Colors.RESET} {Colors.GRAY}Unknown (install psutil){Colors.RESET}") + else: + print(f"{Colors.CYAN}Optimizations: {Colors.RESET} {Colors.BRIGHT_RED}DISABLED{Colors.RESET}") + if not info['has_psutil']: + print(f"{Colors.GRAY}Note: Install 'psutil' for detailed CPU/memory info (pip install psutil){Colors.RESET}") + print() + + +# --------------------------------------------------------------------------- +# Build helpers +# --------------------------------------------------------------------------- + +def format_time(seconds: float) -> str: + if seconds < 60: + return f"{seconds:.2f}s" + elif seconds < 3600: + return f"{int(seconds // 60)}m {seconds % 60:.1f}s" + return f"{int(seconds // 3600)}h {int((seconds % 3600) // 60)}m {seconds % 60:.0f}s" + + +def build_configuration( + msbuild_path: Path, + project_file: Path, + config: BuildConfig, + platform_toolset: str, + *, + rebuild: bool = True, + verbosity: str = 'quiet', + parallel: bool = True, + optimizations: bool = True, + counter: str = "", + capture_output: bool = False, +) -> Tuple[bool, float, str]: + optimal = get_optimal_threads() + cmd = [ + str(msbuild_path), + str(project_file), + f'/t:{"Rebuild" if rebuild else "Build"}', + f'/p:Configuration={config.config}', + f'/p:Platform={config.platform}', + f'/p:OutDir=Build\\{config.name}\\', + f'/p:IntDir=Build\\{config.name}\\obj\\', + '/p:WindowsTargetPlatformVersion=10.0', + f'/p:PlatformToolset={platform_toolset}', + f'/v:{verbosity}', + ] + if parallel: + cmd += [f'/maxcpucount:{optimal}', '/p:UseMultiToolTask=true', f'/p:CL_MPCount={optimal}'] + cmd += ['/p:Optimization=MaxSpeed', '/p:ExceptionHandling=Sync'] + if optimizations: + cmd += get_build_optimizations() + get_memory_optimizations() + + if not capture_output: + color = Colors.BRIGHT_YELLOW + print(f"\n{color}{'='*60}{Colors.RESET}") + label = f"[{counter}] " if counter else "" + print(f"{color}Building {Colors.BRIGHT_WHITE}{config.name:15s}{Colors.RESET} {color}{label}({'rebuild' if rebuild else 'incremental'}){Colors.RESET}") + print(f"{color}{'='*60}{Colors.RESET}") + + start = time.time() + try: + if capture_output: + result = subprocess.run(cmd, check=False, capture_output=True, text=True) + return result.returncode == 0, time.time() - start, result.stdout + result.stderr + else: + result = subprocess.run(cmd, check=False) + return result.returncode == 0, time.time() - start, "" + except Exception as e: + elapsed = time.time() - start + msg = f"ERROR: Build failed with exception: {e}" + if capture_output: + return False, elapsed, msg + print(msg) + return False, elapsed, "" + + +def copy_output(project_dir: Path, dist_dir: Path, config: BuildConfig) -> Tuple[bool, int, Optional[Path]]: + output_file = project_dir / 'Build' / config.name / DLL_NAME + if not output_file.exists(): + print(f"ERROR: DLL not found: {output_file}") + return False, 0, None + dest = dist_dir / config.dest_dir + dest.mkdir(parents=True, exist_ok=True) + try: + dst = dest / DLL_NAME + shutil.copy2(output_file, dst) + return True, output_file.stat().st_size, dst + except Exception as e: + print(f"ERROR: Failed to copy {config.name}: {e}") + return False, 0, None + + +def copy_to_plugins(dist_dir: Path, config: BuildConfig, plugins_dir: Path) -> Optional[Path]: + """Copy DLL from dist// to plugins//.""" + src = dist_dir / config.dest_dir / DLL_NAME + if not src.exists(): + return None + dst_dir = plugins_dir / config.dest_dir + dst_dir.mkdir(parents=True, exist_ok=True) + dst = dst_dir / DLL_NAME + shutil.copy2(src, dst) + return dst + + +def clean_build_artifacts(project_dir: Path, configs: List[BuildConfig]) -> None: + print(f"\n{Colors.CYAN}Cleaning build artifacts...{Colors.RESET}") + build_base = project_dir / 'Build' + if not build_base.exists(): + return + for cfg in configs: + d = build_base / cfg.name + if d.exists(): + try: + robust_rmtree(d) + print(f" {Colors.GRAY}- Cleaned:{Colors.RESET} {cfg.name}") + except Exception as e: + print(f" {Colors.RED}- Failed to clean {cfg.name}: {e}{Colors.RESET}") + try: + if build_base.exists() and not any(build_base.iterdir()): + build_base.rmdir() + except Exception: + pass + print(f"{Colors.BRIGHT_GREEN}Build artifacts cleaned successfully.{Colors.RESET}") + + +def print_available_configurations(project_file: Path) -> None: + try: + tree = ET.parse(project_file) + root = tree.getroot() + ns = {'ms': 'http://schemas.microsoft.com/developer/msbuild/2003'} + configs = [] + for ig in root.findall('.//ms:ItemGroup', ns): + for pc in ig.findall('ms:ProjectConfiguration', ns): + inc = pc.get('Include', '') + parts = inc.split('|') + if len(parts) == 2: + configs.append(tuple(parts)) + print("Available configurations in project:") + print("-" * 60) + from collections import defaultdict + grouped: dict = defaultdict(list) + for cfg, plat in configs: + grouped[cfg].append(plat) + for cfg_name in sorted(grouped): + print(f" {cfg_name:25s} - {', '.join(sorted(grouped[cfg_name]))}") + print(f"\nTotal: {len(configs)} configuration(s)\n") + except Exception as e: + print(f"Could not parse project file: {e}") + + +_print_lock = threading.Lock() + + +def _build_configs_parallel( + msbuild_path: Path, + project_file: Path, + configs: List[BuildConfig], + platform_toolset: str, + *, + rebuild: bool, + verbosity: str, + parallel: bool, + optimizations: bool, + project_dir: Path, + dist_dir: Path, +) -> list: + n = len(configs) + print(f"\nParallel: launching {n} builds simultaneously...") + print("=" * 50) + total_start = time.time() + results_by_idx: dict = {} + idx_lock = threading.Lock() + + def _build_one(idx: int, config: BuildConfig): + import contextlib + import io as _io + success, build_time, captured = build_configuration( + msbuild_path, project_file, config, platform_toolset, + rebuild=rebuild, verbosity=verbosity, + parallel=parallel, optimizations=optimizations, + capture_output=True, + ) + copy_buf = _io.StringIO() + if success: + with contextlib.redirect_stdout(copy_buf): + copy_ok, file_size, dest_path = copy_output(project_dir, dist_dir, config) + else: + copy_ok, file_size, dest_path = False, 0, None + + with _print_lock: + sys.stdout.write("\r" + " " * 80 + "\r") + sys.stdout.flush() + tag = "OK" if (success and copy_ok) else "FAILED" + size_str = f"{file_size:,} bytes" if file_size > 0 else "N/A" + copy_out = copy_buf.getvalue() + if copy_out.strip(): + print(copy_out.rstrip()) + if captured.strip(): + lines = [ln for ln in captured.splitlines() if "MSBuild" not in ln and "Copyright" not in ln] + filtered = "\n".join(lines).strip() + if filtered: + print(filtered) + color = Colors.BRIGHT_GREEN if (success and copy_ok) else Colors.RED + print(f"{color}[{tag}]{Colors.RESET} {config.name} ({format_time(build_time)}) {size_str}") + if dest_path: + print(f" -> {dest_path}") + + with idx_lock: + results_by_idx[idx] = (config, success and copy_ok, build_time, file_size, dest_path) + + with Spinner("Building configurations...", total=n) as s: + with ThreadPoolExecutor(max_workers=n) as executor: + futures = {executor.submit(_build_one, i, cfg): i for i, cfg in enumerate(configs)} + for fut in as_completed(futures): + s.update() + exc = fut.exception() + if exc: + idx = futures[fut] + with _print_lock: + print(f"ERROR: worker for config index {idx} raised: {exc}") + with idx_lock: + results_by_idx[idx] = (configs[idx], False, 0.0, 0, None) + + wall = time.time() - total_start + print(f"\nAll {n} configs finished in {format_time(wall)} (wall clock)") + return [results_by_idx[i] for i in range(n)] + + +# --------------------------------------------------------------------------- +# main +# --------------------------------------------------------------------------- + +def main() -> int: + parser = argparse.ArgumentParser(description='Build nsParser plugin for NSIS') + parser.add_argument('--configs', nargs='+', + choices=list(CONFIGS.keys()) + ['all'], default=None) + parser.add_argument('--config', # singular alias used by CI + choices=list(CONFIGS.keys()) + ['all'], default=None) + parser.add_argument('--rebuild', action='store_true', default=True) + parser.add_argument('--no-rebuild', action='store_false', dest='rebuild') + parser.add_argument('--parallel', action='store_true', default=True) + parser.add_argument('--no-parallel', action='store_false', dest='parallel') + parser.add_argument('--verbosity', + choices=['quiet', 'minimal', 'normal', 'detailed', 'diagnostic'], + default='quiet') + parser.add_argument('--clean', action='store_true', default=False) + parser.add_argument('--list', action='store_true') + parser.add_argument('--list-project', action='store_true') + parser.add_argument('--no-optimizations', action='store_true') + parser.add_argument('--vs-version', choices=['auto', '2026', '2022'], default='auto') + parser.add_argument('--final', action='store_true', default=False, + help='Force rebuild + clean (pre-release build)') + parser.add_argument('--install-dir', type=Path, default=None, + help='Copy built DLLs to this directory (in / subdirs)') + args = parser.parse_args() + + # Merge --config (singular) into --configs list + if args.config and not args.configs: + args.configs = [args.config] + + if args.final: + args.rebuild = True + args.clean = True + + project_dir, project_file, dist_dir = get_project_paths() + + if args.list_project: + print_available_configurations(project_file) + return 0 + + if args.list: + for name, config in CONFIGS.items(): + print(f" {name:15s} -> {config.config} / {config.platform}") + return 0 + + if not project_file.exists(): + print(f"ERROR: project file not found: {project_file}", file=sys.stderr) + return 3 + + msbuild_result = find_msbuild(args.vs_version) + if not msbuild_result: + print("ERROR: MSBuild not found. Install Visual Studio 2022 or 2026.", file=sys.stderr) + return 2 + msbuild_path, platform_toolset, vs_version_name = msbuild_result + + version = read_version() + + if not args.configs: + configs_to_build = list(CONFIGS.values()) + elif 'all' in args.configs: + configs_to_build = list(CONFIGS.values()) + else: + configs_to_build = [CONFIGS[n] for n in args.configs] + + # Banner + print(f"{Colors.BOLD}{Colors.BRIGHT_CYAN}{'='*60}") + print(f"Building nsParser plugin v{version} - {Colors.BRIGHT_WHITE}{len(configs_to_build)}{Colors.RESET} {Colors.BOLD}{Colors.BRIGHT_CYAN}configuration(s)") + print(f"{'='*60}{Colors.RESET}") + print(f"{Colors.CYAN}VS: {Colors.RESET} {Colors.BRIGHT_WHITE}{vs_version_name}{Colors.RESET} {Colors.GRAY}({platform_toolset}){Colors.RESET}") + print(f"{Colors.CYAN}MSBuild: {Colors.RESET} {Colors.BRIGHT_WHITE}{msbuild_path}{Colors.RESET}") + print(f"{Colors.CYAN}Project: {Colors.RESET} {Colors.BRIGHT_WHITE}{project_file}{Colors.RESET}") + print(f"{Colors.CYAN}Dist: {Colors.RESET} {Colors.BRIGHT_WHITE}{dist_dir}{Colors.RESET}") + print(f"{Colors.CYAN}Rebuild: {Colors.RESET} {Colors.BRIGHT_WHITE}{args.rebuild}{Colors.RESET}") + print(f"{Colors.CYAN}Verbosity: {Colors.RESET} {Colors.BRIGHT_WHITE}{args.verbosity}{Colors.RESET}") + print() + + use_optimizations = not args.no_optimizations + print_cpu_info(args.parallel, use_optimizations) + + build_results = [] + total_start = time.time() + + if args.parallel and len(configs_to_build) > 1: + build_results = _build_configs_parallel( + msbuild_path, project_file, configs_to_build, platform_toolset, + rebuild=args.rebuild, verbosity=args.verbosity, + parallel=True, optimizations=use_optimizations, + project_dir=project_dir, dist_dir=dist_dir, + ) + else: + for i, config in enumerate(configs_to_build, 1): + success, b_time, _ = build_configuration( + msbuild_path, project_file, config, platform_toolset, + rebuild=args.rebuild, verbosity=args.verbosity, + parallel=args.parallel, optimizations=use_optimizations, + counter=f"{i}/{len(configs_to_build)}", + ) + if success: + ok, size, path = copy_output(project_dir, dist_dir, config) + build_results.append((config, ok, b_time, size, path)) + else: + build_results.append((config, False, b_time, 0, None)) + + total_time = time.time() - total_start + all_success = all(res[1] for res in build_results) + + print(f"\n{Colors.BOLD}{Colors.BRIGHT_GREEN if all_success else Colors.RED}{'='*50}") + print("ALL BUILDS SUCCESSFUL!" if all_success else "SOME BUILDS FAILED!") + print(f"{'='*50}{Colors.RESET}") + + # Copy to workspace plugins/ dir if present + plugins_dir = get_plugins_dir() + plugins_copied = [] + if plugins_dir and all_success: + for cfg, ok, _, _, _ in build_results: + if ok: + dst = copy_to_plugins(dist_dir, cfg, plugins_dir) + if dst: + plugins_copied.append(str(dst)) + if plugins_copied: + print(f"\n{Colors.CYAN}Installed to plugins/:{Colors.RESET}") + for p in plugins_copied: + print(f" {Colors.GRAY}->{Colors.RESET} {p}") + + if args.install_dir and all_success: + print(f"\n{Colors.CYAN}Installing to {args.install_dir}...{Colors.RESET}") + for cfg, ok, _, _, path in build_results: + if ok and path: + dest = args.install_dir / cfg.dest_dir + dest.mkdir(parents=True, exist_ok=True) + shutil.copy2(path, dest / DLL_NAME) + print(f" {Colors.GRAY}- Installed:{Colors.RESET} {dest / DLL_NAME}") + + print(f"\n{Colors.BOLD}{Colors.BRIGHT_CYAN}{'-'*50}") + print(f"Build Summary - VS {vs_version_name} ({platform_toolset}):") + for cfg, ok, b_time, size, _ in build_results: + color = Colors.GREEN if ok else Colors.RED + tag = "OK " if ok else "FAIL" + print(f" {color}{tag}{Colors.RESET} {cfg.name:15s} - {format_time(b_time):8s} - {size:11,d} bytes") + print(f"{Colors.BOLD}{Colors.BRIGHT_CYAN}{'-'*50}{Colors.RESET}") + print(f"Total time: {format_time(total_time)}\n") + + if args.clean: + clean_build_artifacts(project_dir, configs_to_build) + + return 0 if all_success else 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/dist/amd64-unicode/nsParser.dll b/dist/amd64-unicode/nsParser.dll new file mode 100644 index 0000000000000000000000000000000000000000..2aacfd3d5d7fd2ca34ca6fb681538294c3a30898 GIT binary patch literal 103424 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 XVcZyGwhnR|_Y&hxNEqaA@aw+;NDnTn literal 0 HcmV?d00001 diff --git a/src/api.h b/src/api.h new file mode 100644 index 0000000..85d41c4 --- /dev/null +++ b/src/api.h @@ -0,0 +1,83 @@ +/* + * apih + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2013 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _NSIS_EXEHEAD_API_H_ +#define _NSIS_EXEHEAD_API_H_ + +// Starting with NSIS 2.42, you can check the version of the plugin API in exec_flags->plugin_api_version +// The format is 0xXXXXYYYY where X is the major version and Y is the minor version (MAKELONG(y,x)) +// When doing version checks, always remember to use >=, ex: if (pX->exec_flags->plugin_api_version >= NSISPIAPIVER_1_0) {} + +#define NSISPIAPIVER_1_0 0x00010000 +#define NSISPIAPIVER_CURR NSISPIAPIVER_1_0 + +// NSIS Plug-In Callback Messages +enum NSPIM +{ + NSPIM_UNLOAD, // This is the last message a plugin gets, do final cleanup + NSPIM_GUIUNLOAD, // Called after .onGUIEnd +}; + +// Prototype for callbacks registered with extra_parameters->RegisterPluginCallback() +// Return NULL for unknown messages +// Should always be __cdecl for future expansion possibilities +typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM); + +// extra_parameters data structures containing other interesting stuff +// but the stack, variables and HWND passed on to plug-ins. +typedef struct +{ + int autoclose; + int all_user_var; + int exec_error; + int abort; + int exec_reboot; // NSIS_SUPPORT_REBOOT + int reboot_called; // NSIS_SUPPORT_REBOOT + int XXX_cur_insttype; // depreacted + int plugin_api_version; // see NSISPIAPIVER_CURR + // used to be XXX_insttype_changed + int silent; // NSIS_CONFIG_SILENT_SUPPORT + int instdir_error; + int rtl; + int errlvl; + int alter_reg_view; + int status_update; +} exec_flags_t; + +#ifndef NSISCALL +# define NSISCALL __stdcall +#endif + +typedef struct { + exec_flags_t *exec_flags; + int (NSISCALL *ExecuteCodeSegment)(int, HWND); + void (NSISCALL *validate_filename)(TCHAR *); + int (NSISCALL *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and < 0 on errors +} extra_parameters; + +// Definitions for page showing plug-ins +// See Ui.c to understand better how they're used + +// sent to the outer window to tell it to go to the next inner window +#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8) + +// custom pages should send this message to let NSIS know they're ready +#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd) + +// sent as wParam with WM_NOTIFY_OUTER_NEXT when user cancels - heed its warning +#define NOTIFY_BYE_BYE 'x' + +#endif /* _PLUGIN_H_ */ diff --git a/src/nsParser.c b/src/nsParser.c new file mode 100644 index 0000000..7f2d2ad --- /dev/null +++ b/src/nsParser.c @@ -0,0 +1,144 @@ +/* + nsParser NSIS plugin + Extract patterns from text/HTML files +*/ + +#include +#include "pluginapi.h" +#include "nsParser.h" + +HANDLE g_hInstance; + +static UINT_PTR PluginCallback(enum NSPIM msg) +{ + return 0; +} + +BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + g_hInstance = hInst; + return TRUE; +} + +// Find pattern in file and extract value between quotes +static BOOL ExtractVersion(PTCHAR pszFilename, PCHAR pszPattern, PTCHAR pszVersion, DWORD dwVersionSize) +{ + HANDLE hFile; + DWORD dwBytesRead; + CHAR szBuffer[8192]; + CHAR szSearchBuffer[16384] = {0}; + DWORD dwSearchBufferLen = 0; + DWORD dwPatternLen = lstrlenA(pszPattern); + BOOL bFound = FALSE; + + // Open file + hFile = CreateFile(pszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + // Read file in chunks + while (ReadFile(hFile, szBuffer, sizeof(szBuffer), &dwBytesRead, NULL) && dwBytesRead > 0) + { + // Append to search buffer + if (dwSearchBufferLen + dwBytesRead < sizeof(szSearchBuffer)) + { + CopyMemory(szSearchBuffer + dwSearchBufferLen, szBuffer, dwBytesRead); + dwSearchBufferLen += dwBytesRead; + } + else + { + // Buffer full, keep last 2KB and continue + MoveMemory(szSearchBuffer, szSearchBuffer + dwSearchBufferLen - 2048, 2048); + CopyMemory(szSearchBuffer + 2048, szBuffer, dwBytesRead); + dwSearchBufferLen = 2048 + dwBytesRead; + } + szSearchBuffer[dwSearchBufferLen] = '\0'; + + // Search for pattern + PCHAR pszFound = strstr(szSearchBuffer, pszPattern); + if (pszFound) + { + // Found! Extract value between quotes + // Format: "RDM7zX64.Version":"2025.3.21.0" + PCHAR pszColon = strchr(pszFound + dwPatternLen, ':'); + if (pszColon) + { + PCHAR pszOpenQuote = strchr(pszColon, '"'); + if (pszOpenQuote) + { + PCHAR pszCloseQuote = strchr(pszOpenQuote + 1, '"'); + if (pszCloseQuote) + { + // Extract version + DWORD dwLen = (DWORD)(pszCloseQuote - pszOpenQuote - 1); + if (dwLen < dwVersionSize) + { + // Convert to TCHAR +#ifdef UNICODE + MultiByteToWideChar(CP_ACP, 0, pszOpenQuote + 1, dwLen, pszVersion, dwVersionSize); + pszVersion[dwLen] = 0; +#else + CopyMemory(pszVersion, pszOpenQuote + 1, dwLen); + pszVersion[dwLen] = 0; +#endif + bFound = TRUE; + break; + } + } + } + } + } + } + + CloseHandle(hFile); + return bFound; +} + +// NSIS Plugin function: Extract +// Usage: nsParser::Extract "filepath" "pattern" +// Returns: "OK" or "ERROR", then extracted value +NSISFUNC(Extract) +{ + DLL_INIT(); + { + TCHAR szFilepath[1024]; + TCHAR szPattern[256]; + CHAR szPatternA[256]; + TCHAR szVersion[256] = {0}; + + // Pop filepath + if (popstring(szFilepath) != 0) + { + pushstring(TEXT("")); + pushstring(TEXT("ERROR")); + return; + } + + // Pop pattern + if (popstring(szPattern) != 0) + { + pushstring(TEXT("")); + pushstring(TEXT("ERROR")); + return; + } + + // Convert pattern to ANSI for file searching +#ifdef UNICODE + WideCharToMultiByte(CP_ACP, 0, szPattern, -1, szPatternA, sizeof(szPatternA), NULL, NULL); +#else + lstrcpyA(szPatternA, szPattern); +#endif + + // Extract version + if (ExtractVersion(szFilepath, szPatternA, szVersion, sizeof(szVersion) / sizeof(TCHAR))) + { + pushstring(szVersion); + pushstring(TEXT("OK")); + } + else + { + pushstring(TEXT("")); + pushstring(TEXT("ERROR")); + } + } +} diff --git a/src/nsParser.def b/src/nsParser.def new file mode 100644 index 0000000..7b3faf8 --- /dev/null +++ b/src/nsParser.def @@ -0,0 +1,4 @@ +; nsParser.def - Export definitions for NSIS plugin +LIBRARY nsParser +EXPORTS + Extract diff --git a/src/nsParser.h b/src/nsParser.h new file mode 100644 index 0000000..d42b5e0 --- /dev/null +++ b/src/nsParser.h @@ -0,0 +1,9 @@ +#ifndef __NSPARSER_H__ +#define __NSPARSER_H__ + +#define NSISFUNC(name) void __declspec(dllexport) name(HWND hWndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters *extra) +#define DLL_INIT() \ + EXDLL_INIT(); \ + extra->RegisterPluginCallback((HMODULE)g_hInstance, PluginCallback) + +#endif diff --git a/src/nsParser.vcxproj b/src/nsParser.vcxproj new file mode 100644 index 0000000..8baa3e4 --- /dev/null +++ b/src/nsParser.vcxproj @@ -0,0 +1,211 @@ + + + + + Release + Win32 + + + Release Unicode + Win32 + + + Release + x64 + + + Release Unicode + x64 + + + + 15.0 + {A1B2C3D4-E5F6-7890-ABCD-EF1234567890} + Win32Proj + nsParser + 10.0 + + + + DynamicLibrary + false + v143 + true + MultiByte + + + DynamicLibrary + false + v143 + true + Unicode + + + DynamicLibrary + false + v143 + true + MultiByte + + + DynamicLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + false + $(SolutionDir)Plugins\x86-ansi\ + $(SolutionDir)Plugins\x86-ansi\ + + + false + $(SolutionDir)Plugins\x86-unicode\ + $(SolutionDir)Plugins\x86-unicode\ + + + false + $(SolutionDir)Plugins\x64-ansi\ + $(SolutionDir)Plugins\x64-ansi\ + + + false + $(SolutionDir)Plugins\amd64-unicode\ + $(SolutionDir)Plugins\amd64-unicode\ + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + false + true + true + nsParser.def + kernel32.lib;user32.lib;%(AdditionalDependencies) + + + + + + Level3 + + + MaxSpeed + true + true + + WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + false + true + true + nsParser.def + kernel32.lib;user32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + false + true + true + nsParser.def + kernel32.lib;user32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + + WIN32;NDEBUG;_WINDOWS;_USRDLL;UNICODE;_UNICODE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + false + true + true + nsParser.def + kernel32.lib;user32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/nsis_tchar.h b/src/nsis_tchar.h new file mode 100644 index 0000000..210bab1 --- /dev/null +++ b/src/nsis_tchar.h @@ -0,0 +1,229 @@ +/* + * nsis_tchar.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2013 Nullsoft and Contributors + * + * This software is provided 'as-is', without any express or implied + * warranty. + * + * For Unicode support by Jim Park -- 08/30/2007 + */ + +// Jim Park: Only those we use are listed here. + +#pragma once + +#ifdef _UNICODE + +#ifndef _T +#define __T(x) L ## x +#define _T(x) __T(x) +#define _TEXT(x) __T(x) +#endif + +#ifndef _TCHAR_DEFINED +#define _TCHAR_DEFINED +#if !defined(_NATIVE_WCHAR_T_DEFINED) && !defined(_WCHAR_T_DEFINED) +typedef unsigned short TCHAR; +#else +typedef wchar_t TCHAR; +#endif +#endif + + +// program +#define _tenviron _wenviron +#define __targv __wargv + +// printfs +#define _ftprintf fwprintf +#define _sntprintf _snwprintf +#if (defined(_MSC_VER) && (_MSC_VER<=1310)) || defined(__MINGW32__) +# define _stprintf swprintf +#else +# define _stprintf _swprintf +#endif +#define _tprintf wprintf +#define _vftprintf vfwprintf +#define _vsntprintf _vsnwprintf +#if defined(_MSC_VER) && (_MSC_VER<=1310) +# define _vstprintf vswprintf +#else +# define _vstprintf _vswprintf +#endif + +// scanfs +#define _tscanf wscanf +#define _stscanf swscanf + +// string manipulations +#define _tcscat wcscat +#define _tcschr wcschr +#define _tcsclen wcslen +#define _tcscpy wcscpy +#define _tcsdup _wcsdup +#define _tcslen wcslen +#define _tcsnccpy wcsncpy +#define _tcsncpy wcsncpy +#define _tcsrchr wcsrchr +#define _tcsstr wcsstr +#define _tcstok wcstok + +// string comparisons +#define _tcscmp wcscmp +#define _tcsicmp _wcsicmp +#define _tcsncicmp _wcsnicmp +#define _tcsncmp wcsncmp +#define _tcsnicmp _wcsnicmp + +// upper / lower +#define _tcslwr _wcslwr +#define _tcsupr _wcsupr +#define _totlower towlower +#define _totupper towupper + +// conversions to numbers +#define _tcstoi64 _wcstoi64 +#define _tcstol wcstol +#define _tcstoul wcstoul +#define _tstof _wtof +#define _tstoi _wtoi +#define _tstoi64 _wtoi64 +#define _ttoi _wtoi +#define _ttoi64 _wtoi64 +#define _ttol _wtol + +// conversion from numbers to strings +#define _itot _itow +#define _ltot _ltow +#define _i64tot _i64tow +#define _ui64tot _ui64tow + +// file manipulations +#define _tfopen _wfopen +#define _topen _wopen +#define _tremove _wremove +#define _tunlink _wunlink + +// reading and writing to i/o +#define _fgettc fgetwc +#define _fgetts fgetws +#define _fputts fputws +#define _gettchar getwchar + +// directory +#define _tchdir _wchdir + +// environment +#define _tgetenv _wgetenv +#define _tsystem _wsystem + +// time +#define _tcsftime wcsftime + +#else // ANSI + +#ifndef _T +#define _T(x) x +#define _TEXT(x) x +#endif + +#ifndef _TCHAR_DEFINED +#define _TCHAR_DEFINED +typedef char TCHAR; +#endif + +// program +#define _tenviron environ +#define __targv __argv + +// printfs +#define _ftprintf fprintf +#define _sntprintf _snprintf +#define _stprintf sprintf +#define _tprintf printf +#define _vftprintf vfprintf +#define _vsntprintf _vsnprintf +#define _vstprintf vsprintf + +// scanfs +#define _tscanf scanf +#define _stscanf sscanf + +// string manipulations +#define _tcscat strcat +#define _tcschr strchr +#define _tcsclen strlen +#define _tcscnlen strnlen +#define _tcscpy strcpy +#define _tcsdup _strdup +#define _tcslen strlen +#define _tcsnccpy strncpy +#define _tcsrchr strrchr +#define _tcsstr strstr +#define _tcstok strtok + +// string comparisons +#define _tcscmp strcmp +#define _tcsicmp _stricmp +#define _tcsncmp strncmp +#define _tcsncicmp _strnicmp +#define _tcsnicmp _strnicmp + +// upper / lower +#define _tcslwr _strlwr +#define _tcsupr _strupr + +#define _totupper toupper +#define _totlower tolower + +// conversions to numbers +#define _tcstol strtol +#define _tcstoul strtoul +#define _tstof atof +#define _tstoi atoi +#define _tstoi64 _atoi64 +#define _tstoi64 _atoi64 +#define _ttoi atoi +#define _ttoi64 _atoi64 +#define _ttol atol + +// conversion from numbers to strings +#define _i64tot _i64toa +#define _itot _itoa +#define _ltot _ltoa +#define _ui64tot _ui64toa + +// file manipulations +#define _tfopen fopen +#define _topen _open +#define _tremove remove +#define _tunlink _unlink + +// reading and writing to i/o +#define _fgettc fgetc +#define _fgetts fgets +#define _fputts fputs +#define _gettchar getchar + +// directory +#define _tchdir _chdir + +// environment +#define _tgetenv getenv +#define _tsystem system + +// time +#define _tcsftime strftime + +#endif + +// is functions (the same in Unicode / ANSI) +#define _istgraph isgraph +#define _istascii __isascii + +#define __TFILE__ _T(__FILE__) +#define __TDATE__ _T(__DATE__) +#define __TTIME__ _T(__TIME__) diff --git a/src/pluginapi.c b/src/pluginapi.c new file mode 100644 index 0000000..c507e31 --- /dev/null +++ b/src/pluginapi.c @@ -0,0 +1,294 @@ +#include + +#include "pluginapi.h" + +#ifdef _countof +#define COUNTOF _countof +#else +#define COUNTOF(a) (sizeof(a)/sizeof(a[0])) +#endif + +unsigned int g_stringsize; +stack_t **g_stacktop; +TCHAR *g_variables; + +// utility functions (not required but often useful) + +int NSISCALL popstring(TCHAR *str) +{ + stack_t *th; + if (!g_stacktop || !*g_stacktop) return 1; + th=(*g_stacktop); + if (str) lstrcpy(str,th->text); + *g_stacktop = th->next; + GlobalFree((HGLOBAL)th); + return 0; +} + +int NSISCALL popstringn(TCHAR *str, int maxlen) +{ + stack_t *th; + if (!g_stacktop || !*g_stacktop) return 1; + th=(*g_stacktop); + if (str) lstrcpyn(str,th->text,maxlen?maxlen:g_stringsize); + *g_stacktop = th->next; + GlobalFree((HGLOBAL)th); + return 0; +} + +void NSISCALL pushstring(const TCHAR *str) +{ + stack_t *th; + if (!g_stacktop) return; + th=(stack_t*)GlobalAlloc(GPTR,(sizeof(stack_t)+(g_stringsize)*sizeof(TCHAR))); + lstrcpyn(th->text,str,g_stringsize); + th->next=*g_stacktop; + *g_stacktop=th; +} + +TCHAR* NSISCALL getuservariable(const int varnum) +{ + if (varnum < 0 || varnum >= __INST_LAST) return NULL; + return g_variables+varnum*g_stringsize; +} + +void NSISCALL setuservariable(const int varnum, const TCHAR *var) +{ + if (var != NULL && varnum >= 0 && varnum < __INST_LAST) + lstrcpy(g_variables + varnum*g_stringsize, var); +} + +#ifdef _UNICODE +int NSISCALL PopStringA(char* ansiStr) +{ + wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, g_stringsize*sizeof(wchar_t)); + int rval = popstring(wideStr); + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); + GlobalFree((HGLOBAL)wideStr); + return rval; +} + +int NSISCALL PopStringNA(char* ansiStr, int maxlen) +{ + int realLen = maxlen ? maxlen : g_stringsize; + wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, realLen*sizeof(wchar_t)); + int rval = popstringn(wideStr, realLen); + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, realLen, NULL, NULL); + GlobalFree((HGLOBAL)wideStr); + return rval; +} + +void NSISCALL PushStringA(const char* ansiStr) +{ + wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, g_stringsize*sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); + pushstring(wideStr); + GlobalFree((HGLOBAL)wideStr); + return; +} + +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr) +{ + lstrcpyW(wideStr, getuservariable(varnum)); +} + +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr) +{ + wchar_t* wideStr = getuservariable(varnum); + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); +} + +void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr) +{ + if (ansiStr != NULL && varnum >= 0 && varnum < __INST_LAST) + { + wchar_t* wideStr = g_variables + varnum * g_stringsize; + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); + } +} + +#else +// ANSI defs +int NSISCALL PopStringW(wchar_t* wideStr) +{ + char* ansiStr = (char*) GlobalAlloc(GPTR, g_stringsize); + int rval = popstring(ansiStr); + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); + GlobalFree((HGLOBAL)ansiStr); + return rval; +} + +int NSISCALL PopStringNW(wchar_t* wideStr, int maxlen) +{ + int realLen = maxlen ? maxlen : g_stringsize; + char* ansiStr = (char*) GlobalAlloc(GPTR, realLen); + int rval = popstringn(ansiStr, realLen); + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, realLen); + GlobalFree((HGLOBAL)ansiStr); + return rval; +} + +void NSISCALL PushStringW(wchar_t* wideStr) +{ + char* ansiStr = (char*) GlobalAlloc(GPTR, g_stringsize); + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); + pushstring(ansiStr); + GlobalFree((HGLOBAL)ansiStr); +} + +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr) +{ + char* ansiStr = getuservariable(varnum); + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); +} + +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr) +{ + lstrcpyA(ansiStr, getuservariable(varnum)); +} + +void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr) +{ + if (wideStr != NULL && varnum >= 0 && varnum < __INST_LAST) + { + char* ansiStr = g_variables + varnum * g_stringsize; + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); + } +} +#endif + +// playing with integers + +INT_PTR NSISCALL nsishelper_str_to_ptr(const TCHAR *s) +{ + INT_PTR v=0; + if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X'))) + { + s++; + for (;;) + { + int c=*(++s); + if (c >= _T('0') && c <= _T('9')) c-=_T('0'); + else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10; + else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10; + else break; + v<<=4; + v+=c; + } + } + else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0')) + { + for (;;) + { + int c=*(++s); + if (c >= _T('0') && c <= _T('7')) c-=_T('0'); + else break; + v<<=3; + v+=c; + } + } + else + { + int sign=0; + if (*s == _T('-')) sign++; else s--; + for (;;) + { + int c=*(++s) - _T('0'); + if (c < 0 || c > 9) break; + v*=10; + v+=c; + } + if (sign) v = -v; + } + + return v; +} + +unsigned int NSISCALL myatou(const TCHAR *s) +{ + unsigned int v=0; + + for (;;) + { + unsigned int c=*s++; + if (c >= _T('0') && c <= _T('9')) c-=_T('0'); + else break; + v*=10; + v+=c; + } + return v; +} + +int NSISCALL myatoi_or(const TCHAR *s) +{ + int v=0; + if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X'))) + { + s++; + for (;;) + { + int c=*(++s); + if (c >= _T('0') && c <= _T('9')) c-=_T('0'); + else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10; + else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10; + else break; + v<<=4; + v+=c; + } + } + else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0')) + { + for (;;) + { + int c=*(++s); + if (c >= _T('0') && c <= _T('7')) c-=_T('0'); + else break; + v<<=3; + v+=c; + } + } + else + { + int sign=0; + if (*s == _T('-')) sign++; else s--; + for (;;) + { + int c=*(++s) - _T('0'); + if (c < 0 || c > 9) break; + v*=10; + v+=c; + } + if (sign) v = -v; + } + + // Support for simple ORed expressions + if (*s == _T('|')) + { + v |= myatoi_or(s+1); + } + + return v; +} + +INT_PTR NSISCALL popintptr() +{ + TCHAR buf[128]; + if (popstringn(buf,COUNTOF(buf))) + return 0; + return nsishelper_str_to_ptr(buf); +} + +int NSISCALL popint_or() +{ + TCHAR buf[128]; + if (popstringn(buf,COUNTOF(buf))) + return 0; + return myatoi_or(buf); +} + +void NSISCALL pushintptr(INT_PTR value) +{ + TCHAR buffer[30]; + wsprintf(buffer, sizeof(void*) > 4 ? _T("%Id") : _T("%d"), value); + pushstring(buffer); +} diff --git a/src/pluginapi.h b/src/pluginapi.h new file mode 100644 index 0000000..ca671a8 --- /dev/null +++ b/src/pluginapi.h @@ -0,0 +1,104 @@ +#ifndef ___NSIS_PLUGIN__H___ +#define ___NSIS_PLUGIN__H___ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "api.h" +#include "nsis_tchar.h" + +#ifndef NSISCALL +# define NSISCALL __stdcall +#endif + +#define EXDLL_INIT() { \ + g_stringsize=string_size; \ + g_stacktop=stacktop; \ + g_variables=variables; } + +typedef struct _stack_t { + struct _stack_t *next; + TCHAR text[1]; // this should be the length of string_size +} stack_t; + +enum +{ +INST_0, // $0 +INST_1, // $1 +INST_2, // $2 +INST_3, // $3 +INST_4, // $4 +INST_5, // $5 +INST_6, // $6 +INST_7, // $7 +INST_8, // $8 +INST_9, // $9 +INST_R0, // $R0 +INST_R1, // $R1 +INST_R2, // $R2 +INST_R3, // $R3 +INST_R4, // $R4 +INST_R5, // $R5 +INST_R6, // $R6 +INST_R7, // $R7 +INST_R8, // $R8 +INST_R9, // $R9 +INST_CMDLINE, // $CMDLINE +INST_INSTDIR, // $INSTDIR +INST_OUTDIR, // $OUTDIR +INST_EXEDIR, // $EXEDIR +INST_LANG, // $LANGUAGE +__INST_LAST +}; + +extern unsigned int g_stringsize; +extern stack_t **g_stacktop; +extern TCHAR *g_variables; + +void NSISCALL pushstring(const TCHAR *str); +void NSISCALL pushintptr(INT_PTR value); +#define pushint(v) pushintptr((INT_PTR)(v)) +int NSISCALL popstring(TCHAR *str); // 0 on success, 1 on empty stack +int NSISCALL popstringn(TCHAR *str, int maxlen); // with length limit, pass 0 for g_stringsize +INT_PTR NSISCALL popintptr(); +#define popint() ( (int) popintptr() ) +int NSISCALL popint_or(); // with support for or'ing (2|4|8) +INT_PTR NSISCALL nsishelper_str_to_ptr(const TCHAR *s); +#define myatoi(s) ( (int) nsishelper_str_to_ptr(s) ) // converts a string to an integer +unsigned int NSISCALL myatou(const TCHAR *s); // converts a string to an unsigned integer, decimal only +int NSISCALL myatoi_or(const TCHAR *s); // with support for or'ing (2|4|8) +TCHAR* NSISCALL getuservariable(const int varnum); +void NSISCALL setuservariable(const int varnum, const TCHAR *var); + +#ifdef _UNICODE +#define PopStringW(x) popstring(x) +#define PushStringW(x) pushstring(x) +#define SetUserVariableW(x,y) setuservariable(x,y) + +int NSISCALL PopStringA(char* ansiStr); +void NSISCALL PushStringA(const char* ansiStr); +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr); +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr); +void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr); + +#else +// ANSI defs + +#define PopStringA(x) popstring(x) +#define PushStringA(x) pushstring(x) +#define SetUserVariableA(x,y) setuservariable(x,y) + +int NSISCALL PopStringW(wchar_t* wideStr); +void NSISCALL PushStringW(wchar_t* wideStr); +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr); +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr); +void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif//!___NSIS_PLUGIN__H___ diff --git a/tools/build.cmd b/tools/build.cmd new file mode 100644 index 0000000..ead2dcb --- /dev/null +++ b/tools/build.cmd @@ -0,0 +1,179 @@ +@echo off@echo off + +:: Build script for nsParser plugin - All configurations:: Build script for RDMVersion NSIS plugin + + + +setlocal enabledelayedexpansionsetlocal enabledelayedexpansion + + + +:: Project pathsset PROJECT_FILE=%~dp0RDMVersion.vcxproj + +set PROJECT_DIR=%~dp0set PLUGINS_DIR=%~dp0..\plugins + +set PROJECT_FILE=%PROJECT_DIR%nsParser.vcxproj + +set PLUGINS_DIR=%~dp0..\plugins:: Find MSBuild + +set MSBUILD_PATH= + +:: Find MSBuild + +set MSBUILD_PATH=if exist "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" ( + + set MSBUILD_PATH=C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe + +if exist "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" () + + set MSBUILD_PATH=C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exeif exist "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exe" ( + +) set MSBUILD_PATH=C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exe + +if exist "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exe" () + + set MSBUILD_PATH=C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\MSBuild.exeif exist "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" ( + +) set MSBUILD_PATH=C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe + +if exist "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" () + + set MSBUILD_PATH=C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exeif exist "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" ( + +) set MSBUILD_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe + +) + +if "%MSBUILD_PATH%"=="" (if exist "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe" ( + + echo ERROR: MSBuild not found! set MSBUILD_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe + + echo Please install Visual Studio 2022 with C++ workload.) + + pause + + exit /b 1if "%MSBUILD_PATH%"=="" ( + +) echo ERROR: MSBuild not found! + + echo Please install Visual Studio 2019 or 2022 with C++ workload. + +echo ============================================ pause + +echo Building nsParser plugin - All configurations exit /b 1 + +echo ============================================) + +echo MSBuild: %MSBUILD_PATH% + +echo Project: %PROJECT_FILE%echo ============================================ + +echo.echo Building RDMVersion plugin + +echo ============================================ + +set BUILD_FAILED=0echo MSBuild: %MSBUILD_PATH% + +echo Project: %PROJECT_FILE% + +:: Build x86-ansi (Release Win32)echo. + +echo. + +echo Building x86-ansi...:: Build x86-unicode + +echo ----------------------------------------echo Building x86-unicode... + +"%MSBUILD_PATH%" "%PROJECT_FILE%" /t:Rebuild /p:Configuration="Release" /p:Platform=Win32 /p:WindowsTargetPlatformVersion=10.0 /p:PlatformToolset=v143 /maxcpucount /p:UseMultiToolTask=true /p:CL_MPCount=0 /v:minimalecho ---------------------------------------- + +if errorlevel 1 ("%MSBUILD_PATH%" "%PROJECT_FILE%" /t:Rebuild /p:Configuration="Release Unicode" /p:Platform=Win32 /p:WindowsTargetPlatformVersion=10.0 /maxcpucount /v:minimal + + echo ERROR: x86-ansi build failed! + + set BUILD_FAILED=1if errorlevel 1 ( + +) else ( echo. + + echo SUCCESS: x86-ansi DLL created echo ERROR: Build failed! + +) pause + + exit /b 1 + +:: Build x86-unicode (Release Unicode Win32)) + +echo. + +echo Building x86-unicode...:: Copy to plugins directory + +echo ----------------------------------------set OUTPUT_FILE=%~dp0Plugins\x86-unicode\RDMVersion.dll + +"%MSBUILD_PATH%" "%PROJECT_FILE%" /t:Rebuild /p:Configuration="Release Unicode" /p:Platform=Win32 /p:WindowsTargetPlatformVersion=10.0 /p:PlatformToolset=v143 /maxcpucount /p:UseMultiToolTask=true /p:CL_MPCount=0 /v:minimalset DEST_DIR=%PLUGINS_DIR%\x86-unicode + +if errorlevel 1 ( + + echo ERROR: x86-unicode build failed!if exist "%OUTPUT_FILE%" ( + + set BUILD_FAILED=1 if not exist "%DEST_DIR%" mkdir "%DEST_DIR%" + +) else ( copy /Y "%OUTPUT_FILE%" "%DEST_DIR%\" >nul + + echo SUCCESS: x86-unicode DLL created echo. + +) echo ============================================ + + echo Build successful! + +:: Build x64-ansi (Release x64) echo Plugin copied to: %DEST_DIR%\RDMVersion.dll + +echo. echo ============================================ + +echo Building x64-ansi...) else ( + +echo ---------------------------------------- echo. + +"%MSBUILD_PATH%" "%PROJECT_FILE%" /t:Rebuild /p:Configuration="Release" /p:Platform=x64 /p:WindowsTargetPlatformVersion=10.0 /p:PlatformToolset=v143 /maxcpucount /p:UseMultiToolTask=true /p:CL_MPCount=0 /v:minimal echo ERROR: Output file not found: %OUTPUT_FILE% + +if errorlevel 1 ( pause + + echo ERROR: x64-ansi build failed! exit /b 1 + + set BUILD_FAILED=1) + +) else ( + + echo SUCCESS: x64-ansi DLL createdpause + +) + +:: Build amd64-unicode (Release Unicode x64) +echo. +echo Building amd64-unicode... +echo ---------------------------------------- +"%MSBUILD_PATH%" "%PROJECT_FILE%" /t:Rebuild /p:Configuration="Release Unicode" /p:Platform=x64 /p:WindowsTargetPlatformVersion=10.0 /p:PlatformToolset=v143 /maxcpucount /p:UseMultiToolTask=true /p:CL_MPCount=0 /v:minimal +if errorlevel 1 ( + echo ERROR: amd64-unicode build failed! + set BUILD_FAILED=1 +) else ( + echo SUCCESS: amd64-unicode DLL created +) + +echo. +echo ============================================ +if %BUILD_FAILED%==1 ( + echo BUILD FAILED - Check errors above + echo ============================================ + pause + exit /b 1 +) else ( + echo BUILD SUCCESSFUL - All configurations built + echo ============================================ + echo. + echo Output files: + echo - %PLUGINS_DIR%\x86-ansi\nsParser.dll + echo - %PLUGINS_DIR%\x86-unicode\nsParser.dll + echo - %PLUGINS_DIR%\x64-ansi\nsParser.dll + echo - %PLUGINS_DIR%\amd64-unicode\nsParser.dll +) + +pause