initial: nsResize plugin 1.0.0

This commit is contained in:
2026-04-29 13:25:14 +02:00
commit c51365f97f
37 changed files with 3393 additions and 0 deletions
+24
View File
@@ -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
+52
View File
@@ -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
# 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
*.rc binary
*.rc2 binary
+76
View File
@@ -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.)
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Domande generali
url: https://gitea.emulab.it/Simone/nsis-plugin-nsresize/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-nsresize/security/advisories/new
about: Segnala vulnerabilità di security in privato (non aprire issue pubbliche)
@@ -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
+31
View File
@@ -0,0 +1,31 @@
## Descrizione
<!-- Descrivi cosa cambia questa PR e perché. Riferisci issue se applicabile (Closes #XXX). -->
## 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
<!-- Eventuali considerazioni per i reviewer, screenshot, output di test, ecc. -->
+63
View File
@@ -0,0 +1,63 @@
# 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:
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 --config ${{ 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
+99
View File
@@ -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.
+63
View File
@@ -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/
+19
View File
@@ -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-nsresize/compare/v1.0.0...HEAD
[1.0.0]: https://gitea.emulab.it/Simone/nsis-plugin-nsresize/releases/tag/v1.0.0
+137
View File
@@ -0,0 +1,137 @@
# Contribuire a nsResize
Grazie per il tuo interesse a contribuire!
> Repository primario: [https://gitea.emulab.it/Simone/nsis-plugin-nsresize](https://gitea.emulab.it/Simone/nsis-plugin-nsresize)
> Mirror GitHub: [https://github.com/systempal/nsis-plugin-nsresize](https://github.com/systempal/nsis-plugin-nsresize) (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-nsresize.git
cd nsis-plugin-nsresize
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 `<dir>/{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-nsresize/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-nsresize/issues) con label `question`.
+21
View File
@@ -0,0 +1,21 @@
zlib License
Copyright (c) 2026 Simone
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
+170
View File
@@ -0,0 +1,170 @@
# nsResize NSIS Plugin
**Personal modified version**
---
## Original Description
**Author:** Stuart 'Afrow UK' Welch
**Company:** Afrow Soft Ltd
**Date:** 13th April 2013
**Version:** 1.0.0.0
A small NSIS plug-in for moving or resizing windows/controls.
See Examples\nsResize\*.
## Macros
nsResize.nsh includes macros used by the LargeWindow example script.
## Functions
### nsResize::SetRTL
```nsis
nsResize::SetRTL $(^RTL)
```
Sets right-to-left mode on or off. This is only needed when using the nsResize::Set function.
### nsResize::Set
```nsis
nsResize::Set control_HWND x y width height
```
Sets a control's new X and Y coordinates and a new width and height. You may use the same unit values as nsDialogs. An empty string for x or y will ensure the control is not moved. An empty string for width or height will ensure the control is not resized.
### nsResize::Add
```nsis
nsResize::Add control_HWND x y width height
```
Adds the given X, Y, width and height values. You may use the same unit values as nsDialogs. Note that special treatment must be done for right-to-left languages.
### nsResize::Top
```nsis
nsResize::Top control_HWND
```
Moves a control to the top of the Z-order.
### nsResize::GetPos
```nsis
nsResize::GetPos control_HWND
Pop $X
Pop $Y
```
Gets the control position in dialog units relative to its parent window.
### nsResize::GetPosPx
```nsis
nsResize::GetPosPx control_HWND
Pop $X
Pop $Y
```
Gets the control position in pixels relative to its parent window.
### nsResize::GetSize
```nsis
nsResize::GetSize control_HWND
Pop $Width
Pop $Height
```
Gets the control size in dialog units.
### nsResize::GetSizePx
```nsis
nsResize::GetSizePx control_HWND
Pop $Width
Pop $Height
```
Gets the control size in pixels.
## License
This plug-in is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this plug-in.
Permission is granted to anyone to use this plug-in for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this plug-in must not be misrepresented; you must not claim that you wrote the original plug-in. If you use this plug-in in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered versions must be plainly marked as such, and must not be misrepresented as being the original plug-in.
3. This notice may not be removed or altered from any distribution.
---
## ⚠️ Differences in the Personal Version
This version includes the following changes from the original distribution:
### New supported architecture: x64 (amd64-unicode)
The original supported only:
- x86-ansi
- x86-unicode
The personal version adds support for:
- **amd64-unicode** (x64)
### Visual Studio Project
The original included:
- `Contrib/nsResize/nsResize.sln` - VS2012 Solution
- `Contrib/nsResize/nsResize.vcxproj` - VS2012 Project (x86 only)
The personal version updates to VS2022 with x64 support:
- `Src/nsResize.sln` - VS2022 Solution
- `Src/nsResize.vcxproj` - VS2022 Project (x86-ansi, x86-unicode, amd64-unicode)
### Changed Folder Structure
Source files have been moved from `Contrib/nsResize/` to `Src/` for a cleaner structure.
### Added Files
- `build_plugin.py` - Python script to compile the plugin for all architectures
- `Src/api.h` - NSIS API header
- `Src/pluginapi.c` / `Src/pluginapi.h` - NSIS plugin API
- `Src/nsis_tchar.h` - Header for TCHAR support
- `Src/nsis_unicode/pluginapi_x64.lib` - Plugin API library for x64
- `Src/build_pluginapi_x64.cmd` / `Src/build_pluginapi_x86.cmd` - Scripts to compile plugin API
- `Examples/nsResize/*.exe` - Compiled examples
### Build
```powershell
python build_plugin.py # Build all architectures
python build_plugin.py --config x86-unicode # Single architecture (x86-ansi|x86-unicode|amd64-unicode|all)
python build_plugin.py --toolset 2026 # Specific toolset (2022|2026|auto)
python build_plugin.py --jobs 4 # Number of parallel MSBuild jobs (default: CPU count)
python build_plugin.py --clean # Clean dist/ before build
python build_plugin.py --install-dir "C:\NSIS\Plugins" # Copy to additional NSIS directory
python build_plugin.py --verbose # Extended MSBuild output
python build_plugin.py --version # Print version and exit
```
DLLs are copied to `dist/{platform}/nsResize.dll`.
### Removed Files
Pre-compiled DLL files have been removed from the distribution:
- `Plugins/nsResize.dll`
- `Unicode/Plugins/nsResize.dll`
DLLs are generated by the build and copied to `plugins/{platform}/`.
---
*See [README_IT.md](README_IT.md) for the Italian version.*
+170
View File
@@ -0,0 +1,170 @@
# nsResize NSIS Plugin
**Versione personale modificata**
---
## Descrizione Originale
**Autore:** Stuart 'Afrow UK' Welch
**Azienda:** Afrow Soft Ltd
**Data:** 13 Aprile 2013
**Versione:** 1.0.0.0
Un piccolo plug-in NSIS per spostare o ridimensionare finestre/controlli.
Vedi Examples\nsResize\*.
## Macro
nsResize.nsh include macro usate dallo script di esempio LargeWindow.
## Funzioni
### nsResize::SetRTL
```nsis
nsResize::SetRTL $(^RTL)
```
Abilita o disabilita la modalità da destra a sinistra. Necessario solo quando si usa nsResize::Set.
### nsResize::Set
```nsis
nsResize::Set control_HWND x y width height
```
Imposta le nuove coordinate X e Y e le nuove dimensioni di un controllo. Stringa vuota per x o y = non spostare. Stringa vuota per width o height = non ridimensionare.
### nsResize::Add
```nsis
nsResize::Add control_HWND x y width height
```
Aggiunge i valori X, Y, width e height. Per lingue da destra a sinistra è necessaria una gestione speciale.
### nsResize::Top
```nsis
nsResize::Top control_HWND
```
Sposta un controllo in cima all'ordine Z.
### nsResize::GetPos
```nsis
nsResize::GetPos control_HWND
Pop $X
Pop $Y
```
Ottiene la posizione del controllo in unità dialogo relative alla finestra padre.
### nsResize::GetPosPx
```nsis
nsResize::GetPosPx control_HWND
Pop $X
Pop $Y
```
Ottiene la posizione del controllo in pixel relative alla finestra padre.
### nsResize::GetSize
```nsis
nsResize::GetSize control_HWND
Pop $Width
Pop $Height
```
Ottiene le dimensioni del controllo in unità dialogo.
### nsResize::GetSizePx
```nsis
nsResize::GetSizePx control_HWND
Pop $Width
Pop $Height
```
Ottiene le dimensioni del controllo in pixel.
## Licenza
Questo plug-in viene fornito 'così com'è', senza alcuna garanzia esplicita o implicita. In nessun caso l'autore sarà responsabile per danni derivanti dall'uso di questo plug-in.
È concessa l'autorizzazione a chiunque di usare questo plug-in per qualsiasi scopo, incluse applicazioni commerciali, e di modificarlo e ridistribuirlo liberamente, soggetto alle seguenti restrizioni:
1. L'origine di questo plug-in non deve essere travisata; non si può affermare di avere scritto il plug-in originale.
2. Le versioni alterate devono essere chiaramente contrassegnate come tali.
3. Questo avviso non può essere rimosso o alterato da alcuna distribuzione.
---
## ⚠️ Differenze nella versione personale
Questa versione include le seguenti modifiche rispetto alla distribuzione originale:
### Nuova architettura supportata: x64 (amd64-unicode)
L'originale supportava solo:
- x86-ansi
- x86-unicode
La versione personale aggiunge il supporto per:
- **amd64-unicode** (x64)
### Progetto Visual Studio
L'originale includeva:
- `Contrib/nsResize/nsResize.sln` - Solution VS2012
- `Contrib/nsResize/nsResize.vcxproj` - Progetto VS2012 (solo x86)
La versione personale aggiorna a VS2022 con supporto x64:
- `Src/nsResize.sln` - Solution VS2022
- `Src/nsResize.vcxproj` - Progetto VS2022 (x86-ansi, x86-unicode, amd64-unicode)
### Struttura cartelle modificata
I file sorgenti sono stati spostati da `Contrib/nsResize/` a `Src/` per una struttura più pulita.
### File aggiunti
- `build_plugin.py` - Script Python per compilare il plugin per tutte le architetture
- `Src/api.h` - Header API NSIS
- `Src/pluginapi.c` / `Src/pluginapi.h` - API plugin NSIS
- `Src/nsis_tchar.h` - Header per supporto TCHAR
- `Src/nsis_unicode/pluginapi_x64.lib` - Libreria plugin API per x64
- `Src/build_pluginapi_x64.cmd` / `Src/build_pluginapi_x86.cmd` - Script per compilare plugin API
- `Examples/nsResize/*.exe` - Esempi compilati
### Compilazione
```powershell
python build_plugin.py # Compila tutte le architetture
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
```
I DLL vengono copiati in `dist/{platform}/nsResize.dll`.
### File rimossi
I file DLL precompilati sono stati rimossi dalla distribuzione:
- `Plugins/nsResize.dll`
- `Unicode/Plugins/nsResize.dll`
I DLL vengono generati dalla compilazione e copiati in `plugins/{platform}/`.
---
*See [README.md](README.md) for the English version.*
+40
View File
@@ -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-nsresize/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.
+1
View File
@@ -0,0 +1 @@
1.0.0
+679
View File
@@ -0,0 +1,679 @@
#!/usr/bin/env python3
"""
Build script for nsResize 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 = 'nsResize.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 / 'nsResize.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/<plugin>/)."""
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/<dest_dir>/ to plugins/<dest_dir>/."""
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 nsResize 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 <config>/ 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 nsResize 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())
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+108
View File
@@ -0,0 +1,108 @@
nsResize NSIS plug-in
Author: Stuart 'Afrow UK' Welch
Company: Afrow Soft Ltd
Date: 13th April 2013
Version: 1.0.0.0
A small NSIS plug-in for moving or resizing windows/controls.
See Examples\nsResize\*.
------------------------------------------------------------------------
Macros
------------------------------------------------------------------------
nsResize.nsh includes macros used by the LargeWindow example script.
------------------------------------------------------------------------
Functions
------------------------------------------------------------------------
nsResize::SetRTL $(^RTL)
Sets right-to-left mode on or off. This is only needed when using the
nsResize::Set function.
------------------------------------------------------------------------
nsResize::Set control_HWND x y width height
Sets a control's new X and Y coordinates and a new width and height.
You may use the same unit values as nsDialogs. An empty string for x
or y will ensure the control is not moved. An empty string for width
or height will ensure the control is not resized.
------------------------------------------------------------------------
nsResize::Add control_HWND x y width height
Adds the given X, Y, width and height values. You may use the same
unit values as nsDialogs. Note that special treatment must be done for
right-to-left languages.
------------------------------------------------------------------------
nsResize::Top control_HWND
Moves a control to the top of the Z-order.
------------------------------------------------------------------------
nsResize::GetPos control_HWND
Pop $X
Pop $Y
Gets the control position in dialog units relative to its parent
window.
------------------------------------------------------------------------
nsResize::GetPosPx control_HWND
Pop $X
Pop $Y
Gets the control position in pixels relative to its parent window.
------------------------------------------------------------------------
nsResize::GetSize control_HWND
Pop $Width
Pop $Height
Gets the control size in dialog units.
------------------------------------------------------------------------
nsResize::GetSizePx control_HWND
Pop $Width
Pop $Height
Gets the control size in pixels.
------------------------------------------------------------------------
Change Log
------------------------------------------------------------------------
1.0.0.0 - 13th April 2013
* First version.
------------------------------------------------------------------------
License
------------------------------------------------------------------------
This plug-in is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this plug-in.
Permission is granted to anyone to use this plug-in for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this plug-in must not be misrepresented; you must not
claim that you wrote the original plug-in.
If you use this plug-in in a product, an acknowledgment in the
product documentation would be appreciated but is not required.
2. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original plug-in.
3. This notice may not be removed or altered from any distribution.
+44
View File
@@ -0,0 +1,44 @@
!addplugindir "n:\code\\Workspace\\Launchers\\plugins\\x86-unicode\\"
!include MUI2.nsh
Name Circle
OutFile Circle.exe
RequestExecutionLevel user
!insertmacro MUI_PAGE_WELCOME
Page Custom CirclePage_Show
!insertmacro MUI_LANGUAGE English
Var Label
Function CirclePage_Show
!insertmacro MUI_HEADER_TEXT `Circle` `Moves a label in a circle using a timer and absolute positioning`
nsDialogs::Create 1018
Pop $R0
${NSD_CreateLabel} 100% 100% 20u 20u ``
Pop $Label
SetCtlColors $Label 0x000000 0xFF0000
StrCpy $R0 0
${NSD_CreateTimer} CirclePage_TimerTick 50
nsDialogs::Show
${NSD_KillTimer} CirclePage_TimerTick
FunctionEnd
Function CirclePage_TimerTick
Math::Script `R0 = R0 + 0.1; R1 = 140 + sin(R0) * 140; R2 = 55 + cos(R0) * 50`
nsResize::Set $Label $R1u $R2u `` ``
FunctionEnd
Section
SectionEnd
+118
View File
@@ -0,0 +1,118 @@
/*
This script uses the nsResize plug-in to resize your NSIS installer
and uninstaller windows.
*/
!addplugindir "n:\code\\Workspace\\Launchers\\plugins\\x86-unicode\\"
!addincludedir "n:\code\\Workspace\\Launchers\\include\\"
!include MUI2.nsh
!include nsResize.nsh
Name LargeWindow
OutFile LargeWindow.exe
RequestExecutionLevel user
InstallDir $EXEDIR
ShowInstDetails show
; Increase the width and height by these units:
!define AddWidth 100u
!define AddHeight 75u
; Resizing still works with MUI interface customisation.
!define MUI_LICENSEPAGE_RADIOBUTTONS
!define MUI_COMPONENTSPAGE_SMALLDESC
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_FINISHPAGE_RUN $INSTDIR\Uninstall.exe
; These will do the initial window resizing.
!define MUI_CUSTOMFUNCTION_GUIINIT myGUIInit
!define MUI_CUSTOMFUNCTION_UNGUIINIT un.myGUIInit
; Each MUI install page must have a show function assigned.
!define MUI_PAGE_CUSTOMFUNCTION_SHOW WelcomePage_Show
!insertmacro MUI_PAGE_WELCOME
!define MUI_PAGE_CUSTOMFUNCTION_SHOW LicensePage_Show
!insertmacro MUI_PAGE_LICENSE `${__FILE__}`
!define MUI_PAGE_CUSTOMFUNCTION_SHOW DirectoryPage_Show
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_PAGE_CUSTOMFUNCTION_SHOW ComponentsPage_Show
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_PAGE_CUSTOMFUNCTION_SHOW InstFilesPage_Show
!insertmacro MUI_PAGE_INSTFILES
!define MUI_PAGE_CUSTOMFUNCTION_SHOW FinishPage_Show
!insertmacro MUI_PAGE_FINISH
; Each MUI uninstall page must have a show function assigned.
!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.WelcomePage_Show
!insertmacro MUI_UNPAGE_WELCOME
!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.ConfirmPage_Show
!insertmacro MUI_UNPAGE_CONFIRM
!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.InstFilesPage_Show
!insertmacro MUI_UNPAGE_INSTFILES
!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.FinishPage_Show
!insertmacro MUI_UNPAGE_FINISH
!insertmacro MUI_LANGUAGE English
LangString SECTION_WRITE_UNINSTALLER ${LANG_ENGLISH} `This will write an uninstaller executable into the current installation directory. The uninstaller UI has also increased in size!`
Function myGUIInit
${nsResize_Window} ${AddWidth} ${AddHeight}
FunctionEnd
Function WelcomePage_Show
${nsResize_WelcomePage} ${AddWidth} ${AddHeight}
FunctionEnd
Function LicensePage_Show
${nsResize_LicensePage} ${AddWidth} ${AddHeight}
FunctionEnd
Function DirectoryPage_Show
${nsResize_DirectoryPage} ${AddWidth} ${AddHeight}
FunctionEnd
Function ComponentsPage_Show
${nsResize_ComponentsPage} ${AddWidth} ${AddHeight}
FunctionEnd
Function InstFilesPage_Show
${nsResize_InstFilesPage} ${AddWidth} ${AddHeight}
FunctionEnd
Function FinishPage_Show
${nsResize_FinishPage} ${AddWidth} ${AddHeight}
FunctionEnd
Function un.myGUIInit
${nsResize_Window} ${AddWidth} ${AddHeight}
FunctionEnd
Function un.WelcomePage_Show
${nsResize_WelcomePage} ${AddWidth} ${AddHeight}
FunctionEnd
Function un.ConfirmPage_Show
${nsResize_ConfirmPage} ${AddWidth} ${AddHeight}
FunctionEnd
Function un.InstFilesPage_Show
${nsResize_InstFilesPage} ${AddWidth} ${AddHeight}
FunctionEnd
Function un.FinishPage_Show
${nsResize_FinishPage} ${AddWidth} ${AddHeight}
FunctionEnd
Section `Write uninstaller` SECTION_WRITE_UNINSTALLER
SectionIn RO
WriteUninstaller $INSTDIR\Uninstall.exe
MessageBox MB_OK|MB_ICONINFORMATION `Wrote: $INSTDIR\Uninstall.exe`
SectionEnd
Section Uninstall
Delete $INSTDIR\Uninstall.exe
SectionEnd
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SECTION_WRITE_UNINSTALLER} $(SECTION_WRITE_UNINSTALLER)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
+187
View File
@@ -0,0 +1,187 @@
!ifndef __nsResize_NSH__
!define __nsResize_NSH__
!macro __nsResize_AddParent Id X Y W H
GetDlgItem $R0 $HWNDPARENT ${Id}
nsResize::Add $R0 ${X} ${Y} ${W} ${H}
!macroend
!macro __nsResize_AddChild Id X Y W H
GetDlgItem $R1 $R0 ${Id}
nsResize::Add $R1 ${X} ${Y} ${W} ${H}
!macroend
!macro _nsResize_Window AddWidth AddHeight
Push $R0
nsResize::Add $HWNDPARENT 0 0 ${AddWidth} ${AddHeight}
${If} $(^RTL) == 1
!insertmacro __nsResize_AddParent 3 0 ${AddHeight} 0 0
!insertmacro __nsResize_AddParent 1 0 ${AddHeight} 0 0
!insertmacro __nsResize_AddParent 2 0 ${AddHeight} 0 0
${Else}
!insertmacro __nsResize_AddParent 3 ${AddWidth} ${AddHeight} 0 0
!insertmacro __nsResize_AddParent 1 ${AddWidth} ${AddHeight} 0 0
!insertmacro __nsResize_AddParent 2 ${AddWidth} ${AddHeight} 0 0
!insertmacro __nsResize_AddParent 1039 ${AddWidth} 0 0 0
${EndIf}
!insertmacro __nsResize_AddParent 1018 0 0 ${AddWidth} ${AddHeight}
!insertmacro __nsResize_AddParent 1044 0 0 ${AddWidth} ${AddHeight}
!insertmacro __nsResize_AddParent 1035 0 ${AddHeight} ${AddWidth} 0
!insertmacro __nsResize_AddParent 1036 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddParent 1045 0 ${AddHeight} ${AddWidth} 0
!insertmacro __nsResize_AddParent 1256 0 ${AddHeight} ${AddWidth} 0
!insertmacro __nsResize_AddParent 1028 0 ${AddHeight} ${AddWidth} 0
!insertmacro __nsResize_AddParent 1034 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddParent 1037 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddParent 1038 0 0 ${AddWidth} 0
Pop $R0
!macroend
!define nsResize_Window `!insertmacro _nsResize_Window`
!macro _nsResize_WelcomePage AddWidth AddHeight
nsResize::Add $mui.WelcomePage.Image 0 0 0 ${AddHeight}
${If} $(^RTL) == 1
nsResize::Add $mui.WelcomePage.Title -${AddWidth} 0 ${AddWidth} 0
nsResize::Add $mui.WelcomePage.Text -${AddWidth} 0 ${AddWidth} ${AddHeight}
${Else}
nsResize::Add $mui.WelcomePage.Title 0 0 ${AddWidth} 0
nsResize::Add $mui.WelcomePage.Text 0 0 ${AddWidth} ${AddHeight}
${EndIf}
!macroend
!define nsResize_WelcomePage `!insertmacro _nsResize_WelcomePage`
!macro _nsResize_LicensePage AddWidth AddHeight
Push $R0
Push $R1
FindWindow $R0 `#32770` `` $HWNDPARENT
nsResize::Add $R0 0 0 ${AddWidth} ${AddHeight}
!insertmacro __nsResize_AddChild 1040 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddChild 1000 0 0 ${AddWidth} ${AddHeight}
!insertmacro __nsResize_AddChild 1006 0 ${AddHeight} ${AddWidth} 0
!insertmacro __nsResize_AddChild 1034 0 ${AddHeight} ${AddWidth} 0
!insertmacro __nsResize_AddChild 1035 0 ${AddHeight} ${AddWidth} 0
Pop $R1
Pop $R0
!macroend
!define nsResize_LicensePage `!insertmacro _nsResize_LicensePage`
!macro _nsResize_DirectoryPage AddWidth AddHeight
Push $R0
Push $R1
FindWindow $R0 `#32770` `` $HWNDPARENT
nsResize::Add $R0 0 0 ${AddWidth} ${AddHeight}
!insertmacro __nsResize_AddChild 1019 0 0 ${AddWidth} 0
${If} $(^RTL) == 1
!insertmacro __nsResize_AddChild 1024 ${AddWidth} 0 0 0
!insertmacro __nsResize_AddChild 1023 ${AddWidth} 0 0 0
${Else}
!insertmacro __nsResize_AddChild 1001 ${AddWidth} 0 0 0
!insertmacro __nsResize_AddChild 1008 ${AddWidth} 0 0 0
${EndIf}
!insertmacro __nsResize_AddChild 1006 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddChild 1020 0 0 ${AddWidth} 0
Pop $R1
Pop $R0
!macroend
!define nsResize_DirectoryPage `!insertmacro _nsResize_DirectoryPage`
!macro _nsResize_ComponentsPage AddWidth AddHeight
Push $R0
Push $R1
FindWindow $R0 `#32770` `` $HWNDPARENT
nsResize::Add $R0 0 0 ${AddWidth} ${AddHeight}
!insertmacro __nsResize_AddChild 1017 0 0 ${AddWidth} ${AddHeight}
${If} $(^RTL) == 1
!insertmacro __nsResize_AddChild 1022 ${AddWidth} 0 0 ${AddHeight}
!insertmacro __nsResize_AddChild 1021 ${AddWidth} 0 0 0
!insertmacro __nsResize_AddChild 1023 ${AddWidth} ${AddHeight} 0 0
${Else}
!insertmacro __nsResize_AddChild 1022 0 0 0 ${AddHeight}
!insertmacro __nsResize_AddChild 1023 0 ${AddHeight} 0 0
${EndIf}
!insertmacro __nsResize_AddChild 1006 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddChild 1032 0 0 ${AddWidth} ${AddHeight}
!ifndef MUI_COMPONENTSPAGE_NODESC
!ifdef MUI_COMPONENTSPAGE_SMALLDESC
!insertmacro __nsResize_AddChild 1042 0 ${AddHeight} ${AddWidth} 0
!insertmacro __nsResize_AddChild 1043 0 ${AddHeight} ${AddWidth} 0
!else
!insertmacro __nsResize_AddChild 1042 ${AddWidth} 0 0 ${AddHeight}
!insertmacro __nsResize_AddChild 1043 ${AddWidth} 0 0 ${AddHeight}
!endif
!endif
Pop $R1
Pop $R0
!macroend
!define nsResize_ComponentsPage `!insertmacro _nsResize_ComponentsPage`
!macro _nsResize_InstFilesPage AddWidth AddHeight
Push $R0
Push $R1
FindWindow $R0 `#32770` `` $HWNDPARENT
nsResize::Add $R0 0 0 ${AddWidth} ${AddHeight}
!insertmacro __nsResize_AddChild 1004 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddChild 1006 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddChild 1016 0 0 ${AddWidth} ${AddHeight}
Pop $R1
Pop $R0
!macroend
!define nsResize_InstFilesPage `!insertmacro _nsResize_InstFilesPage`
!macro _nsResize_FinishPage AddWidth AddHeight
nsResize::Add $mui.FinishPage.Image 0 0 0 ${AddHeight}
${If} $(^RTL) == 1
nsResize::Add $mui.FinishPage.Title -${AddWidth} 0 ${AddWidth} 0
nsResize::Add $mui.FinishPage.Text -${AddWidth} 0 ${AddWidth} ${AddHeight}
${Else}
nsResize::Add $mui.FinishPage.Title 0 0 ${AddWidth} 0
nsResize::Add $mui.FinishPage.Text 0 0 ${AddWidth} ${AddHeight}
${EndIf}
!ifdef MUI_FINISHPAGE_RUN_VARIABLES
nsResize::Add $mui.FinishPage.Run 0 ${AddHeight} 0 0
!endif
!ifdef MUI_FINISHPAGE_SHOREADME_VARAIBLES ;not a typo!
nsResize::Add $mui.FinishPage.ShowReadme 0 ${AddHeight} 0 0
!endif
!ifdef MUI_FINISHPAGE_LINK
nsResize::Add $mui.FinishPage.Link 0 ${AddHeight} 0 0
!endif
!ifdef MUI_FINISHPAGE_REBOOT_VARIABLES
nsResize::Add $mui.FinishPage.RebootNow 0 ${AddHeight} 0 0
nsResize::Add $mui.FinishPage.RebootLater 0 ${AddHeight} 0 0
!endif
!macroend
!define nsResize_FinishPage `!insertmacro _nsResize_FinishPage`
!macro _nsResize_ConfirmPage AddWidth AddHeight
Push $R0
Push $R1
FindWindow $R0 `#32770` `` $HWNDPARENT
nsResize::Add $R0 0 0 ${AddWidth} ${AddHeight}
${If} $(^RTL) == 1
!insertmacro __nsResize_AddChild 1029 ${AddWidth} 0 0 0
${EndIf}
!insertmacro __nsResize_AddChild 1000 0 0 ${AddWidth} 0
!insertmacro __nsResize_AddChild 1006 0 0 ${AddWidth} 0
Pop $R1
Pop $R0
!macroend
!define nsResize_ConfirmPage `!insertmacro _nsResize_ConfirmPage`
!endif
+85
View File
@@ -0,0 +1,85 @@
/*
* apih
*
* This file is a part of NSIS.
*
* Copyright (C) 1999-2019 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 structure containing other interesting stuff
// besides the stack, variables and HWND passed on to plug-ins.
typedef struct
{
int autoclose; // SetAutoClose
int all_user_var; // SetShellVarContext: User context = 0, Machine context = 1
int exec_error; // IfErrors
int abort; // IfAbort
int exec_reboot; // IfRebootFlag (NSIS_SUPPORT_REBOOT)
int reboot_called; // NSIS_SUPPORT_REBOOT
int XXX_cur_insttype; // Deprecated
int plugin_api_version; // Plug-in ABI. See NSISPIAPIVER_CURR (Note: used to be XXX_insttype_changed)
int silent; // IfSilent (NSIS_CONFIG_SILENT_SUPPORT)
int instdir_error; // GetInstDirError
int rtl; // 1 if $LANGUAGE is a RTL language
int errlvl; // SetErrorLevel
int alter_reg_view; // SetRegView: Default View = 0, Alternative View = (sizeof(void*) > 4 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY)
int status_update; // SetDetailsPrint
} exec_flags_t;
#ifndef NSISCALL
# define NSISCALL __stdcall
#endif
#if !defined(_WIN32) && !defined(LPTSTR)
# define LPTSTR TCHAR*
#endif
typedef struct {
exec_flags_t *exec_flags;
int (NSISCALL *ExecuteCodeSegment)(int, HWND);
void (NSISCALL *validate_filename)(LPTSTR);
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 /* _NSIS_EXEHEAD_API_H_ */
+7
View File
@@ -0,0 +1,7 @@
@echo off
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
cd /d %~dp0
cl /c /O2 /DUNICODE /D_UNICODE /GS- /TC pluginapi.c /Fo:pluginapi_x64.obj
lib /OUT:nsis_unicode\pluginapi_x64.lib pluginapi_x64.obj
del pluginapi_x64.obj
echo Done!
+15
View File
@@ -0,0 +1,15 @@
@echo off
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars32.bat"
cd /d %~dp0
REM Build Unicode version
cl /c /O2 /DUNICODE /D_UNICODE /GS- /TC pluginapi.c /Fo:pluginapi_unicode.obj
lib /OUT:nsis_unicode\pluginapi.lib pluginapi_unicode.obj
del pluginapi_unicode.obj
REM Build ANSI version
cl /c /O2 /GS- /TC pluginapi.c /Fo:pluginapi_ansi.obj
lib /OUT:nsis_ansi\pluginapi.lib pluginapi_ansi.obj
del pluginapi_ansi.obj
echo Done!
+257
View File
@@ -0,0 +1,257 @@
/*
nsResize NSIS plug-in
Author: Stuart 'Afrow UK' Welch
Company: Afrow Soft Ltd.
Website: http://www.afrowsoft.co.uk
E-mail: afrowuk@afrowsoft.co.uk
Date: 13th April 2013
Version: 1.0.0.0
A small NSIS plug-in for resizing windows. Uses code from nsDialogs for unit/RTL conversion.
*/
#include <windows.h>
#include "nsResize.h"
#include "pluginapi.h"
HANDLE g_hInstance;
HWND g_hWndParent;
BOOL g_rtl;
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
g_hInstance = hInst;
return TRUE;
}
static UINT_PTR PluginCallback(enum NSPIM msg)
{
return 0;
}
static int ConvertPlacement(TCHAR* str, int total, BOOL height, BOOL add)
{
TCHAR unit = *CharPrev(str, str + lstrlen(str));
int x = myatoi(str);
if (unit == TEXT('%'))
{
if (x < 0 && !add)
return MulDiv(total, 100 + x, 100);
return MulDiv(total, x, 100);
}
if (unit == TEXT('u'))
{
RECT r;
r.left = r.top = x;
r.right = r.bottom = 0;
MapDialogRect(g_hWndParent, &r);
if (height)
return x >= 0 || add ? r.top : total + r.top;
return x >= 0 || add ? r.left : total + r.left;
}
if (x < 0 && !add)
return total + x;
return x;
}
static void ConvertPosToRTL(int *x, int width, int dialogWidth)
{
if (!g_rtl)
return;
*x = dialogWidth - width - *x;
}
static BOOL PopPlacement(HWND hWndControl, int* x, int* y, int* width, int* height, UINT* uFlags, BOOL add)
{
RECT dialogRect;
int dialogWidth;
int dialogHeight;
TCHAR buf[1024];
GetClientRect(GetParent(hWndControl), &dialogRect);
dialogWidth = dialogRect.right;
dialogHeight = dialogRect.bottom;
if (popstringn(buf, 1024))
return FALSE;
if (!*buf)
*uFlags |= SWP_NOMOVE;
else
*x = ConvertPlacement(buf, dialogWidth, FALSE, add);
if (popstringn(buf, 1024))
return FALSE;
if (!*buf)
*uFlags |= SWP_NOMOVE;
else
*y = ConvertPlacement(buf, dialogHeight, TRUE, add);
if (popstringn(buf, 1024))
return FALSE;
if (!*buf)
*uFlags |= SWP_NOSIZE;
else
*width = ConvertPlacement(buf, dialogWidth, FALSE, add);
if (popstringn(buf, 1024))
return FALSE;
if (!*buf)
*uFlags |= SWP_NOSIZE;
else
*height = ConvertPlacement(buf, dialogHeight, TRUE, add);
if (*uFlags & SWP_NOMOVE)
*x = *y = 0;
if (*uFlags & SWP_NOSIZE)
*width = *height = 0;
if (!add)
{
if (*uFlags & SWP_NOSIZE)
{
GetClientRect(hWndControl, &dialogRect);
ConvertPosToRTL(x, dialogRect.right, dialogWidth);
}
else
{
ConvertPosToRTL(x, *width, dialogWidth);
}
}
return TRUE;
}
static void GetRect(HWND hWnd, RECT* r)
{
GetWindowRect(hWnd, r);
MapWindowPoints(NULL, GetParent(hWnd), (LPPOINT)r, 2);
}
NSISFUNC(SetRTL)
{
DLL_INIT();
extra->RegisterPluginCallback((HMODULE)g_hInstance, PluginCallback);
g_rtl = (BOOL)popint();
}
NSISFUNC(Set)
{
DLL_INIT();
{
HWND hWndCtl = (HWND)popintptr();
if (IsWindow(hWndCtl))
{
int x, y, width, height;
UINT uFlags = SWP_NOZORDER;
if (PopPlacement(hWndCtl, &x, &y, &width, &height, &uFlags, FALSE))
SetWindowPos(hWndCtl, NULL, x, y, width, height, uFlags);
}
}
}
NSISFUNC(Add)
{
DLL_INIT();
{
HWND hWndCtl = (HWND)popintptr();
if (IsWindow(hWndCtl))
{
int x, y, width, height;
UINT uFlags = SWP_NOZORDER;
if (PopPlacement(hWndCtl, &x, &y, &width, &height, &uFlags, TRUE))
{
RECT pos;
GetRect(hWndCtl, &pos);
SetWindowPos(hWndCtl, NULL, pos.left + x, pos.top + y, (pos.right - pos.left) + width, (pos.bottom - pos.top) + height, uFlags);
}
}
}
}
NSISFUNC(Top)
{
DLL_INIT();
{
HWND hWndCtl = (HWND)popintptr();
if (IsWindow(hWndCtl))
{
SetWindowPos(hWndCtl, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
}
}
}
NSISFUNC(GetPosPx)
{
DLL_INIT();
{
HWND hWndCtl = (HWND)popintptr();
if (IsWindow(hWndCtl))
{
RECT pos;
GetRect(hWndCtl, &pos);
MapDialogRect(g_hWndParent, &pos);
pushint(pos.top);
pushint(pos.left);
}
}
}
NSISFUNC(GetPos)
{
DLL_INIT();
{
HWND hWndCtl = (HWND)popintptr();
if (IsWindow(hWndCtl))
{
RECT pos;
GetRect(hWndCtl, &pos);
pushint(pos.top);
pushint(pos.left);
}
}
}
NSISFUNC(GetSizePx)
{
DLL_INIT();
{
HWND hWndCtl = (HWND)popintptr();
if (IsWindow(hWndCtl))
{
RECT pos;
GetRect(hWndCtl, &pos);
MapDialogRect(g_hWndParent, &pos);
pushint(pos.bottom);
pushint(pos.right);
}
}
}
NSISFUNC(GetSize)
{
DLL_INIT();
{
HWND hWndCtl = (HWND)popintptr();
if (IsWindow(hWndCtl))
{
RECT pos;
GetRect(hWndCtl, &pos);
pushint(pos.bottom);
pushint(pos.right);
}
}
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef __NsThread_H__
#define __NsThread_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(); g_hWndParent = hWndParent; }
#endif
BIN
View File
Binary file not shown.
+23
View File
@@ -0,0 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{4977186E-7BE7-4DC5-809E-596BF31A2C8C}") = "nsResize", "nsResize.vcxproj", "{C5988C24-9154-4DE8-92E3-DF89FBFA72EC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release Unicode|Win32 = Release Unicode|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C5988C24-9154-4DE8-92E3-DF89FBFA72EC}.Debug|Win32.ActiveCfg = Debug|Win32
{C5988C24-9154-4DE8-92E3-DF89FBFA72EC}.Debug|Win32.Build.0 = Debug|Win32
{C5988C24-9154-4DE8-92E3-DF89FBFA72EC}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
{C5988C24-9154-4DE8-92E3-DF89FBFA72EC}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
{C5988C24-9154-4DE8-92E3-DF89FBFA72EC}.Release|Win32.ActiveCfg = Release|Win32
{C5988C24-9154-4DE8-92E3-DF89FBFA72EC}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+165
View File
@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Unicode|Win32">
<Configuration>Release Unicode</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Unicode|x64">
<Configuration>Release Unicode</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C5988C24-9154-4DE8-92E3-DF89FBFA72EC}</ProjectGuid>
<RootNamespace>nsResize</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
<OutDir>$(SolutionDir)..\..\Unicode\Plugins\</OutDir>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
<OutDir>$(SolutionDir)..\..\Unicode\Plugins\x64\</OutDir>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)..\..\Plugins\</OutDir>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)..\..\Plugins\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>nsis_ansi\pluginapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EntryPointSymbol>DllMain</EntryPointSymbol>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>nsis_ansi\pluginapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EntryPointSymbol>DllMain</EntryPointSymbol>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>nsis_unicode\pluginapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<EntryPointSymbol>DllMain</EntryPointSymbol>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>nsis_unicode\pluginapi_x64.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<EntryPointSymbol>DllMain</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="nsResize.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="nsResize.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="nsResize.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+35
View File
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="nsThread.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="nsThread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="nsThread.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
+229
View File
@@ -0,0 +1,229 @@
/*
* nsis_tchar.h
*
* This file is a part of NSIS.
*
* Copyright (C) 1999-2019 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||_MSC_FULL_VER<=140040310)) || 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__)
+305
View File
@@ -0,0 +1,305 @@
#include <windows.h>
#include "pluginapi.h"
#ifndef COUNTOF
#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))
#endif
// minimal tchar.h emulation
#ifndef _T
# define _T TEXT
#endif
#if !defined(TCHAR) && !defined(_TCHAR_DEFINED)
# ifdef UNICODE
# define TCHAR WCHAR
# else
# define TCHAR char
# endif
#endif
#define isvalidnsisvarindex(varnum) ( ((unsigned int)(varnum)) < (__INST_LAST) )
unsigned int g_stringsize;
stack_t **g_stacktop;
LPTSTR g_variables;
// utility functions (not required but often useful)
int NSISCALL popstring(LPTSTR 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(LPTSTR 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(LPCTSTR str)
{
stack_t *th;
if (!g_stacktop) return;
th=(stack_t*)GlobalAlloc(GPTR,(sizeof(stack_t)+(g_stringsize)*sizeof(*str)));
lstrcpyn(th->text,str,g_stringsize);
th->next=*g_stacktop;
*g_stacktop=th;
}
LPTSTR NSISCALL getuservariable(const int varnum)
{
if (!isvalidnsisvarindex(varnum)) return NULL;
return g_variables+varnum*g_stringsize;
}
void NSISCALL setuservariable(const int varnum, LPCTSTR var)
{
if (var && isvalidnsisvarindex(varnum))
lstrcpy(g_variables + varnum*g_stringsize, var);
}
#ifdef UNICODE
int NSISCALL PopStringA(LPSTR ansiStr)
{
LPWSTR wideStr = (LPWSTR) GlobalAlloc(GPTR, g_stringsize*sizeof(WCHAR));
int rval = popstring(wideStr);
WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL);
GlobalFree((HGLOBAL)wideStr);
return rval;
}
int NSISCALL PopStringNA(LPSTR ansiStr, int maxlen)
{
int realLen = maxlen ? maxlen : g_stringsize;
LPWSTR wideStr = (LPWSTR) GlobalAlloc(GPTR, realLen*sizeof(WCHAR));
int rval = popstringn(wideStr, realLen);
WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, realLen, NULL, NULL);
GlobalFree((HGLOBAL)wideStr);
return rval;
}
void NSISCALL PushStringA(LPCSTR ansiStr)
{
LPWSTR wideStr = (LPWSTR) GlobalAlloc(GPTR, g_stringsize*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize);
pushstring(wideStr);
GlobalFree((HGLOBAL)wideStr);
return;
}
void NSISCALL GetUserVariableW(const int varnum, LPWSTR wideStr)
{
lstrcpyW(wideStr, getuservariable(varnum));
}
void NSISCALL GetUserVariableA(const int varnum, LPSTR ansiStr)
{
LPWSTR wideStr = getuservariable(varnum);
WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL);
}
void NSISCALL SetUserVariableA(const int varnum, LPCSTR ansiStr)
{
if (ansiStr && isvalidnsisvarindex(varnum))
{
LPWSTR wideStr = g_variables + varnum * g_stringsize;
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize);
}
}
#else
// ANSI defs
int NSISCALL PopStringW(LPWSTR wideStr)
{
LPSTR ansiStr = (LPSTR) 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(LPWSTR wideStr, int maxlen)
{
int realLen = maxlen ? maxlen : g_stringsize;
LPSTR ansiStr = (LPSTR) GlobalAlloc(GPTR, realLen);
int rval = popstringn(ansiStr, realLen);
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, realLen);
GlobalFree((HGLOBAL)ansiStr);
return rval;
}
void NSISCALL PushStringW(LPWSTR wideStr)
{
LPSTR ansiStr = (LPSTR) 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, LPWSTR wideStr)
{
LPSTR ansiStr = getuservariable(varnum);
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize);
}
void NSISCALL GetUserVariableA(const int varnum, LPSTR ansiStr)
{
lstrcpyA(ansiStr, getuservariable(varnum));
}
void NSISCALL SetUserVariableW(const int varnum, LPCWSTR wideStr)
{
if (wideStr && isvalidnsisvarindex(varnum))
{
LPSTR 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(LPCTSTR 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(LPCTSTR 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(LPCTSTR 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);
}
+109
View File
@@ -0,0 +1,109 @@
#ifndef ___NSIS_PLUGIN__H___
#define ___NSIS_PLUGIN__H___
#ifdef __cplusplus
extern "C" {
#endif
#include "api.h"
#include "nsis_tchar.h" // BUGBUG: Why cannot our plugins use the compilers tchar.h?
#ifndef NSISCALL
# define NSISCALL WINAPI
#endif
#define EXDLL_INIT() { \
g_stringsize=string_size; \
g_stacktop=stacktop; \
g_variables=variables; }
typedef struct _stack_t {
struct _stack_t *next;
#ifdef UNICODE
WCHAR text[1]; // this should be the length of g_stringsize when allocating
#else
char text[1];
#endif
} 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 LPTSTR g_variables;
void NSISCALL pushstring(LPCTSTR str);
void NSISCALL pushintptr(INT_PTR value);
#define pushint(v) pushintptr((INT_PTR)(v))
int NSISCALL popstring(LPTSTR str); // 0 on success, 1 on empty stack
int NSISCALL popstringn(LPTSTR 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(LPCTSTR s);
#define myatoi(s) ( (int) nsishelper_str_to_ptr(s) ) // converts a string to an integer
unsigned int NSISCALL myatou(LPCTSTR s); // converts a string to an unsigned integer, decimal only
int NSISCALL myatoi_or(LPCTSTR s); // with support for or'ing (2|4|8)
LPTSTR NSISCALL getuservariable(const int varnum);
void NSISCALL setuservariable(const int varnum, LPCTSTR var);
#ifdef UNICODE
#define PopStringW(x) popstring(x)
#define PushStringW(x) pushstring(x)
#define SetUserVariableW(x,y) setuservariable(x,y)
int NSISCALL PopStringA(LPSTR ansiStr);
int NSISCALL PopStringNA(LPSTR ansiStr, int maxlen);
void NSISCALL PushStringA(LPCSTR ansiStr);
void NSISCALL GetUserVariableW(const int varnum, LPWSTR wideStr);
void NSISCALL GetUserVariableA(const int varnum, LPSTR ansiStr);
void NSISCALL SetUserVariableA(const int varnum, LPCSTR ansiStr);
#else
// ANSI defs
#define PopStringA(x) popstring(x)
#define PushStringA(x) pushstring(x)
#define SetUserVariableA(x,y) setuservariable(x,y)
int NSISCALL PopStringW(LPWSTR wideStr);
void NSISCALL PushStringW(LPWSTR wideStr);
void NSISCALL GetUserVariableW(const int varnum, LPWSTR wideStr);
void NSISCALL GetUserVariableA(const int varnum, LPSTR ansiStr);
void NSISCALL SetUserVariableW(const int varnum, LPCWSTR wideStr);
#endif
#ifdef __cplusplus
}
#endif
#endif//!___NSIS_PLUGIN__H___
+14
View File
@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by nsResize.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif