diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..54ed8cd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "versions/7-zip-zstd"] + path = versions/7-zip-zstd + url = https://github.com/mcmilk/7-Zip-zstd.git diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..eeb6fc7 --- /dev/null +++ b/build.cmd @@ -0,0 +1,7 @@ +@echo off +:: Generic wrapper for build_plugin.py +:: Usage: build.cmd [--7zip-version 19.00|25.01|26.00|zstd] [--toolset 2022|2026|auto] [...] +:: Default: --7zip-version 26.00 --toolset auto +setlocal +python "%~dp0build_plugin.py" %* +exit /b %errorlevel% diff --git a/build_1900.cmd b/build_1900.cmd new file mode 100644 index 0000000..cc7c1f3 --- /dev/null +++ b/build_1900.cmd @@ -0,0 +1,6 @@ +@echo off +:: Build ns7zip using 7-Zip 19.00 sources +:: Usage: build_1900.cmd [--toolset 2022|2026|auto] [...] +setlocal +python "%~dp0build_plugin.py" --7zip-version 19.00 %* +exit /b %errorlevel% diff --git a/build_2501.cmd b/build_2501.cmd new file mode 100644 index 0000000..4f8e629 --- /dev/null +++ b/build_2501.cmd @@ -0,0 +1,6 @@ +@echo off +:: Build ns7zip using 7-Zip 25.01 sources +:: Usage: build_2501.cmd [--toolset 2022|2026|auto] [...] +setlocal +python "%~dp0build_plugin.py" --7zip-version 25.01 %* +exit /b %errorlevel% diff --git a/build_2600.cmd b/build_2600.cmd new file mode 100644 index 0000000..876d60c --- /dev/null +++ b/build_2600.cmd @@ -0,0 +1,6 @@ +@echo off +:: Build ns7zip using 7-Zip 26.00 sources (default) +:: Usage: build_2600.cmd [--toolset 2022|2026|auto] [...] +setlocal +python "%~dp0build_plugin.py" --7zip-version 26.00 %* +exit /b %errorlevel% diff --git a/build_plugin.py b/build_plugin.py index a41e47f..ab44676 100644 --- a/build_plugin.py +++ b/build_plugin.py @@ -23,14 +23,17 @@ SCRIPTS = { "2026": "tools/legacy/build_plugin_2501_vs2026.py"}, "26.00": {"2022": None, "2026": "tools/legacy/build_plugin_2600_vs2026.py"}, + "zstd": {"2022": None, + "2026": "tools/legacy/build_plugin_zstd_vs2026.py"}, } def main() -> int: parser = argparse.ArgumentParser(description="Build nsis7z NSIS plugin") parser.add_argument("--7zip-version", dest="zip_version", - choices=["19.00", "25.01", "26.00"], default="26.00", - help="7-Zip version to build (default: 26.00)") + choices=["19.00", "25.01", "26.00", "zstd"], default="26.00", + help="7-Zip version to build (default: 26.00); " + "'zstd' uses mcmilk/7-Zip-zstd submodule") parser.add_argument("--toolset", choices=["2022", "2026", "auto"], default="auto", help="Visual Studio toolset version (default: auto)") parser.add_argument("--version", action="store_true", @@ -42,8 +45,9 @@ def main() -> int: return 0 ver = (ROOT / "VERSION").read_text(encoding="utf-8-sig").strip() + zip_label = "7z-ZS" if known.zip_version == "zstd" else f"7z {known.zip_version}" print(f"{Colors.BOLD}{Colors.BRIGHT_CYAN}=== Building ns7zip v{ver} " - f"(7z {known.zip_version}) ==={Colors.RESET}") + f"({zip_label}) ==={Colors.RESET}") toolset = known.toolset if toolset == "auto": diff --git a/build_zstd.cmd b/build_zstd.cmd new file mode 100644 index 0000000..32d7b2a --- /dev/null +++ b/build_zstd.cmd @@ -0,0 +1,6 @@ +@echo off +:: Build ns7zip using 7-Zip-zstd sources (mcmilk fork) +:: Usage: build_zstd.cmd [--toolset 2022|2026|auto] [...] +setlocal +python "%~dp0build_plugin.py" --7zip-version zstd %* +exit /b %errorlevel% diff --git a/plugins/amd64-unicode/nsis7z.dll b/plugins/amd64-unicode/nsis7z.dll new file mode 100644 index 0000000..202f5b2 Binary files /dev/null and b/plugins/amd64-unicode/nsis7z.dll differ diff --git a/plugins/x86-ansi/nsis7z.dll b/plugins/x86-ansi/nsis7z.dll new file mode 100644 index 0000000..ec6d5f0 Binary files /dev/null and b/plugins/x86-ansi/nsis7z.dll differ diff --git a/plugins/x86-unicode/nsis7z.dll b/plugins/x86-unicode/nsis7z.dll new file mode 100644 index 0000000..9515502 Binary files /dev/null and b/plugins/x86-unicode/nsis7z.dll differ diff --git a/tools/fix_vcxproj.py b/tools/fix_vcxproj.py new file mode 100644 index 0000000..82057e9 --- /dev/null +++ b/tools/fix_vcxproj.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""Add missing source files to Nsis7z_vs2026.vcxproj""" +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +vcxproj = ROOT / 'versions/zstd/CPP/7zip/Bundles/Nsis7z/Nsis7z_vs2026.vcxproj' + +# Relative paths from vcxproj dir (versions/zstd/CPP/7zip/Bundles/Nsis7z/) +# 5 levels up = versions/ +MISSING = [ + r'..\..\..\..\..\7-zip-zstd\CPP\Common\MyWindows.cpp', + r'..\..\..\..\..\7-zip-zstd\C\hashes\xxhash.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\dict_buffer.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\fl2_common.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\fl2_compress.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\fl2_pool.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\fl2_threading.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\lzma2_enc.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\radix_bitpack.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\radix_mf.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\radix_struct.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\range_enc.c', + r'..\..\..\..\..\7-zip-zstd\C\fast-lzma2\util.c', +] + +content = vcxproj.read_text(encoding='utf-8') + +ANCHOR = ' ' +if ANCHOR not in content: + print('ERROR: anchor not found in vcxproj') + exit(1) + +lines = [f' ' for p in MISSING] +block = '\n'.join(lines) + '\n ' +content = content.replace(ANCHOR, block + ANCHOR.lstrip()) +vcxproj.write_text(content, encoding='utf-8') +print(f'Added {len(MISSING)} source files to vcxproj') diff --git a/tools/legacy/build_plugin_2501_vs2026.py b/tools/legacy/build_plugin_2501_vs2026.py index 99295db..7ada1d1 100644 --- a/tools/legacy/build_plugin_2501_vs2026.py +++ b/tools/legacy/build_plugin_2501_vs2026.py @@ -84,6 +84,7 @@ def _find_msbuild_via_vswhere(vs_version: str) -> 'Optional[Tuple[Path, str, str result = subprocess.run( [ str(_VSWHERE_PATH), + '-products', '*', '-version', _VS_VERSION_RANGE[ver], '-latest', '-requires', 'Microsoft.Component.MSBuild', @@ -102,6 +103,13 @@ def _find_msbuild_via_vswhere(vs_version: str) -> 'Optional[Tuple[Path, str, str return None +# Numeric version folder used by VS2026 installer (version 18.x) +_VS_NUMERIC_FOLDER = { + '2026': '18', + '2022': '2022', +} + + def find_msbuild(vs_version: str = 'auto') -> 'Optional[Tuple[Path, str, str]]': """Find MSBuild.exe via vswhere, then well-known fallback paths. @@ -114,11 +122,16 @@ def find_msbuild(vs_version: str = 'auto') -> 'Optional[Tuple[Path, str, str]]': vs_editions = ['Community', 'Professional', 'Enterprise', 'BuildTools'] versions_to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version] for version in versions_to_try: - base_path = Path(rf'C:\Program Files\Microsoft Visual Studio\{version}') - for edition in vs_editions: - msbuild_path = base_path / edition / 'MSBuild' / 'Current' / 'Bin' / 'MSBuild.exe' - if msbuild_path.exists(): - return msbuild_path, _VS_TOOLSET[version], version + numeric = _VS_NUMERIC_FOLDER.get(version, version) + base_paths = [ + Path(rf'C:\Program Files (x86)\Microsoft Visual Studio\{numeric}'), + Path(rf'C:\Program Files\Microsoft Visual Studio\{version}'), + ] + for base_path in base_paths: + for edition in vs_editions: + msbuild_path = base_path / edition / 'MSBuild' / 'Current' / 'Bin' / 'MSBuild.exe' + if msbuild_path.exists(): + return msbuild_path, _VS_TOOLSET[version], version return None def get_project_paths() -> Tuple[Path, Path, Path]: diff --git a/tools/legacy/build_plugin_2600_vs2026.py b/tools/legacy/build_plugin_2600_vs2026.py index 4641d35..3641fc4 100644 --- a/tools/legacy/build_plugin_2600_vs2026.py +++ b/tools/legacy/build_plugin_2600_vs2026.py @@ -84,6 +84,7 @@ def _find_msbuild_via_vswhere(vs_version: str) -> 'Optional[Tuple[Path, str, str result = subprocess.run( [ str(_VSWHERE_PATH), + '-products', '*', '-version', _VS_VERSION_RANGE[ver], '-latest', '-requires', 'Microsoft.Component.MSBuild', @@ -102,6 +103,13 @@ def _find_msbuild_via_vswhere(vs_version: str) -> 'Optional[Tuple[Path, str, str return None +# Numeric version folder used by VS2026 installer (version 18.x) +_VS_NUMERIC_FOLDER = { + '2026': '18', + '2022': '2022', +} + + def find_msbuild(vs_version: str = 'auto') -> 'Optional[Tuple[Path, str, str]]': """Find MSBuild.exe via vswhere, then well-known fallback paths. @@ -114,11 +122,16 @@ def find_msbuild(vs_version: str = 'auto') -> 'Optional[Tuple[Path, str, str]]': vs_editions = ['Community', 'Professional', 'Enterprise', 'BuildTools'] versions_to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version] for version in versions_to_try: - base_path = Path(rf'C:\Program Files\Microsoft Visual Studio\{version}') - for edition in vs_editions: - msbuild_path = base_path / edition / 'MSBuild' / 'Current' / 'Bin' / 'MSBuild.exe' - if msbuild_path.exists(): - return msbuild_path, _VS_TOOLSET[version], version + numeric = _VS_NUMERIC_FOLDER.get(version, version) + base_paths = [ + Path(rf'C:\Program Files (x86)\Microsoft Visual Studio\{numeric}'), + Path(rf'C:\Program Files\Microsoft Visual Studio\{version}'), + ] + for base_path in base_paths: + for edition in vs_editions: + msbuild_path = base_path / edition / 'MSBuild' / 'Current' / 'Bin' / 'MSBuild.exe' + if msbuild_path.exists(): + return msbuild_path, _VS_TOOLSET[version], version return None def get_project_paths(toolset: str = 'v145') -> Tuple[Path, Path, Path]: diff --git a/tools/legacy/build_plugin_vs2026.py b/tools/legacy/build_plugin_vs2026.py index c041c19..b9ed587 100644 --- a/tools/legacy/build_plugin_vs2026.py +++ b/tools/legacy/build_plugin_vs2026.py @@ -84,6 +84,7 @@ def _find_msbuild_via_vswhere(vs_version: str) -> 'Optional[Tuple[Path, str, str result = subprocess.run( [ str(_VSWHERE_PATH), + '-products', '*', '-version', _VS_VERSION_RANGE[ver], '-latest', '-requires', 'Microsoft.Component.MSBuild', @@ -102,6 +103,13 @@ def _find_msbuild_via_vswhere(vs_version: str) -> 'Optional[Tuple[Path, str, str return None +# Numeric version folder used by VS2026 installer (version 18.x) +_VS_NUMERIC_FOLDER = { + '2026': '18', + '2022': '2022', +} + + def find_msbuild(vs_version: str = 'auto') -> 'Optional[Tuple[Path, str, str]]': """Find MSBuild.exe via vswhere, then well-known fallback paths. @@ -114,11 +122,16 @@ def find_msbuild(vs_version: str = 'auto') -> 'Optional[Tuple[Path, str, str]]': vs_editions = ['Community', 'Professional', 'Enterprise', 'BuildTools'] versions_to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version] for version in versions_to_try: - base_path = Path(rf'C:\Program Files\Microsoft Visual Studio\{version}') - for edition in vs_editions: - msbuild_path = base_path / edition / 'MSBuild' / 'Current' / 'Bin' / 'MSBuild.exe' - if msbuild_path.exists(): - return msbuild_path, _VS_TOOLSET[version], version + numeric = _VS_NUMERIC_FOLDER.get(version, version) + base_paths = [ + Path(rf'C:\Program Files (x86)\Microsoft Visual Studio\{numeric}'), + Path(rf'C:\Program Files\Microsoft Visual Studio\{version}'), + ] + for base_path in base_paths: + for edition in vs_editions: + msbuild_path = base_path / edition / 'MSBuild' / 'Current' / 'Bin' / 'MSBuild.exe' + if msbuild_path.exists(): + return msbuild_path, _VS_TOOLSET[version], version return None def get_project_paths() -> Tuple[Path, Path, Path]: diff --git a/tools/legacy/build_plugin_zstd_vs2026.py b/tools/legacy/build_plugin_zstd_vs2026.py new file mode 100644 index 0000000..5913559 --- /dev/null +++ b/tools/legacy/build_plugin_zstd_vs2026.py @@ -0,0 +1,700 @@ +#!/usr/bin/env python3 +""" +Build script for nsis7z plugin (7-Zip ZS / mcmilk/7-Zip-zstd) - Visual Studio 2026 +Supports multiple build configurations with flexible parameters. +Uses PlatformToolset v145 (Visual Studio 2026 Build Tools). + +The 7-Zip ZS source is pulled from the git submodule at versions/7-zip-zstd/. +The NSIS plugin wrapper (nsis7z.cpp, vcxproj, …) lives in versions/zstd/. + +NOTE: VS2026 Build Tools use v145 toolset (version 18.x) +""" + +import argparse +import os +import sys +import subprocess +import shutil +import time +import multiprocessing +import threading +from concurrent.futures import ThreadPoolExecutor, as_completed +from pathlib import Path +from typing import List, Tuple, Optional +import xml.etree.ElementTree as ET + + +class BuildConfig: + """Configuration for a single build target""" + 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 + + +# Predefined build configurations +CONFIGS = { + 'x86-unicode': BuildConfig( + name='x86-unicode', + config='Release Unicode', + platform='Win32', + dest_dir='x86-unicode' + ), + 'x64-unicode': BuildConfig( + name='x64-unicode', + config='Release Unicode', + platform='x64', + dest_dir='amd64-unicode' + ), + 'x86-ansi': BuildConfig( + name='x86-ansi', + config='Release', + platform='Win32', + dest_dir='x86-ansi' + ), +} + + +# Standard vswhere.exe location (installed with any VS 2017+ setup) +_VSWHERE_PATH = Path(r'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe') + +# vswhere version range per VS year +_VS_VERSION_RANGE = { + '2026': '[18.0,19.0)', + '2022': '[17.0,18.0)', +} + +# MSBuild toolset per VS year +_VS_TOOLSET = { + '2026': 'v145', # VS 2026 uses v145 toolset + '2022': 'v143', # VS 2022 uses v143 toolset +} + + +def _find_msbuild_via_vswhere(vs_version: str) -> 'Optional[Tuple[Path, str, str]]': + """Locate MSBuild via vswhere.exe.""" + if not _VSWHERE_PATH.exists(): + return None + versions_to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version] + for ver in versions_to_try: + if ver not in _VS_VERSION_RANGE: + continue + try: + result = subprocess.run( + [ + str(_VSWHERE_PATH), + '-products', '*', + '-version', _VS_VERSION_RANGE[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: + msbuild_path = Path(lines[0]) + if msbuild_path.exists(): + return msbuild_path, _VS_TOOLSET[ver], ver + except Exception: + pass + return None + + +# Numeric version folder used by VS2026 installer (version 18.x) +_VS_NUMERIC_FOLDER = { + '2026': '18', + '2022': '2022', +} + + +def find_msbuild(vs_version: str = 'auto') -> 'Optional[Tuple[Path, str, str]]': + """Find MSBuild.exe via vswhere, then well-known fallback paths. + + Returns (msbuild_path, toolset_version, vs_year) or None. + """ + result = _find_msbuild_via_vswhere(vs_version) + if result is not None: + return result + + vs_editions = ['Community', 'Professional', 'Enterprise', 'BuildTools'] + versions_to_try = ['2026', '2022'] if vs_version == 'auto' else [vs_version] + for version in versions_to_try: + numeric = _VS_NUMERIC_FOLDER.get(version, version) + base_paths = [ + Path(rf'C:\Program Files (x86)\Microsoft Visual Studio\{numeric}'), + Path(rf'C:\Program Files\Microsoft Visual Studio\{version}'), + ] + for base_path in base_paths: + for edition in vs_editions: + msbuild_path = base_path / edition / 'MSBuild' / 'Current' / 'Bin' / 'MSBuild.exe' + if msbuild_path.exists(): + return msbuild_path, _VS_TOOLSET[version], version + return None + + +def get_project_paths(toolset: str = 'v145') -> Tuple[Path, Path, Path]: + """Get project directory, project file, and plugins directory""" + script_dir = Path(__file__).parent.absolute() + project_dir = script_dir.parent.parent / 'versions' / 'zstd' + vcxproj = 'Nsis7z_vs2026.vcxproj' + project_file = project_dir / 'CPP' / '7zip' / 'Bundles' / 'Nsis7z' / vcxproj + plugins_dir = script_dir.parent.parent / 'plugins' + + return project_dir, project_file, plugins_dir + + +def get_cpu_info() -> dict: + """Get CPU information for parallel build optimization""" + try: + import psutil + logical_cores = psutil.cpu_count(logical=True) + physical_cores = psutil.cpu_count(logical=False) + + return { + 'logical_cores': logical_cores, + 'physical_cores': physical_cores, + 'has_hyperthreading': logical_cores > physical_cores, + 'has_psutil': True + } + except ImportError: + cpu_count = multiprocessing.cpu_count() + return { + 'logical_cores': cpu_count, + 'physical_cores': cpu_count, + 'has_hyperthreading': False, + 'has_psutil': False + } + + +def get_optimal_thread_count() -> int: + """Get optimal thread count for compilation""" + cpu_info = get_cpu_info() + if cpu_info['has_hyperthreading'] and cpu_info['physical_cores'] > 1: + return cpu_info['physical_cores'] + return cpu_info['logical_cores'] + + +def get_build_optimizations() -> List[str]: + """Get additional build optimization flags""" + return [ + '/p:BuildInParallel=true', + '/p:MultiProcessorCompilation=true', + '/p:PreferredToolArchitecture=x64', + '/p:UseSharedCompilation=true', + '/p:TrackFileAccess=false', + '/nodeReuse:true', + '/p:GenerateResourceUsePreserializedResources=true' + ] + + +def get_memory_optimizations() -> List[str]: + """Get memory optimization flags for faster builds""" + try: + import psutil + memory_gb = psutil.virtual_memory().total / (1024 ** 3) + if memory_gb >= 16: + return [ + '/p:DisableFastUpToDateCheck=false', + '/p:BuildProjectReferences=true', + '/p:UseCommonOutputDirectory=false' + ] + elif memory_gb >= 8: + return ['/p:DisableFastUpToDateCheck=false'] + else: + return [] + except ImportError: + return ['/p:DisableFastUpToDateCheck=false'] + + +def print_cpu_info(use_parallel: bool, use_optimizations: bool = True) -> None: + """Print CPU information for build optimization""" + if not use_parallel: + print("Build mode: Single-threaded") + if use_optimizations: + print("Optimizations: ENABLED (memory, caching)") + return + + cpu_info = get_cpu_info() + optimal_threads = get_optimal_thread_count() + + print("Build mode: Parallel") + print(f"Logical cores: {cpu_info['logical_cores']}") + print(f"Physical cores: {cpu_info['physical_cores']}") + + if cpu_info['has_hyperthreading']: + print("Hyperthreading: ENABLED") + print(f"Optimal threads: {optimal_threads} (using physical cores)") + else: + print("Hyperthreading: NOT AVAILABLE") + print(f"Optimal threads: {optimal_threads}") + + print(f"MSBuild threads: {optimal_threads}") + + if use_optimizations: + print("Optimizations: ENABLED (parallel, memory, caching)") + try: + import psutil + memory_gb = psutil.virtual_memory().total / (1024 ** 3) + print(f"Available memory: {memory_gb:.1f} GB") + except ImportError: + print("Available memory: Unknown (install psutil for details)") + else: + print("Optimizations: DISABLED") + + if not cpu_info['has_psutil']: + print("Note: Install 'psutil' for detailed CPU/memory info (pip install psutil)") + + print() + + +def build_configuration( + msbuild_path: Path, + project_file: Path, + config: BuildConfig, + rebuild: bool = True, + verbosity: str = 'quiet', + parallel: bool = True, + optimizations: bool = True, + counter: str = "", + capture_output: bool = False, + toolset: str = 'v145', +) -> Tuple[bool, float, str]: + """Build a single configuration. + + Returns (success, elapsed_time, captured_output). + """ + 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={toolset}', + f'/v:{verbosity}', + ] + + if parallel: + optimal_threads = get_optimal_thread_count() + cmd.extend([ + f'/maxcpucount:{optimal_threads}', + '/p:UseMultiToolTask=true', + f'/p:CL_MPCount={optimal_threads}' + ]) + + if optimizations: + cmd.extend(get_build_optimizations()) + cmd.extend(get_memory_optimizations()) + cache_dir = setup_build_cache() + if cache_dir: + cmd.append('/p:MSBuildCacheEnabled=true') + + if not capture_output: + print(f"\n{'=' * 50}") + if counter: + print(f"Building {config.name} [{counter}]") + else: + print(f"Building {config.name}...") + print('=' * 50) + + start_time = time.time() + try: + if capture_output: + result = subprocess.run(cmd, check=False, capture_output=True, text=True) + elapsed = time.time() - start_time + return result.returncode == 0, elapsed, result.stdout + result.stderr + else: + result = subprocess.run(cmd, check=False) + elapsed = time.time() - start_time + return result.returncode == 0, elapsed, "" + except Exception as e: + elapsed = time.time() - start_time + 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, + plugins_dir: Path, + config: BuildConfig +) -> Tuple[bool, int, Optional[Path]]: + """Copy built DLL to destination directory. + + Returns (success, file_size, dest_path). + """ + output_file = ( + project_dir / 'CPP' / '7zip' / 'Bundles' / 'Nsis7z' + / 'Build' / config.name / 'nsis7z.dll' + ) + dest_dir = plugins_dir / config.dest_dir + + if not output_file.exists(): + print(f"ERROR: {config.name} DLL not found at {output_file}") + return False, 0, None + + dest_dir.mkdir(parents=True, exist_ok=True) + + try: + dest_path = dest_dir / 'nsis7z.dll' + shutil.copy2(output_file, dest_path) + file_size = output_file.stat().st_size + print(f"SUCCESS: {config.name} - {file_size:,} bytes - Copied to {dest_dir}") + return True, file_size, dest_path + except Exception as e: + print(f"ERROR: Failed to copy {config.name}: {e}") + return False, 0, None + + +def clean_build_artifacts(project_dir: Path, configs: List[BuildConfig]) -> None: + """Clean up build artifacts""" + print("\nCleaning build artifacts...") + + build_base_dir = ( + project_dir / 'CPP' / '7zip' / 'Bundles' / 'Nsis7z' / 'Build' + ) + + dirs_to_clean = {build_base_dir / config.name for config in configs} + + for dir_path in dirs_to_clean: + if dir_path.exists(): + try: + shutil.rmtree(dir_path) + print(f" - Cleaned: {dir_path.name}") + except Exception as e: + print(f" - Failed to clean {dir_path.name}: {e}") + + print("Build artifacts cleaned successfully.") + + +def format_time(seconds: float) -> str: + """Format seconds to human-readable string""" + if seconds < 60: + return f"{seconds:.2f}s" + elif seconds < 3600: + minutes = int(seconds // 60) + secs = seconds % 60 + return f"{minutes}m {secs:.1f}s" + else: + hours = int(seconds // 3600) + minutes = int((seconds % 3600) // 60) + secs = seconds % 60 + return f"{hours}h {minutes}m {secs:.0f}s" + + +def setup_build_cache() -> Optional[str]: + """Setup build cache directory for faster incremental builds""" + try: + cache_dir = Path.home() / '.msbuild_cache' / 'nsis7z-zstd-vs2026' + cache_dir.mkdir(parents=True, exist_ok=True) + return str(cache_dir) + except Exception: + return None + + +def get_available_configurations(project_file: Path) -> List[Tuple[str, str]]: + """Parse .vcxproj file to get available configurations""" + try: + tree = ET.parse(project_file) + root = tree.getroot() + ns = {'ms': 'http://schemas.microsoft.com/developer/msbuild/2003'} + configs = [] + for item_group in root.findall('.//ms:ItemGroup', ns): + for proj_config in item_group.findall('ms:ProjectConfiguration', ns): + include = proj_config.get('Include') + if include: + parts = include.split('|') + if len(parts) == 2: + configs.append((parts[0], parts[1])) + return configs + except Exception as e: + print(f"Warning: Could not parse project file: {e}") + return [] + + +def print_available_configurations(project_file: Path) -> None: + """Print all configurations available in the project""" + configs = get_available_configurations(project_file) + if not configs: + print("No configurations found or could not read project file.") + return + + print("Available configurations in project:") + print("-" * 60) + from collections import defaultdict + grouped = defaultdict(list) + for config, platform in configs: + grouped[config].append(platform) + for config_name in sorted(grouped.keys()): + platforms = ', '.join(sorted(grouped[config_name])) + print(f" {config_name:25s} - {platforms}") + print(f"\nTotal: {len(configs)} configuration(s)") + print() + print("Configurations mapped in this build script:") + print("-" * 60) + for name, config in CONFIGS.items(): + print(f" {name:15s} -> {config.config} / {config.platform}") + print() + + +_print_lock = threading.Lock() + + +def _build_configs_parallel( + msbuild_path: Path, + project_file: Path, + configs: 'List[BuildConfig]', + *, + rebuild: bool, + verbosity: str, + parallel: bool, + optimizations: bool, + project_dir: Path, + plugins_dir: Path, + toolset: str = 'v145', +) -> list: + """Build all configurations simultaneously, printing output atomically.""" + n = len(configs) + print(f"\nParallel-configs: 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'): + success, build_time, captured = build_configuration( + msbuild_path, project_file, config, + rebuild=rebuild, verbosity=verbosity, + parallel=parallel, optimizations=optimizations, + capture_output=True, toolset=toolset, + ) + import io, contextlib + copy_buf = io.StringIO() + if success: + with contextlib.redirect_stdout(copy_buf): + copy_ok, file_size, dest_path = copy_output(project_dir, plugins_dir, config) + else: + copy_ok, file_size, dest_path = False, 0, None + + with _print_lock: + all_ok = success and copy_ok + tag = "OK" if all_ok else "FAILED" + size_str = f"{file_size:,} bytes" if file_size > 0 else "N/A" + print(f"[{tag}] {config.name} ({format_time(build_time)}) {size_str}") + if dest_path: + print(f" -> {dest_path}") + if not all_ok: + copy_out = copy_buf.getvalue() + if copy_out.strip(): + print(copy_out.rstrip()) + if captured.strip(): + print("--- Build output ---") + print(captured.rstrip()) + + with idx_lock: + results_by_idx[idx] = (config, success and copy_ok, build_time, file_size, dest_path) + + 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): + 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.time() - total_start + print(f"\nAll {n} configs finished in {format_time(wall_time)} (wall clock)") + return [results_by_idx[i] for i in range(n)] + + +def main(): + """Main build function""" + parser = argparse.ArgumentParser( + description='Build nsis7z plugin (7-Zip ZS / mcmilk/7-Zip-zstd, Visual Studio 2026)', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + %(prog)s # Build all configurations + %(prog)s --list # List script configurations + %(prog)s --list-project # List all project configurations + %(prog)s --configs x86-unicode # Build only x86-unicode + %(prog)s --configs x86-unicode x64-unicode + %(prog)s --no-rebuild # Incremental build + %(prog)s --no-parallel # Single-threaded build + %(prog)s --no-clean # Skip cleanup + %(prog)s --verbosity minimal # Show more build output + """ + ) + + parser.add_argument( + '--configs', nargs='+', + choices=list(CONFIGS.keys()) + ['all'], + default=['all'], + help='Configurations to build (default: all)' + ) + parser.add_argument('--rebuild', action='store_true', default=True) + parser.add_argument('--no-rebuild', action='store_false', dest='rebuild', + help='Incremental build (only changed files)') + 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=True) + parser.add_argument('--no-clean', action='store_false', dest='clean') + parser.add_argument('--list', action='store_true', + help='List script configurations and exit') + parser.add_argument('--list-project', action='store_true', + help='List all configurations in the .vcxproj and exit') + parser.add_argument('--pause', action='store_true', + help='Wait for key press at the end') + parser.add_argument('--no-optimizations', action='store_true', + help='Disable additional build optimizations') + parser.add_argument('--vs-version', choices=['auto', '2026', '2022'], default='auto', + help='Visual Studio version to use (default: auto)') + + args = parser.parse_args() + + # Find MSBuild + msbuild_result = find_msbuild(args.vs_version) + if not msbuild_result: + print("ERROR: MSBuild not found!") + return 1 + msbuild_path, platform_toolset, vs_version_name = msbuild_result + + # Get project paths + project_dir, project_file, plugins_dir = get_project_paths(platform_toolset) + + if args.list_project: + if not project_file.exists(): + print(f"ERROR: Project file not found: {project_file}") + return 1 + print_available_configurations(project_file) + return 0 + + if args.list: + print("Build script configurations (7-Zip ZS / mcmilk, VS2026):") + print("-" * 60) + for name, config in CONFIGS.items(): + print(f" {name:15s} -> {config.config} / {config.platform}") + print(f"\nTotal: {len(CONFIGS)} configuration(s)") + return 0 + + if not project_file.exists(): + print(f"ERROR: Project file not found: {project_file}") + print() + print("Make sure the submodule is initialised:") + print(" git submodule update --init versions/7-zip-zstd") + return 1 + + # Determine configurations to build + if 'all' in args.configs: + configs_to_build = list(CONFIGS.values()) + else: + configs_to_build = [CONFIGS[name] for name in args.configs] + + # Print header + print("=" * 60) + print( + f"Building nsis7z plugin (7-Zip ZS, VS2026)" + f" - {len(configs_to_build)} configuration(s)" + ) + print("=" * 60) + print(f"Visual Studio: {vs_version_name} (toolset {platform_toolset})") + print(f"MSBuild: {msbuild_path}") + print(f"Project: {project_file}") + print(f"Plugins: {plugins_dir}") + print(f"Rebuild: {args.rebuild}") + print(f"Verbosity: {args.verbosity}") + print() + + use_optimizations = not args.no_optimizations + print_cpu_info(args.parallel, use_optimizations) + + # Build + build_results = [] + total_start_time = time.time() + + if args.parallel and len(configs_to_build) > 1: + build_results = _build_configs_parallel( + msbuild_path, project_file, configs_to_build, + rebuild=args.rebuild, verbosity=args.verbosity, + parallel=args.parallel, optimizations=use_optimizations, + project_dir=project_dir, plugins_dir=plugins_dir, + toolset=platform_toolset, + ) + else: + for i, config in enumerate(configs_to_build, 1): + success, build_time, _ = build_configuration( + msbuild_path, project_file, config, + rebuild=args.rebuild, verbosity=args.verbosity, + parallel=args.parallel, optimizations=use_optimizations, + counter=f"{i}/{len(configs_to_build)}", + toolset=platform_toolset, + ) + + if not success: + print(f"ERROR: {config.name} build failed! (Time: {format_time(build_time)})") + build_results.append((config, False, build_time, 0, None)) + continue + + success, file_size, dest_path = copy_output(project_dir, plugins_dir, config) + print(f"Build time: {format_time(build_time)}") + build_results.append((config, success, build_time, file_size, dest_path)) + + total_time = time.time() - total_start_time + + # Summary + print("\n" + "=" * 50) + all_success = all(success for _, success, _, _, _ in build_results) + + if all_success: + print("ALL BUILDS SUCCESSFUL!") + print("=" * 50) + print("\nPlugins copied to:") + for config, _, build_time, file_size, dest_path in build_results: + dest = dest_path or plugins_dir / config.dest_dir / 'nsis7z.dll' + print(f" - {dest}") + if args.clean: + print() + clean_build_artifacts(project_dir, configs_to_build) + else: + print("SOME BUILDS FAILED!") + print("=" * 50) + print("\nFailed configurations:") + for config, success, build_time, file_size, dest_path in build_results: + if not success: + print(f" - {config.name}") + + print("\n" + "-" * 50) + print("Build Summary:") + for config, success, build_time, file_size, dest_path in build_results: + status = "OK" if success else "FAIL" + size_str = f"{file_size:,} bytes" if file_size > 0 else "N/A" + print(f" {status} {config.name:15s} - {format_time(build_time):8s} - {size_str}") + print("-" * 50) + print(f"Total time: {format_time(total_time)}") + print() + + if args.pause: + try: + input("Press Enter to continue...") + except EOFError: + pass + + return 0 if all_success else 1 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/versions/7-zip-zstd b/versions/7-zip-zstd new file mode 160000 index 0000000..6146959 --- /dev/null +++ b/versions/7-zip-zstd @@ -0,0 +1 @@ +Subproject commit 6146959af008acfb7e92c7d38ef9e43bf9f6afbb diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/Nsis7z_vs2026.vcxproj b/versions/zstd/CPP/7zip/Bundles/Nsis7z/Nsis7z_vs2026.vcxproj new file mode 100644 index 0000000..a994824 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/Nsis7z_vs2026.vcxproj @@ -0,0 +1,1023 @@ + + + + + + Debug Unicode + Win32 + + + Debug Unicode + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release Unicode + Win32 + + + Release Unicode + x64 + + + Release + Win32 + + + Release + x64 + + + + + + {B3A7F2E1-9DC8-4B51-A36F-C4D33E86A6FD} + 10.0.26100.0 + + + + DynamicLibrary + v145 + false + MultiByte + + + DynamicLibrary + v145 + false + MultiByte + + + DynamicLibrary + v145 + false + Unicode + + + DynamicLibrary + v145 + false + Unicode + + + DynamicLibrary + v145 + false + Unicode + + + DynamicLibrary + v145 + false + Unicode + + + DynamicLibrary + v145 + false + MultiByte + + + DynamicLibrary + v145 + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + nsis7z + $(Configuration)\ + $(Configuration)\ + + + false + false + nsis7z + + + true + false + + + true + false + nsis7z + + + false + false + nsis7z + $(Configuration)\ + $(Configuration)\ + + + false + false + nsis7z + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + + + true + false + + + true + false + nsis7z + + + + + MultiThreaded + Default + true + true + MinSpace + true + false + true + Level3 + ..\..\..\..\..\7-zip-zstd\CPP\;..\..\..\..\..\7-zip-zstd\;..\..\..\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;%(PreprocessorDefinitions) + AssemblyAndMachineCode + FastCall + None + 4100 + + + .\Release\Alone.tlb + + + 0x0419 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\Alone.bsc + + + true + + + No + UseLinkTimeCodeGeneration + true + true + + + + + + MultiThreaded + Default + true + true + MinSpace + true + false + true + Level3 + ..\..\..\..\..\7-zip-zstd\CPP\;..\..\..\..\..\7-zip-zstd\;..\..\..\;%(AdditionalIncludeDirectories) + NDEBUG;WIN32;%(PreprocessorDefinitions) + AssemblyAndMachineCode + FastCall + + + .\Release\Alone.tlb + + + 0x0419 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\Alone.bsc + + + true + + + UseLinkTimeCodeGeneration + true + true + + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level4 + true + EditAndContinue + ..\..\..\..\..\7-zip-zstd\CPP\;..\..\..\..\..\7-zip-zstd\;..\..\..\;%(AdditionalIncludeDirectories) + _DEBUG;UNICODE;WIN32;_CONSOLE;%(PreprocessorDefinitions) + NotUsing + FastCall + EnableFastChecks + + + .\DebugU\Alone.tlb + + + 0x0419 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\DebugU\Alone.bsc + + + true + true + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level4 + ProgramDatabase + ..\..\..\..\..\7-zip-zstd\CPP\;..\..\..\..\..\7-zip-zstd\;..\..\..\;%(AdditionalIncludeDirectories) + _DEBUG;UNICODE;WIN32;_CONSOLE;%(PreprocessorDefinitions) + NotUsing + FastCall + EnableFastChecks + + + .\DebugU\Alone.tlb + + + 0x0419 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\DebugU\Alone.bsc + + + true + true + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + MultiThreaded + Default + true + true + MinSpace + true + false + true + Level4 + ..\..\..\..\..\7-zip-zstd\CPP\;..\..\..\..\..\7-zip-zstd\;..\..\..\;%(AdditionalIncludeDirectories) + NDEBUG;UNICODE;WIN32;%(PreprocessorDefinitions) + NotUsing + FastCall + None + 4100 + + + .\ReleaseU\Alone.tlb + + + 0x0419 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\ReleaseU\Alone.bsc + + + true + + + No + UseLinkTimeCodeGeneration + true + true + + + + + + MultiThreaded + Default + true + true + MinSpace + true + false + true + Level4 + ..\..\..\..\..\7-zip-zstd\CPP\;..\..\..\..\..\7-zip-zstd\;..\..\..\;%(AdditionalIncludeDirectories) + NDEBUG;UNICODE;WIN32;%(PreprocessorDefinitions) + NotUsing + FastCall + None + 4100 + + + .\ReleaseU\Alone.tlb + + + 0x0419 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\ReleaseU\Alone.bsc + + + true + + + No + UseLinkTimeCodeGeneration + true + true + + + + + + MultiThreadedDebugDLL + Default + Disabled + true + Level3 + true + EditAndContinue + ..\..\..\..\..\7-zip-zstd\CPP\;..\..\..\..\..\7-zip-zstd\;..\..\..\;%(AdditionalIncludeDirectories) + _DEBUG;WIN32;_CONSOLE;%(PreprocessorDefinitions) + FastCall + EnableFastChecks + + + .\Debug\Alone.tlb + + + 0x0419 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\Alone.bsc + + + true + true + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + ProgramDatabase + ..\..\..\..\..\7-zip-zstd\CPP\;..\..\..\..\..\7-zip-zstd\;..\..\..\;%(AdditionalIncludeDirectories) + _DEBUG;WIN32;_CONSOLE;%(PreprocessorDefinitions) + FastCall + EnableFastChecks + + + .\Debug\Alone.tlb + + + 0x0419 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\Alone.bsc + + + true + true + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + StdAfx.h + StdAfx.h + Create + Create + StdAfx.h + StdAfx.h + Create + Create + StdAfx.h + StdAfx.h + Create + Create + StdAfx.h + StdAfx.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/StdAfx.h b/versions/zstd/CPP/7zip/Bundles/Nsis7z/StdAfx.h new file mode 100644 index 0000000..26f54c6 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/StdAfx.h @@ -0,0 +1,13 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "Common/Common.h" +#include +#include +#include "Common/MyWindows.h" +#include "Common/NewHandler.h" +#include "pluginapi.h" + +#endif diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/StdAfx2.cpp b/versions/zstd/CPP/7zip/Bundles/Nsis7z/StdAfx2.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/StdAfx2.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/afxres.h b/versions/zstd/CPP/7zip/Bundles/Nsis7z/afxres.h new file mode 100644 index 0000000..c2fadd4 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/afxres.h @@ -0,0 +1 @@ +#include diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/api.h b/versions/zstd/CPP/7zip/Bundles/Nsis7z/api.h new file mode 100644 index 0000000..85d41c4 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/api.h @@ -0,0 +1,83 @@ +/* + * apih + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2013 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _NSIS_EXEHEAD_API_H_ +#define _NSIS_EXEHEAD_API_H_ + +// Starting with NSIS 2.42, you can check the version of the plugin API in exec_flags->plugin_api_version +// The format is 0xXXXXYYYY where X is the major version and Y is the minor version (MAKELONG(y,x)) +// When doing version checks, always remember to use >=, ex: if (pX->exec_flags->plugin_api_version >= NSISPIAPIVER_1_0) {} + +#define NSISPIAPIVER_1_0 0x00010000 +#define NSISPIAPIVER_CURR NSISPIAPIVER_1_0 + +// NSIS Plug-In Callback Messages +enum NSPIM +{ + NSPIM_UNLOAD, // This is the last message a plugin gets, do final cleanup + NSPIM_GUIUNLOAD, // Called after .onGUIEnd +}; + +// Prototype for callbacks registered with extra_parameters->RegisterPluginCallback() +// Return NULL for unknown messages +// Should always be __cdecl for future expansion possibilities +typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM); + +// extra_parameters data structures containing other interesting stuff +// but the stack, variables and HWND passed on to plug-ins. +typedef struct +{ + int autoclose; + int all_user_var; + int exec_error; + int abort; + int exec_reboot; // NSIS_SUPPORT_REBOOT + int reboot_called; // NSIS_SUPPORT_REBOOT + int XXX_cur_insttype; // depreacted + int plugin_api_version; // see NSISPIAPIVER_CURR + // used to be XXX_insttype_changed + int silent; // NSIS_CONFIG_SILENT_SUPPORT + int instdir_error; + int rtl; + int errlvl; + int alter_reg_view; + int status_update; +} exec_flags_t; + +#ifndef NSISCALL +# define NSISCALL __stdcall +#endif + +typedef struct { + exec_flags_t *exec_flags; + int (NSISCALL *ExecuteCodeSegment)(int, HWND); + void (NSISCALL *validate_filename)(TCHAR *); + int (NSISCALL *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and < 0 on errors +} extra_parameters; + +// Definitions for page showing plug-ins +// See Ui.c to understand better how they're used + +// sent to the outer window to tell it to go to the next inner window +#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8) + +// custom pages should send this message to let NSIS know they're ready +#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd) + +// sent as wParam with WM_NOTIFY_OUTER_NEXT when user cancels - heed its warning +#define NOTIFY_BYE_BYE 'x' + +#endif /* _PLUGIN_H_ */ diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/nsis7z.cpp b/versions/zstd/CPP/7zip/Bundles/Nsis7z/nsis7z.cpp new file mode 100644 index 0000000..8f8daaa --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/nsis7z.cpp @@ -0,0 +1,190 @@ +#include "StdAfx.h" + +#include "../../UI/NSIS/ExtractCallbackConsole.h" +#include "Common/StringConvert.h" + +#pragma warning(disable: 4100) + +#define IDC_PROGRESS 1004 +#define IDC_INTROTEXT 1006 + +#define EXTRACTFUNC(funcname) extern "C" { \ +void __declspec(dllexport) __cdecl funcname(HWND hwndParent, int string_size, \ + TCHAR *variables, stack_t **stacktop, \ + extra_parameters *extra) \ +{ \ + EXDLL_INIT();\ + g_lastVal = -1; \ + g_hwndParent=hwndParent; \ + HWND hwndDlg = FindWindowEx(g_hwndParent, NULL, TEXT("#32770"), NULL); \ + g_hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS); \ + g_hwndText = GetDlgItem(hwndDlg, IDC_INTROTEXT); \ + TCHAR sArchive[1024], *outDir = getuservariable(INST_OUTDIR); \ + popstring(sArchive); \ + g_pluginExtra = extra; \ + +#define EXTRACTFUNCEND } } + +HINSTANCE g_hInstance2; +HWND g_hwndParent; +HWND g_hwndProgress; +HWND g_hwndText; +extra_parameters *g_pluginExtra; + +void DoInitialize(); +int DoExtract(LPTSTR archive, LPTSTR dir, bool overwrite, bool expath, ExtractProgressHandler epc, const UStringVector& skipPatterns); +int DoExtractWithFile(LPTSTR archive, LPTSTR dir, bool overwrite, bool expath, ExtractProgressWithFileHandler epc, const UStringVector& skipPatterns); + +int g_progressCallback = -1; +int g_lastVal = -1; +TCHAR* g_sDetails; + +static void PopSkipPatterns(UStringVector& skipPatterns) +{ + TCHAR *buf = new TCHAR[g_stringsize]; + while (popstring(buf) == 0 && lstrlen(buf) > 0) + { +#ifdef UNICODE + skipPatterns.Add(UString(buf)); +#else + skipPatterns.Add(MultiByteToUnicodeString(AString(buf))); +#endif + } + delete[] buf; +} + +int GetPercentComplete(UInt64 completedSize, UInt64 totalSize) +{ + if (totalSize == 0) return 0; + const int nsisProgressMax = 30000; + int val = (int)((completedSize*nsisProgressMax)/totalSize); + if (val < 0) return 0; + if (val > nsisProgressMax) return nsisProgressMax; + return val; +} + +void SimpleProgressHandler(UInt64 completedSize, UInt64 totalSize) +{ + int val = GetPercentComplete(completedSize, totalSize); + if (g_lastVal != val) + SendMessage(g_hwndProgress, PBM_SETPOS, g_lastVal = val, 0); +} + +void CallbackProgressHandler(UInt64 completedSize, UInt64 totalSize) +{ + int val = 0; + + if (totalSize > 0) + { + val = GetPercentComplete(completedSize, totalSize); + + static TCHAR buf[32]; + wsprintf(buf, TEXT("%lu"), totalSize); + pushstring(buf); + wsprintf(buf, TEXT("%lu"), completedSize); + pushstring(buf); + g_pluginExtra->ExecuteCodeSegment(g_progressCallback-1, 0); + } + + if (g_lastVal != val) + SendMessage(g_hwndProgress, PBM_SETPOS, g_lastVal = val, 0); +} + +void CallbackFileProgressHandler(UInt64 completedSize, UInt64 totalSize, const wchar_t *fileName) +{ + int val = 0; + + if (totalSize > 0) + val = GetPercentComplete(completedSize, totalSize); + + // Notify NSIS only when a new file starts (filename changes) + if (fileName && fileName[0]) + { + static TCHAR fileNameBuf[MAX_PATH]; + static TCHAR prevFileNameBuf[MAX_PATH]; + static TCHAR buf[32]; + + lstrcpyn(fileNameBuf, (const TCHAR*)fileName, MAX_PATH); + if (lstrcmp(fileNameBuf, prevFileNameBuf) != 0) + { + lstrcpy(prevFileNameBuf, fileNameBuf); + pushstring(fileNameBuf); + wsprintf(buf, TEXT("%lu"), (DWORD)totalSize); + pushstring(buf); + wsprintf(buf, TEXT("%lu"), (DWORD)completedSize); + pushstring(buf); + g_pluginExtra->ExecuteCodeSegment(g_progressCallback-1, 0); + } + } + + if (g_lastVal != val) + SendMessage(g_hwndProgress, PBM_SETPOS, g_lastVal = val, 0); +} + +void DetailsProgressHandler(UInt64 completedSize, UInt64 totalSize) +{ + int val = 0; + + if (totalSize > 0) + { + val = GetPercentComplete(completedSize, totalSize); + + TCHAR* buf = new TCHAR[g_stringsize]; + TCHAR* buf2 = new TCHAR[g_stringsize]; + wsprintf(buf, TEXT("%d%% (%d / %d MB)"), (int)(val?val/300:0), (int)(completedSize?completedSize/(1024*1024):0), (int)(totalSize/(1024*1024))); + wsprintf(buf2, g_sDetails, buf); + SetWindowText(g_hwndText, buf2); + delete[] buf; + delete[] buf2; + } + + if (g_lastVal != val) + SendMessage(g_hwndProgress, PBM_SETPOS, g_lastVal = val, 0); +} + +EXTRACTFUNC(Extract) +{ + UStringVector skipPatterns; + PopSkipPatterns(skipPatterns); + DoExtract(sArchive, outDir, true, true, (ExtractProgressHandler)SimpleProgressHandler, skipPatterns); +} +EXTRACTFUNCEND + +EXTRACTFUNC(ExtractWithDetails) +{ + g_sDetails = new TCHAR[string_size]; + popstring(g_sDetails); + UStringVector skipPatterns; + PopSkipPatterns(skipPatterns); + DoExtract(sArchive, outDir, true, true, (ExtractProgressHandler)DetailsProgressHandler, skipPatterns); + delete[] g_sDetails; +} +EXTRACTFUNCEND + +EXTRACTFUNC(ExtractWithCallback) +{ + g_progressCallback = popint(); + UStringVector skipPatterns; + PopSkipPatterns(skipPatterns); + DoExtract(sArchive, outDir, true, true, (ExtractProgressHandler)CallbackProgressHandler, skipPatterns); +} +EXTRACTFUNCEND + +EXTRACTFUNC(ExtractWithFileCallback) +{ + g_progressCallback = popint(); + UStringVector skipPatterns; + PopSkipPatterns(skipPatterns); + DoExtractWithFile(sArchive, outDir, true, true, CallbackFileProgressHandler, skipPatterns); +} +EXTRACTFUNCEND + +extern "C" BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + g_hInstance2=(HINSTANCE)hInst; + if (ul_reason_for_call == DLL_PROCESS_ATTACH) + { + DoInitialize(); + } + return TRUE; +} diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/nsis_tchar.h b/versions/zstd/CPP/7zip/Bundles/Nsis7z/nsis_tchar.h new file mode 100644 index 0000000..210bab1 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/nsis_tchar.h @@ -0,0 +1,229 @@ +/* + * nsis_tchar.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2013 Nullsoft and Contributors + * + * This software is provided 'as-is', without any express or implied + * warranty. + * + * For Unicode support by Jim Park -- 08/30/2007 + */ + +// Jim Park: Only those we use are listed here. + +#pragma once + +#ifdef _UNICODE + +#ifndef _T +#define __T(x) L ## x +#define _T(x) __T(x) +#define _TEXT(x) __T(x) +#endif + +#ifndef _TCHAR_DEFINED +#define _TCHAR_DEFINED +#if !defined(_NATIVE_WCHAR_T_DEFINED) && !defined(_WCHAR_T_DEFINED) +typedef unsigned short TCHAR; +#else +typedef wchar_t TCHAR; +#endif +#endif + + +// program +#define _tenviron _wenviron +#define __targv __wargv + +// printfs +#define _ftprintf fwprintf +#define _sntprintf _snwprintf +#if (defined(_MSC_VER) && (_MSC_VER<=1310)) || defined(__MINGW32__) +# define _stprintf swprintf +#else +# define _stprintf _swprintf +#endif +#define _tprintf wprintf +#define _vftprintf vfwprintf +#define _vsntprintf _vsnwprintf +#if defined(_MSC_VER) && (_MSC_VER<=1310) +# define _vstprintf vswprintf +#else +# define _vstprintf _vswprintf +#endif + +// scanfs +#define _tscanf wscanf +#define _stscanf swscanf + +// string manipulations +#define _tcscat wcscat +#define _tcschr wcschr +#define _tcsclen wcslen +#define _tcscpy wcscpy +#define _tcsdup _wcsdup +#define _tcslen wcslen +#define _tcsnccpy wcsncpy +#define _tcsncpy wcsncpy +#define _tcsrchr wcsrchr +#define _tcsstr wcsstr +#define _tcstok wcstok + +// string comparisons +#define _tcscmp wcscmp +#define _tcsicmp _wcsicmp +#define _tcsncicmp _wcsnicmp +#define _tcsncmp wcsncmp +#define _tcsnicmp _wcsnicmp + +// upper / lower +#define _tcslwr _wcslwr +#define _tcsupr _wcsupr +#define _totlower towlower +#define _totupper towupper + +// conversions to numbers +#define _tcstoi64 _wcstoi64 +#define _tcstol wcstol +#define _tcstoul wcstoul +#define _tstof _wtof +#define _tstoi _wtoi +#define _tstoi64 _wtoi64 +#define _ttoi _wtoi +#define _ttoi64 _wtoi64 +#define _ttol _wtol + +// conversion from numbers to strings +#define _itot _itow +#define _ltot _ltow +#define _i64tot _i64tow +#define _ui64tot _ui64tow + +// file manipulations +#define _tfopen _wfopen +#define _topen _wopen +#define _tremove _wremove +#define _tunlink _wunlink + +// reading and writing to i/o +#define _fgettc fgetwc +#define _fgetts fgetws +#define _fputts fputws +#define _gettchar getwchar + +// directory +#define _tchdir _wchdir + +// environment +#define _tgetenv _wgetenv +#define _tsystem _wsystem + +// time +#define _tcsftime wcsftime + +#else // ANSI + +#ifndef _T +#define _T(x) x +#define _TEXT(x) x +#endif + +#ifndef _TCHAR_DEFINED +#define _TCHAR_DEFINED +typedef char TCHAR; +#endif + +// program +#define _tenviron environ +#define __targv __argv + +// printfs +#define _ftprintf fprintf +#define _sntprintf _snprintf +#define _stprintf sprintf +#define _tprintf printf +#define _vftprintf vfprintf +#define _vsntprintf _vsnprintf +#define _vstprintf vsprintf + +// scanfs +#define _tscanf scanf +#define _stscanf sscanf + +// string manipulations +#define _tcscat strcat +#define _tcschr strchr +#define _tcsclen strlen +#define _tcscnlen strnlen +#define _tcscpy strcpy +#define _tcsdup _strdup +#define _tcslen strlen +#define _tcsnccpy strncpy +#define _tcsrchr strrchr +#define _tcsstr strstr +#define _tcstok strtok + +// string comparisons +#define _tcscmp strcmp +#define _tcsicmp _stricmp +#define _tcsncmp strncmp +#define _tcsncicmp _strnicmp +#define _tcsnicmp _strnicmp + +// upper / lower +#define _tcslwr _strlwr +#define _tcsupr _strupr + +#define _totupper toupper +#define _totlower tolower + +// conversions to numbers +#define _tcstol strtol +#define _tcstoul strtoul +#define _tstof atof +#define _tstoi atoi +#define _tstoi64 _atoi64 +#define _tstoi64 _atoi64 +#define _ttoi atoi +#define _ttoi64 _atoi64 +#define _ttol atol + +// conversion from numbers to strings +#define _i64tot _i64toa +#define _itot _itoa +#define _ltot _ltoa +#define _ui64tot _ui64toa + +// file manipulations +#define _tfopen fopen +#define _topen _open +#define _tremove remove +#define _tunlink _unlink + +// reading and writing to i/o +#define _fgettc fgetc +#define _fgetts fgets +#define _fputts fputs +#define _gettchar getchar + +// directory +#define _tchdir _chdir + +// environment +#define _tgetenv getenv +#define _tsystem system + +// time +#define _tcsftime strftime + +#endif + +// is functions (the same in Unicode / ANSI) +#define _istgraph isgraph +#define _istascii __isascii + +#define __TFILE__ _T(__FILE__) +#define __TDATE__ _T(__DATE__) +#define __TTIME__ _T(__TIME__) diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/pluginapi.cpp b/versions/zstd/CPP/7zip/Bundles/Nsis7z/pluginapi.cpp new file mode 100644 index 0000000..69406a8 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/pluginapi.cpp @@ -0,0 +1,292 @@ +#include "StdAfx.h" + +#ifdef _countof +#define COUNTOF _countof +#else +#define COUNTOF(a) (sizeof(a)/sizeof(a[0])) +#endif + +unsigned int g_stringsize; +stack_t **g_stacktop; +TCHAR *g_variables; + +// utility functions (not required but often useful) + +int NSISCALL popstring(TCHAR *str) +{ + stack_t *th; + if (!g_stacktop || !*g_stacktop) return 1; + th=(*g_stacktop); + if (str) lstrcpy(str,th->text); + *g_stacktop = th->next; + GlobalFree((HGLOBAL)th); + return 0; +} + +int NSISCALL popstringn(TCHAR *str, int maxlen) +{ + stack_t *th; + if (!g_stacktop || !*g_stacktop) return 1; + th=(*g_stacktop); + if (str) lstrcpyn(str,th->text,maxlen?maxlen:g_stringsize); + *g_stacktop = th->next; + GlobalFree((HGLOBAL)th); + return 0; +} + +void NSISCALL pushstring(const TCHAR *str) +{ + stack_t *th; + if (!g_stacktop) return; + th=(stack_t*)GlobalAlloc(GPTR,(sizeof(stack_t)+(g_stringsize)*sizeof(TCHAR))); + lstrcpyn(th->text,str,g_stringsize); + th->next=*g_stacktop; + *g_stacktop=th; +} + +TCHAR* NSISCALL getuservariable(const int varnum) +{ + if (varnum < 0 || varnum >= __INST_LAST) return NULL; + return g_variables+varnum*g_stringsize; +} + +void NSISCALL setuservariable(const int varnum, const TCHAR *var) +{ + if (var != NULL && varnum >= 0 && varnum < __INST_LAST) + lstrcpy(g_variables + varnum*g_stringsize, var); +} + +#ifdef _UNICODE +int NSISCALL PopStringA(char* ansiStr) +{ + wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, g_stringsize*sizeof(wchar_t)); + int rval = popstring(wideStr); + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); + GlobalFree((HGLOBAL)wideStr); + return rval; +} + +int NSISCALL PopStringNA(char* ansiStr, int maxlen) +{ + int realLen = maxlen ? maxlen : g_stringsize; + wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, realLen*sizeof(wchar_t)); + int rval = popstringn(wideStr, realLen); + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, realLen, NULL, NULL); + GlobalFree((HGLOBAL)wideStr); + return rval; +} + +void NSISCALL PushStringA(const char* ansiStr) +{ + wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, g_stringsize*sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); + pushstring(wideStr); + GlobalFree((HGLOBAL)wideStr); + return; +} + +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr) +{ + lstrcpyW(wideStr, getuservariable(varnum)); +} + +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr) +{ + wchar_t* wideStr = getuservariable(varnum); + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); +} + +void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr) +{ + if (ansiStr != NULL && varnum >= 0 && varnum < __INST_LAST) + { + wchar_t* wideStr = g_variables + varnum * g_stringsize; + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); + } +} + +#else +// ANSI defs +int NSISCALL PopStringW(wchar_t* wideStr) +{ + char* ansiStr = (char*) GlobalAlloc(GPTR, g_stringsize); + int rval = popstring(ansiStr); + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); + GlobalFree((HGLOBAL)ansiStr); + return rval; +} + +int NSISCALL PopStringNW(wchar_t* wideStr, int maxlen) +{ + int realLen = maxlen ? maxlen : g_stringsize; + char* ansiStr = (char*) GlobalAlloc(GPTR, realLen); + int rval = popstringn(ansiStr, realLen); + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, realLen); + GlobalFree((HGLOBAL)ansiStr); + return rval; +} + +void NSISCALL PushStringW(wchar_t* wideStr) +{ + char* ansiStr = (char*) GlobalAlloc(GPTR, g_stringsize); + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); + pushstring(ansiStr); + GlobalFree((HGLOBAL)ansiStr); +} + +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr) +{ + char* ansiStr = getuservariable(varnum); + MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); +} + +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr) +{ + lstrcpyA(ansiStr, getuservariable(varnum)); +} + +void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr) +{ + if (wideStr != NULL && varnum >= 0 && varnum < __INST_LAST) + { + char* ansiStr = g_variables + varnum * g_stringsize; + WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); + } +} +#endif + +// playing with integers + +INT_PTR NSISCALL nsishelper_str_to_ptr(const TCHAR *s) +{ + INT_PTR v=0; + if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X'))) + { + s++; + for (;;) + { + int c=*(++s); + if (c >= _T('0') && c <= _T('9')) c-=_T('0'); + else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10; + else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10; + else break; + v<<=4; + v+=c; + } + } + else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0')) + { + for (;;) + { + int c=*(++s); + if (c >= _T('0') && c <= _T('7')) c-=_T('0'); + else break; + v<<=3; + v+=c; + } + } + else + { + int sign=0; + if (*s == _T('-')) sign++; else s--; + for (;;) + { + int c=*(++s) - _T('0'); + if (c < 0 || c > 9) break; + v*=10; + v+=c; + } + if (sign) v = -v; + } + + return v; +} + +unsigned int NSISCALL myatou(const TCHAR *s) +{ + unsigned int v=0; + + for (;;) + { + unsigned int c=*s++; + if (c >= _T('0') && c <= _T('9')) c-=_T('0'); + else break; + v*=10; + v+=c; + } + return v; +} + +int NSISCALL myatoi_or(const TCHAR *s) +{ + int v=0; + if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X'))) + { + s++; + for (;;) + { + int c=*(++s); + if (c >= _T('0') && c <= _T('9')) c-=_T('0'); + else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10; + else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10; + else break; + v<<=4; + v+=c; + } + } + else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0')) + { + for (;;) + { + int c=*(++s); + if (c >= _T('0') && c <= _T('7')) c-=_T('0'); + else break; + v<<=3; + v+=c; + } + } + else + { + int sign=0; + if (*s == _T('-')) sign++; else s--; + for (;;) + { + int c=*(++s) - _T('0'); + if (c < 0 || c > 9) break; + v*=10; + v+=c; + } + if (sign) v = -v; + } + + // Support for simple ORed expressions + if (*s == _T('|')) + { + v |= myatoi_or(s+1); + } + + return v; +} + +INT_PTR NSISCALL popintptr() +{ + TCHAR buf[128]; + if (popstringn(buf,COUNTOF(buf))) + return 0; + return nsishelper_str_to_ptr(buf); +} + +int NSISCALL popint_or() +{ + TCHAR buf[128]; + if (popstringn(buf,COUNTOF(buf))) + return 0; + return myatoi_or(buf); +} + +void NSISCALL pushintptr(INT_PTR value) +{ + TCHAR buffer[30]; + wsprintf(buffer, sizeof(void*) > 4 ? _T("%Id") : _T("%d"), value); + pushstring(buffer); +} diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/pluginapi.h b/versions/zstd/CPP/7zip/Bundles/Nsis7z/pluginapi.h new file mode 100644 index 0000000..f607b11 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/pluginapi.h @@ -0,0 +1,115 @@ +#ifndef ___NSIS_PLUGIN__H___ +#define ___NSIS_PLUGIN__H___ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "api.h" +#ifdef _UNICODE +#ifndef _T +#define __T(x) L ## x +#define _T(x) __T(x) +#define _TEXT(x) __T(x) +#endif +#else +#ifndef _T +#define _T(x) x +#define _TEXT(x) x +#endif +#endif + +#ifndef NSISCALL +# define NSISCALL __stdcall +#endif + +#define EXDLL_INIT() { \ + g_stringsize=string_size; \ + g_stacktop=stacktop; \ + g_variables=variables; } + +typedef struct _stack_t { + struct _stack_t *next; + TCHAR text[1]; // this should be the length of string_size +} stack_t; + +enum +{ +INST_0, // $0 +INST_1, // $1 +INST_2, // $2 +INST_3, // $3 +INST_4, // $4 +INST_5, // $5 +INST_6, // $6 +INST_7, // $7 +INST_8, // $8 +INST_9, // $9 +INST_R0, // $R0 +INST_R1, // $R1 +INST_R2, // $R2 +INST_R3, // $R3 +INST_R4, // $R4 +INST_R5, // $R5 +INST_R6, // $R6 +INST_R7, // $R7 +INST_R8, // $R8 +INST_R9, // $R9 +INST_CMDLINE, // $CMDLINE +INST_INSTDIR, // $INSTDIR +INST_OUTDIR, // $OUTDIR +INST_EXEDIR, // $EXEDIR +INST_LANG, // $LANGUAGE +__INST_LAST +}; + +extern unsigned int g_stringsize; +extern stack_t **g_stacktop; +extern TCHAR *g_variables; + +void NSISCALL pushstring(const TCHAR *str); +void NSISCALL pushintptr(INT_PTR value); +#define pushint(v) pushintptr((INT_PTR)(v)) +int NSISCALL popstring(TCHAR *str); // 0 on success, 1 on empty stack +int NSISCALL popstringn(TCHAR *str, int maxlen); // with length limit, pass 0 for g_stringsize +INT_PTR NSISCALL popintptr(); +#define popint() ( (int) popintptr() ) +int NSISCALL popint_or(); // with support for or'ing (2|4|8) +INT_PTR NSISCALL nsishelper_str_to_ptr(const TCHAR *s); +#define myatoi(s) ( (int) nsishelper_str_to_ptr(s) ) // converts a string to an integer +unsigned int NSISCALL myatou(const TCHAR *s); // converts a string to an unsigned integer, decimal only +int NSISCALL myatoi_or(const TCHAR *s); // with support for or'ing (2|4|8) +TCHAR* NSISCALL getuservariable(const int varnum); +void NSISCALL setuservariable(const int varnum, const TCHAR *var); + +#ifdef _UNICODE +#define PopStringW(x) popstring(x) +#define PushStringW(x) pushstring(x) +#define SetUserVariableW(x,y) setuservariable(x,y) + +int NSISCALL PopStringA(char* ansiStr); +void NSISCALL PushStringA(const char* ansiStr); +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr); +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr); +void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr); + +#else +// ANSI defs + +#define PopStringA(x) popstring(x) +#define PushStringA(x) pushstring(x) +#define SetUserVariableA(x,y) setuservariable(x,y) + +int NSISCALL PopStringW(wchar_t* wideStr); +void NSISCALL PushStringW(wchar_t* wideStr); +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr); +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr); +void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif//!___NSIS_PLUGIN__H___ diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/resource.h b/versions/zstd/CPP/7zip/Bundles/Nsis7z/resource.h new file mode 100644 index 0000000..08340b3 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resource.rc +// +#define MY_VER_BUILD 0 +#define DBG_FL 0 +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 20 + +// 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 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/versions/zstd/CPP/7zip/Bundles/Nsis7z/resource.rc b/versions/zstd/CPP/7zip/Bundles/Nsis7z/resource.rc new file mode 100644 index 0000000..18da943 --- /dev/null +++ b/versions/zstd/CPP/7zip/Bundles/Nsis7z/resource.rc @@ -0,0 +1,99 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 25,01,0,0 + PRODUCTVERSION 25,01,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Igor Pavlov" + VALUE "FileDescription", "7-Zip NSIS Plug-in" + VALUE "FileVersion", "25.01.0.0" + VALUE "InternalName", "nsis7z" + VALUE "LegalCopyright", "Copyright (c) 1999-2025 Igor Pavlov, Nik Medved, Marek Mizanin, Stuart Welch" + VALUE "OriginalFilename", "nsis7z.dll" + VALUE "ProductName", "7-Zip" + VALUE "ProductVersion", "25.01.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/versions/zstd/CPP/7zip/UI/NSIS/ExtractCallbackConsole.cpp b/versions/zstd/CPP/7zip/UI/NSIS/ExtractCallbackConsole.cpp new file mode 100644 index 0000000..f0cb06a --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/ExtractCallbackConsole.cpp @@ -0,0 +1,163 @@ +// ExtractCallbackConsole.h + +#include "StdAfx.h" + +#include "Common/Common.h" +#include "ExtractCallbackConsole.h" +#include "UserInputUtils2.h" +#include "NSISBreak.h" + +#include "Common/Wildcard.h" + +#include "Windows/FileDir.h" +#include "Windows/FileFind.h" +#include "Windows/TimeUtils.h" +#include "Windows/Defs.h" +#include "Windows/PropVariant.h" +#include "Windows/ErrorMsg.h" +#include "Windows/PropVariantConv.h" + +#include "7zip/Common/FilePathAutoRename.h" + +#include "7zip/UI/Common/ExtractingFilePath.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +extern HWND g_hwndProgress; + +void CExtractCallbackConsole::UpdateProgress() +{ + // Prima controlla se c'è il callback con filename (nuova funzione) + if (ProgressWithFileHandler != NULL) + { + if (completedSize != -1 || totalSize > 0) + ProgressWithFileHandler(completedSize, totalSize, CurrentFileName.Ptr()); + else + ProgressWithFileHandler(0, 0, CurrentFileName.Ptr()); + } + // Altrimenti usa il callback originale (per compatibilità) + else if (ProgressHandler != NULL) + { + if (completedSize != -1 || totalSize > 0) + ProgressHandler(completedSize, totalSize); + else + ProgressHandler(0, 0); + } +} + +STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 val) +{ + totalSize = val; + UpdateProgress(); + if (NNSISBreak::TestBreakSignal()) + return E_ABORT; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *val) +{ + completedSize = *val; + UpdateProgress(); + if (NNSISBreak::TestBreakSignal()) + return E_ABORT; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::AskOverwrite( + const wchar_t *existName, const FILETIME *, const UInt64 *, + const wchar_t *newName, const FILETIME *, const UInt64 *, + Int32 *answer) +{ + *answer = NOverwriteAnswer::kYesToAll; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position) +{ + // Memorizza il nome del file corrente per passarlo al callback + CurrentFileName = name; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) +{ + NumFileErrorsInCurrentArchive++; + NumFileErrors++; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted) +{ + switch(opRes) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + NumFileErrorsInCurrentArchive++; + NumFileErrors++; + + } + } + return S_OK; +} + +#ifndef Z7_NO_CRYPTO + +HRESULT CExtractCallbackConsole::SetPassword(const UString &password) +{ + PasswordIsDefined = true; + Password = password; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) +{ + if (!PasswordIsDefined) + { + Password = GetPassword(OutStream); + PasswordIsDefined = true; + } + return StringToBstr(Password, password); +} + +#endif + +HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode) +{ + NumArchives++; + NumFileErrorsInCurrentArchive = 0; + return S_OK; +} + +HRESULT CExtractCallbackConsole::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) +{ + if (result != S_OK) + { + NumArchiveErrors++; + } + return S_OK; +} + +HRESULT CExtractCallbackConsole::ThereAreNoFiles() +{ + return S_OK; +} + +HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) +{ + if (result == S_OK) + { + if (NumFileErrorsInCurrentArchive != 0) + { + NumArchiveErrors++; + } + return result; + } + NumArchiveErrors++; + if (result == E_ABORT || result == ERROR_DISK_FULL) + return result; + return S_OK; +} diff --git a/versions/zstd/CPP/7zip/UI/NSIS/ExtractCallbackConsole.h b/versions/zstd/CPP/7zip/UI/NSIS/ExtractCallbackConsole.h new file mode 100644 index 0000000..cb4c236 --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/ExtractCallbackConsole.h @@ -0,0 +1,98 @@ +// ExtractCallbackConsole.h +// NSIS version adapted for 7-Zip 25.01 API + +#ifndef __EXTRACTCALLBACKCONSOLE_H +#define __EXTRACTCALLBACKCONSOLE_H + +#include "Common/MyCom.h" +#include "Common/MyString.h" +#include "Common/StdOutStream.h" +#include "7zip/Common/FileStreams.h" +#include "7zip/IPassword.h" +#include "7zip/Archive/IArchive.h" +#include "7zip/UI/Common/ArchiveExtractCallback.h" +#include "7zip/UI/Console/OpenCallbackConsole.h" + +typedef void (*ExtractProgressHandler)(UInt64 completedSize, UInt64 totalSize); +typedef void (*ExtractProgressWithFileHandler)(UInt64 completedSize, UInt64 totalSize, const wchar_t *fileName); + +class CExtractCallbackConsole Z7_final: + public IFolderArchiveExtractCallback, + public IExtractCallbackUI, +#ifndef Z7_NO_CRYPTO + public ICryptoGetTextPassword, +#endif + public COpenCallbackConsole, + public CMyUnknownImp +{ + Z7_COM_QI_BEGIN2(IFolderArchiveExtractCallback) +#ifndef Z7_NO_CRYPTO + Z7_COM_QI_ENTRY(ICryptoGetTextPassword) +#endif + Z7_COM_QI_END + Z7_COM_ADDREF_RELEASE + + // IProgress + Z7_IFACE_COM7_IMP(IProgress) + + // IFolderArchiveExtractCallback + Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback) + + // IExtractCallbackUI (non-COM interface) + Z7_IFACE_IMP(IExtractCallbackUI) + +#ifndef Z7_NO_CRYPTO + Z7_IFACE_COM7_IMP(ICryptoGetTextPassword) +#endif + +public: +#ifndef Z7_NO_CRYPTO + bool PasswordIsDefined; + UString Password; +#endif + + UInt64 NumArchives; + UInt64 NumArchiveErrors; + UInt64 NumFileErrors; + UInt64 NumFileErrorsInCurrentArchive; + + CStdOutStream *OutStream; + + UInt64 totalSize, completedSize, lastVal; + + ExtractProgressHandler ProgressHandler; + ExtractProgressWithFileHandler ProgressWithFileHandler; + UString CurrentFileName; + + CExtractCallbackConsole(): + PasswordIsDefined(false), + NumArchives(0), + NumArchiveErrors(0), + NumFileErrors(0), + NumFileErrorsInCurrentArchive(0), + OutStream(NULL), + totalSize((UInt64)(Int64)-1), + completedSize(0), + lastVal(0), + ProgressHandler(NULL), + ProgressWithFileHandler(NULL) + {} + + void Init() + { + NumArchives = 0; + NumArchiveErrors = 0; + NumFileErrors = 0; + NumFileErrorsInCurrentArchive = 0; + + totalSize = (UInt64)(Int64)-1; + completedSize = 0; + lastVal = 0; + ProgressHandler = NULL; + ProgressWithFileHandler = NULL; + } + + void UpdateProgress(); +}; + +#endif diff --git a/versions/zstd/CPP/7zip/UI/NSIS/Main.cpp b/versions/zstd/CPP/7zip/UI/NSIS/Main.cpp new file mode 100644 index 0000000..bcc392b --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/Main.cpp @@ -0,0 +1,313 @@ +// Main.cpp + +#include "StdAfx.h" + +#include "Common/Common.h" +#include "Common/MyInitGuid.h" + +#include "Common/CommandLineParser.h" +#include "Common/MyException.h" +#include "Common/IntToString.h" +#include "Common/StdOutStream.h" +#include "Common/StringConvert.h" +#include "Common/StringToInt.h" + +#include "Windows/FileDir.h" +#include "Windows/FileName.h" +#include "Windows/Defs.h" +#include "Windows/ErrorMsg.h" +#ifdef _WIN32 +#include "Windows/MemoryLock.h" +#endif + +#include "7zip/IPassword.h" +#include "7zip/ICoder.h" +#include "7zip/UI/Common/UpdateAction.h" +#include "7zip/UI/Common/Update.h" +#include "7zip/UI/Common/Extract.h" +#include "7zip/UI/Common/ArchiveCommandLine.h" +#include "7zip/UI/Common/ExitCode.h" +#ifdef EXTERNAL_CODECS +#include "7zip/UI/Common/LoadCodecs.h" +#endif + +//#include "../../Compress/LZMA_Alone/LzmaBenchCon.h" + +#include "7zip/UI/Console/OpenCallbackConsole.h" +#include "ExtractCallbackConsole.h" + +#include "7zip/MyVersion.h" + +#if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) +extern "C" +{ +#include "C/Alloc.h" +} +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NCommandLineParser; + +HINSTANCE g_hInstance = 0; + +// --------------------------- +// exception messages + +#ifndef _WIN32 +static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) +{ + parts.Clear(); + for(int i = 0; i < numArguments; i++) + { + UString s = MultiByteToUnicodeString(arguments[i]); + parts.Add(s); + } +} +#endif + +#ifdef EXTERNAL_CODECS +static void PrintString(CStdOutStream &stdStream, const AString &s, int size) +{ + int len = s.Length(); + stdStream << s; + for (int i = len; i < size; i++) + stdStream << ' '; +} +#endif + +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +#ifdef _WIN32 +void SwitchFileAPIEncoding(BOOL ansi) +{ + if (ansi) + { + SetFileApisToOEM(); + } + else + { + SetFileApisToANSI(); + } +} +#endif + +int DoExtractArchive(UString archive, UString targetDir, bool overwrite, bool extractPaths, ExtractProgressHandler epc, const UStringVector& skipPatterns) +{ + CCodecs *codecs = new CCodecs; + CMyComPtr compressCodecsInfo = codecs; + HRESULT result = codecs->Load(); + + if (result != S_OK) + throw CSystemException(result); + + if (codecs->Formats.Size() == 0) throw -1; + + CIntVector formatIndices; + + if (!codecs->FindFormatForArchiveType(L"7z", formatIndices)) + { + throw -1; + } + + BOOL bApisAreAnsi = AreFileApisANSI(); + +#ifdef _WIN32 + if (bApisAreAnsi) + SwitchFileAPIEncoding(bApisAreAnsi); +#endif + + CExtractCallbackConsole *ecs = new CExtractCallbackConsole(); + CMyComPtr extractCallback = ecs; + ecs->Init(); + ecs->ProgressHandler = epc; // Imposta DOPO Init() + + COpenCallbackConsole openCallback; + + CExtractOptions eo; + eo.StdOutMode = false; + eo.PathMode = extractPaths?NExtract::NPathMode::kCurPaths:NExtract::NPathMode::kNoPaths; + eo.TestMode = false; + eo.OverwriteMode = overwrite?NExtract::NOverwriteMode::kOverwrite:NExtract::NOverwriteMode::kSkip; + eo.OutputDir = targetDir; + eo.YesToAll = true; +#ifdef COMPRESS_MT + CObjectVector prp; + eo.Properties = prp; +#endif + UString errorMessage; + CDecompressStat stat; + NWildcard::CCensor wildcardCensor; + NWildcard::CCensorPathProps props; + props.Recursive = true; + props.WildcardMatching = true; + wildcardCensor.AddItem(NWildcard::ECensorPathMode::k_FullPath, true, L"*", props); + for (unsigned i = 0; i < skipPatterns.Size(); i++) + { + const UString &p = skipPatterns[i]; + if (p.IsEmpty()) continue; + // Keep only single-name patterns: multi-segment ones land in a separate Pair + // and would be silently ignored by Pairs.Front().Head below. + if (p.Find(L'\\') >= 0 || p.Find(L'/') >= 0) continue; + wildcardCensor.AddItem(NWildcard::ECensorPathMode::k_FullPath, false, p, props); + } + UStringVector ArchivePathsSorted; + UStringVector ArchivePathsFullSorted; + ArchivePathsSorted.Add(archive); + UString fullPath; + NFile::NDir::MyGetFullPathName(archive, fullPath); + ArchivePathsFullSorted.Add(fullPath); + + UStringVector v1, v2; + v1.Add(fs2us(archive)); + v2.Add(fs2us(archive)); + const NWildcard::CCensorNode &wildcardCensorHead = + wildcardCensor.Pairs.Front().Head; + + result = Extract( + codecs, CObjectVector(), CIntVector(), + v1, v2, + wildcardCensorHead, + eo, ecs, ecs, ecs, +#ifndef Z7_SFX + NULL, // hash +#endif + errorMessage, stat); + +#ifdef _WIN32 + if (bApisAreAnsi) + SwitchFileAPIEncoding(!bApisAreAnsi); +#endif + + + if (!errorMessage.IsEmpty()) + { + if (result == S_OK) + result = E_FAIL; + } + + if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) + { + if (result != S_OK) + throw CSystemException(result); + + return NExitCode::kFatalError; + } + + if (result != S_OK) + throw CSystemException(result); + + return 0; +} + +int DoExtractArchiveWithFile(UString archive, UString targetDir, bool overwrite, bool extractPaths, ExtractProgressWithFileHandler epc, const UStringVector& skipPatterns) +{ + CCodecs *codecs = new CCodecs; + CMyComPtr compressCodecsInfo = codecs; + HRESULT result = codecs->Load(); + + if (result != S_OK) + throw CSystemException(result); + + if (codecs->Formats.Size() == 0) throw -1; + + CIntVector formatIndices; + + if (!codecs->FindFormatForArchiveType(L"7z", formatIndices)) + { + throw -1; + } + + BOOL bApisAreAnsi = AreFileApisANSI(); + +#ifdef _WIN32 + if (bApisAreAnsi) + SwitchFileAPIEncoding(bApisAreAnsi); +#endif + + CExtractCallbackConsole *ecs = new CExtractCallbackConsole(); + CMyComPtr extractCallback = ecs; + ecs->Init(); + ecs->ProgressWithFileHandler = epc; // Imposta DOPO Init() per evitare che venga resettato + + COpenCallbackConsole openCallback; + + CExtractOptions eo; + eo.StdOutMode = false; + eo.PathMode = extractPaths?NExtract::NPathMode::kCurPaths:NExtract::NPathMode::kNoPaths; + eo.TestMode = false; + eo.OverwriteMode = overwrite?NExtract::NOverwriteMode::kOverwrite:NExtract::NOverwriteMode::kSkip; + eo.OutputDir = targetDir; + eo.YesToAll = true; +#ifdef COMPRESS_MT + CObjectVector prp; + eo.Properties = prp; +#endif + UString errorMessage; + CDecompressStat stat; + NWildcard::CCensor wildcardCensor; + NWildcard::CCensorPathProps props; + props.Recursive = true; + props.WildcardMatching = true; + wildcardCensor.AddItem(NWildcard::ECensorPathMode::k_FullPath, true, L"*", props); + for (unsigned i = 0; i < skipPatterns.Size(); i++) + { + const UString &p = skipPatterns[i]; + if (p.IsEmpty()) continue; + // Keep only single-name patterns: multi-segment ones land in a separate Pair + // and would be silently ignored by Pairs.Front().Head below. + if (p.Find(L'\\') >= 0 || p.Find(L'/') >= 0) continue; + wildcardCensor.AddItem(NWildcard::ECensorPathMode::k_FullPath, false, p, props); + } + UStringVector ArchivePathsSorted; + UStringVector ArchivePathsFullSorted; + ArchivePathsSorted.Add(archive); + UString fullPath; + NFile::NDir::MyGetFullPathName(archive, fullPath); + ArchivePathsFullSorted.Add(fullPath); + + UStringVector v1, v2; + v1.Add(fs2us(archive)); + v2.Add(fs2us(archive)); + const NWildcard::CCensorNode &wildcardCensorHead = + wildcardCensor.Pairs.Front().Head; + + result = Extract( + codecs, CObjectVector(), CIntVector(), + v1, v2, + wildcardCensorHead, + eo, ecs, ecs, ecs, +#ifndef Z7_SFX + NULL, // hash +#endif + errorMessage, stat); + +#ifdef _WIN32 + if (bApisAreAnsi) + SwitchFileAPIEncoding(!bApisAreAnsi); +#endif + + + if (!errorMessage.IsEmpty()) + { + if (result == S_OK) + result = E_FAIL; + } + + if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) + { + if (result != S_OK) + throw CSystemException(result); + + return NExitCode::kFatalError; + } + + if (result != S_OK) + throw CSystemException(result); + + return 0; +} + diff --git a/versions/zstd/CPP/7zip/UI/NSIS/MainAr.cpp b/versions/zstd/CPP/7zip/UI/NSIS/MainAr.cpp new file mode 100644 index 0000000..425c767 --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/MainAr.cpp @@ -0,0 +1,109 @@ +// MainAr.cpp + +#include "StdAfx.h" + +// #include + +#include "Common/Common.h" + +#include "Windows/ErrorMsg.h" + +#include "Common/StdOutStream.h" +#include "Common/NewHandler.h" +#include "Common/MyException.h" +#include "Common/StringConvert.h" + +#include "7zip/UI/Common/ExitCode.h" +#include "7zip/UI/Common/ArchiveCommandLine.h" +#include "ExtractCallbackConsole.h" +#include "NSISBreak.h" + +using namespace NWindows; + +#ifdef _WIN32 + +#pragma warning(disable : 4996) + +#ifndef _UNICODE +bool g_IsNT = false; +#endif +#if !defined(_UNICODE) || !defined(_WIN64) +static inline bool IsItWindowsNT() +{ + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (!::GetVersionEx(&versionInfo)) + return false; + return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); +} +#endif +#endif + +void DoInitialize() +{ + #ifdef _WIN32 + + #ifdef _UNICODE + #ifndef _WIN64 + if (!IsItWindowsNT()) + { + //(*g_StdStream) << "This program requires Windows NT/2000/2003/2008/XP/Vista"; + // return NExitCode::kFatalError; + return; + } + #endif + #else + g_IsNT = IsItWindowsNT(); + #endif + + #endif +} + + +extern int DoExtractArchive(UString archive, UString targetDir, bool overwrite, bool extractPathes, ExtractProgressHandler epc, const UStringVector& skipPatterns); +extern int DoExtractArchiveWithFile(UString archive, UString targetDir, bool overwrite, bool extractPathes, ExtractProgressWithFileHandler epc, const UStringVector& skipPatterns); + +int DoExtract(LPTSTR archive, LPTSTR dir, bool overwrite, bool expath, ExtractProgressHandler epc, const UStringVector& skipPatterns) +{ + if (!archive || !dir) return -1; + int res = 0; + try + { +#ifdef UNICODE + UString uarchive(archive); + UString udir(dir); +#else + UString uarchive = MultiByteToUnicodeString(AString(archive)); + UString udir = MultiByteToUnicodeString(AString(dir)); +#endif + res = DoExtractArchive(uarchive, udir, overwrite, expath, epc, skipPatterns); + } + catch(...) + { + return -1; + } + return res; +} + +int DoExtractWithFile(LPTSTR archive, LPTSTR dir, bool overwrite, bool expath, ExtractProgressWithFileHandler epc, const UStringVector& skipPatterns) +{ + if (!archive || !dir) return -1; + int res = 0; + try + { +#ifdef UNICODE + UString uarchive(archive); + UString udir(dir); +#else + UString uarchive = MultiByteToUnicodeString(AString(archive)); + UString udir = MultiByteToUnicodeString(AString(dir)); +#endif + res = DoExtractArchiveWithFile(uarchive, udir, overwrite, expath, epc, skipPatterns); + } + catch(...) + { + return -1; + } + return res; +} + diff --git a/versions/zstd/CPP/7zip/UI/NSIS/NSISBreak.cpp b/versions/zstd/CPP/7zip/UI/NSIS/NSISBreak.cpp new file mode 100644 index 0000000..93ac0d5 --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/NSISBreak.cpp @@ -0,0 +1,31 @@ +// ConsoleClose.cpp + +#include "StdAfx.h" + +#include "NSISBreak.h" + +static int g_BreakCounter = 0; + +namespace NNSISBreak { + +void SendBreakSignal() +{ + g_BreakCounter++; +} + +bool TestBreakSignal() +{ + /* + if (g_BreakCounter > 0) + return true; + */ + return (g_BreakCounter > 0); +} + +void CheckCtrlBreak() +{ + if (TestBreakSignal()) + throw CCtrlBreakException(); +} + +} diff --git a/versions/zstd/CPP/7zip/UI/NSIS/NSISBreak.h b/versions/zstd/CPP/7zip/UI/NSIS/NSISBreak.h new file mode 100644 index 0000000..ca43f20 --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/NSISBreak.h @@ -0,0 +1,16 @@ +#ifndef __NSISBREAKUTILS_H +#define __NSISBREAKUTILS_H + +namespace NNSISBreak { + +bool TestBreakSignal(); +void SendBreakSignal(); + +class CCtrlBreakException +{}; + +void CheckCtrlBreak(); + +} + +#endif diff --git a/versions/zstd/CPP/7zip/UI/NSIS/StdAfx.h b/versions/zstd/CPP/7zip/UI/NSIS/StdAfx.h new file mode 100644 index 0000000..c8c5279 --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include +#include "7zip/Bundles/Nsis7z/pluginapi.h" + +#endif diff --git a/versions/zstd/CPP/7zip/UI/NSIS/UserInputUtils2.cpp b/versions/zstd/CPP/7zip/UI/NSIS/UserInputUtils2.cpp new file mode 100644 index 0000000..85d6d4f --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/UserInputUtils2.cpp @@ -0,0 +1,60 @@ +// UserInputUtils.cpp + +#include "StdAfx.h" + +#include "Common/StdInStream.h" +#include "Common/StringConvert.h" + +#include "UserInputUtils2.h" + +static const char kYes = 'Y'; +static const char kNo = 'N'; +static const char kYesAll = 'A'; +static const char kNoAll = 'S'; +static const char kAutoRename = 'U'; +static const char kQuit = 'Q'; + +static const char *kFirstQuestionMessage = "?\n"; +static const char *kHelpQuestionMessage = + "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename / (Q)uit? "; + +// return true if pressed Quite; +// in: anAll +// out: anAll, anYes; + +NUserAnswerMode::EEnum ScanUserYesNoAllQuit2(CStdOutStream *outStream) +{ + (*outStream) << kFirstQuestionMessage; + for(;;) + { + (*outStream) << kHelpQuestionMessage; + AString scannedString; + g_StdIn.ScanAStringUntilNewLine(scannedString); + scannedString.Trim(); + if(!scannedString.IsEmpty()) + switch(::MyCharUpper(scannedString[0])) + { + case kYes: + return NUserAnswerMode::kYes; + case kNo: + return NUserAnswerMode::kNo; + case kYesAll: + return NUserAnswerMode::kYesAll; + case kNoAll: + return NUserAnswerMode::kNoAll; + case kAutoRename: + return NUserAnswerMode::kAutoRename; + case kQuit: + return NUserAnswerMode::kQuit; + } + } +} + +UString GetPassword(CStdOutStream *outStream) +{ + (*outStream) << "\nEnter password:"; + outStream->Flush(); + AString oemPassword; + g_StdIn.ScanAStringUntilNewLine(oemPassword); + return MultiByteToUnicodeString(oemPassword, CP_OEMCP); +} diff --git a/versions/zstd/CPP/7zip/UI/NSIS/UserInputUtils2.h b/versions/zstd/CPP/7zip/UI/NSIS/UserInputUtils2.h new file mode 100644 index 0000000..d8c3de0 --- /dev/null +++ b/versions/zstd/CPP/7zip/UI/NSIS/UserInputUtils2.h @@ -0,0 +1,24 @@ +// UserInputUtils.h + +#ifndef __USERINPUTUTILS_H +#define __USERINPUTUTILS_H + +#include "Common/StdOutStream.h" + +namespace NUserAnswerMode { + +enum EEnum +{ + kYes, + kNo, + kYesAll, + kNoAll, + kAutoRename, + kQuit +}; +} + +NUserAnswerMode::EEnum ScanUserYesNoAllQuit2(CStdOutStream *outStream); +UString GetPassword(CStdOutStream *outStream); + +#endif