Windows installer 2.0 (C++ port)
No files matched your search
@@ -0,0 +1,40 @@
|
|||||||
|
# Build output
|
||||||
|
build/
|
||||||
|
build_x64/
|
||||||
|
build_x86/
|
||||||
|
out/
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.lib
|
||||||
|
*.exp
|
||||||
|
*.obj
|
||||||
|
*.pdb
|
||||||
|
*.ilk
|
||||||
|
*.res
|
||||||
|
*.tlog
|
||||||
|
*.idb
|
||||||
|
|
||||||
|
# Installation images and archives (never committed)
|
||||||
|
Data.pf
|
||||||
|
*.wim
|
||||||
|
*.esd
|
||||||
|
*.iso
|
||||||
|
*.pf
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
|
|
||||||
|
# Visual Studio
|
||||||
|
.vs/
|
||||||
|
*.vcxproj*
|
||||||
|
*.sln
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
|
||||||
|
# Logs, temporary and debug files
|
||||||
|
*.log
|
||||||
|
*.tmp
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
|
project(WindowsSetupCpp LANGUAGES CXX)
|
||||||
|
|
||||||
|
enable_language(RC)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
add_executable(WindowsSetup WIN32
|
||||||
|
src/main.cpp
|
||||||
|
src/util.cpp
|
||||||
|
app.rc
|
||||||
|
)
|
||||||
|
|
||||||
|
set_property(TARGET WindowsSetup PROPERTY MSVC_RUNTIME_LIBRARY
|
||||||
|
"MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
|
||||||
|
target_compile_definitions(WindowsSetup PRIVATE
|
||||||
|
UNICODE
|
||||||
|
_UNICODE
|
||||||
|
WIN32_LEAN_AND_MEAN
|
||||||
|
NOMINMAX
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_options(WindowsSetup PRIVATE
|
||||||
|
/utf-8
|
||||||
|
/W4
|
||||||
|
/permissive-
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(WindowsSetup PRIVATE
|
||||||
|
user32
|
||||||
|
gdi32
|
||||||
|
gdiplus
|
||||||
|
ole32
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_options(WindowsSetup PRIVATE /MANIFEST:NO)
|
||||||
|
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set_target_properties(WindowsSetup PROPERTIES OUTPUT_NAME "setup_x64")
|
||||||
|
else()
|
||||||
|
set_target_properties(WindowsSetup PROPERTIES OUTPUT_NAME "setup_x86")
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Paravis
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# Windows Setup by Paravis — C++ port
|
||||||
|
|
||||||
|
Native Win32 port of `Windows_installer_NEW\setup.au3`.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Requirements: Visual Studio 2022 (Desktop C++) and CMake 3.20+.
|
||||||
|
|
||||||
|
```bat
|
||||||
|
build.cmd
|
||||||
|
```
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
|
||||||
|
```
|
||||||
|
build_x64\Release\setup_x64.exe
|
||||||
|
build_x86\Release\setup_x86.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
The executables use a static CRT, are GUI subsystem, and use the same
|
||||||
|
`asInvoker` manifest / Common Controls 6 as the AutoIt builds.
|
||||||
|
|
||||||
|
## Preview
|
||||||
|
|
||||||
|
- `setup_x64.exe /preview` or an executable named `setup_preview*.exe`
|
||||||
|
starts preview mode: fixed 307×259 position, all buttons enabled, no
|
||||||
|
`src_*.exe` helper, preview wallpaper.
|
||||||
|
- The ported `setup_preview.exe` in `..\Windows_installer_NEW` is the x64
|
||||||
|
build used this way.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
On a PARAVIS flash the two Windows Setup WIMs are:
|
||||||
|
|
||||||
|
- `\efi\Paravis\Boot\ws64.wim`, image 1, `\Windows\Setup.exe` — x64 build
|
||||||
|
- `\efi\Paravis\Boot\ws86.wim`, image 1, `\Windows\Setup.exe` — x86 build
|
||||||
|
|
||||||
|
`Winpeshl.ini` in both WIMs already launches `%SYSTEMROOT%\setup.exe`.
|
||||||
|
The launcher starts the real setup from `X:\sources\setup.exe`.
|
||||||
|
|
||||||
|
The window is layered with color key `0xABCDEF`. The Montserrat fonts are
|
||||||
|
embedded as RCDATA; the 1024×768 wallpaper is embedded as a lossless PNG and
|
||||||
|
decoded with GDI+ at startup. This keeps each executable around 1 MB.
|
||||||
|
The UI is the same 376/410/360-wide layout as the AutoIt version, with native
|
||||||
|
buttons. GDI+ and ole32 are standard components of the Windows Setup boot.wim
|
||||||
|
(verified in the target image).
|
||||||
|
|
||||||
|
## Behaviour
|
||||||
|
|
||||||
|
- Searches all drives for `\WindowsESD\NOT.DEL` or
|
||||||
|
`\efi\Paravis\Windows\NOT.DEL`.
|
||||||
|
- Warns and exits if both image folders are present.
|
||||||
|
- Finds `\efi\Paravis\Boot\NOT.DEL` for `src_x64.exe` / `src_x86.exe`
|
||||||
|
and Total Commander.
|
||||||
|
- Uses `%WINDIR%\SYSWOW64` to select the x64 UI; `firmware_type` selects
|
||||||
|
Legacy vs UEFI for the x86 UI.
|
||||||
|
- Builds the same `X:\sources\setup.exe /installfrom:... /m:... [/unattend:...]`
|
||||||
|
command lines as AutoIt.
|
||||||
|
- Disables Windows buttons when the corresponding ESD image is missing.
|
||||||
|
- Reboot button exits the launcher (the WinPE startup script performs the
|
||||||
|
reboot).
|
||||||
|
- Debug log: set `PARAVIS_DEBUG_LOG=1` to write
|
||||||
|
`%TEMP%\winsetup_cpp_debug.log`.
|
||||||
|
|
||||||
|
## Repository layout
|
||||||
|
|
||||||
|
```
|
||||||
|
src/ C++ sources and resources
|
||||||
|
assets/ fonts, wallpapers and UI images (incl. Montserrat OFL)
|
||||||
|
legacy-au3/ original AutoIt scripts
|
||||||
|
app.rc resource script
|
||||||
|
app.manifest application manifest
|
||||||
|
build.cmd release build (x64 + x86)
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT for the program code. See [`LICENSE`](LICENSE).
|
||||||
|
|
||||||
|
Montserrat is licensed under the SIL Open Font License 1.1; see
|
||||||
|
[`assets/OFL.txt`](assets/OFL.txt) and [`THIRD-PARTY.md`](THIRD-PARTY.md).
|
||||||
|
|
||||||
|
This repository contains source code only. Windows installation images
|
||||||
|
(`*.wim`, `*.esd`, `Data.pf`), Microsoft font derivatives and third-party
|
||||||
|
binaries are not distributed here.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Third-party components
|
||||||
|
|
||||||
|
## Montserrat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
|
||||||
|
- `assets/Montserrat-Regular.ttf`
|
||||||
|
- `assets/Montserrat-Bold.ttf`
|
||||||
|
|
||||||
|
Copyright 2024 The Montserrat.Git Project Authors
|
||||||
|
(https://github.com/JulietaUla/Montserrat.git)
|
||||||
|
|
||||||
|
Licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
The full license text is in [`assets/OFL.txt`](assets/OFL.txt) and is also
|
||||||
|
available at <https://openfontlicense.org>.
|
||||||
|
|
||||||
|
The fonts are embedded into the built executables as `RCDATA` resources so
|
||||||
|
that the installer does not depend on system fonts.
|
||||||
|
|
||||||
|
## Images and icons
|
||||||
|
|
||||||
|
`assets/*.png`, `assets/*.bmp`, `assets/*.jpg` and `sec.ico` are Paravis
|
||||||
|
artwork used by the installer UI.
|
||||||
|
|
||||||
|
## Not included
|
||||||
|
|
||||||
|
This repository contains source code and build assets only. It does not
|
||||||
|
contain, and must not be used to redistribute:
|
||||||
|
|
||||||
|
- Microsoft installation images (`*.wim`, `*.esd`, `*.iso`), including the
|
||||||
|
`Data.pf` archive;
|
||||||
|
- Microsoft font derivatives (`tahoma*.pf2`, `segoeui18.pf2`);
|
||||||
|
- Total Commander or any other third-party binaries;
|
||||||
|
- signing keys, certificates or signed binaries;
|
||||||
|
- build output (`*.exe`, object files, logs).
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<dependency>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
||||||
|
</dependentAssembly>
|
||||||
|
</dependency>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges>
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
</assembly>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
1 ICON "sec.ico"
|
||||||
|
1 24 "app.manifest"
|
||||||
|
|
||||||
|
101 RCDATA "assets\\Montserrat-Regular.ttf"
|
||||||
|
102 RCDATA "assets\\Montserrat-Bold.ttf"
|
||||||
|
|
||||||
|
201 RCDATA "assets\\wallpaper-install.png"
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2024 The Montserrat.Git Project Authors (https://github.com/JulietaUla/Montserrat.git)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
https://openfontlicense.org
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 1023 B |
|
After Width: | Height: | Size: 428 B |
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 59 KiB |
@@ -0,0 +1,18 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
cmake -S . -B build_x64 -G "Visual Studio 17 2022" -A x64
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
cmake --build build_x64 --config Release
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
|
||||||
|
cmake -S . -B build_x86 -G "Visual Studio 17 2022" -A Win32
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
cmake --build build_x86 --config Release
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Built:
|
||||||
|
echo %~dp0build_x64\Release\setup_x64.exe
|
||||||
|
echo %~dp0build_x86\Release\setup_x86.exe
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Windows installer (legacy AutoIt)
|
||||||
|
|
||||||
|
Исходный текст оригинальной версии на AutoIt (`setup.au3`,
|
||||||
|
`setup-preview.au3`). Поддерживаемая версия — C++-порт в корне репозитория
|
||||||
|
(`src/`, `assets/`, `CMakeLists.txt`).
|
||||||
|
|
||||||
|
## Сборка C++ версии
|
||||||
|
|
||||||
|
Из корня репозитория:
|
||||||
|
|
||||||
|
```
|
||||||
|
build.cmd
|
||||||
|
```
|
||||||
|
|
||||||
|
Получаются `build_x64\Release\setup_x64.exe` и
|
||||||
|
`build_x86\Release\setup_x86.exe`. `setup_preview.exe` — x64-сборка в режиме
|
||||||
|
предпросмотра (режим определяется по имени файла или ключу `/preview`).
|
||||||
|
|
||||||
|
## Размещение на флешке PARAVIS
|
||||||
|
|
||||||
|
- `\efi\Paravis\Boot\ws64.wim` — образ 1, `\Windows\Setup.exe` (x64)
|
||||||
|
- `\efi\Paravis\Boot\ws86.wim` — образ 1, `\Windows\Setup.exe` (x86)
|
||||||
|
|
||||||
|
`Winpeshl.ini` в этих WIM указывает на `%SYSTEMROOT%\setup.exe`.
|
||||||
|
|
||||||
|
Образы установки могут размещаться на любом диске, но с сохранением путей.
|
||||||
|
Если путей больше одного, будет ошибка.
|
||||||
|
|
||||||
|
> Первый путь — `../efi/Paravis/Windows`
|
||||||
|
> Второй путь — `../WindowsESD`
|
||||||
|
|
||||||
|
Также нужно создать файл `NOT.DEL` (можно пустой) в двух местах:
|
||||||
|
|
||||||
|
1. по пути, где лежат образы ESD;
|
||||||
|
2. по пути `../efi/Paravis/Boot/`.
|
||||||
@@ -0,0 +1,240 @@
|
|||||||
|
#NoTrayIcon
|
||||||
|
#include <Array.au3>
|
||||||
|
#include <File.au3>
|
||||||
|
#include <GUIConstantsEx.au3>
|
||||||
|
#include <WindowsConstants.au3>
|
||||||
|
#include <WinAPI.au3>
|
||||||
|
#include <AutoItConstants.au3>
|
||||||
|
|
||||||
|
Global $aArray = DriveGetDrive($DT_ALL), $sDisk, $iBtn11, $iBtn10, $iBtn7, $PathEr, $sDiskS, $UN11, $UN10x64, $UN10x86, $UN7x64, $UN7x86
|
||||||
|
Global $bFontOk = False, $font = "Segoe UI"
|
||||||
|
|
||||||
|
_LoadFonts()
|
||||||
|
$font = _Font()
|
||||||
|
|
||||||
|
For $i = 1 To $aArray[0]
|
||||||
|
$aFileList = _FileListToArrayRec($aArray[$i] & "\WindowsESD", "NOT.DEL", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
|
||||||
|
If Not @error Then
|
||||||
|
$sDisk = $aArray[$i] & "\WindowsESD\"
|
||||||
|
$PathEr = 1
|
||||||
|
ExitLoop
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
For $i = 1 To $aArray[0]
|
||||||
|
$aFileList = _FileListToArrayRec($aArray[$i] & "\efi\Paravis\Windows", "NOT.DEL", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
|
||||||
|
If Not @error Then
|
||||||
|
$sDisk = $aArray[$i] & "\efi\Paravis\Windows\"
|
||||||
|
$PathEr += 1
|
||||||
|
ExitLoop
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
If $PathEr > 1 Then
|
||||||
|
MsgBox(48, 'Предупреждение!', 'В системе больше одной папки с образами. Проверьте и удалите лишние (читаем ReadMe.txt). Система будет перезагружена.')
|
||||||
|
Exit
|
||||||
|
EndIf
|
||||||
|
For $i = 1 To $aArray[0]
|
||||||
|
$aFileList = _FileListToArrayRec($aArray[$i] & "\efi\Paravis\Boot", "NOT.DEL", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
|
||||||
|
If Not @error Then
|
||||||
|
$sDiskS = $aArray[$i] & "\efi\Paravis\Boot"
|
||||||
|
ExitLoop
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
|
||||||
|
$ESD11 = $sDisk & "install_11.esd"
|
||||||
|
$ESD10x64 = $sDisk & "install_10_x64.esd"
|
||||||
|
$ESD10x86 = $sDisk & "install_10_x86.esd"
|
||||||
|
$ESD7x64 = $sDisk & "install_7_x64.esd"
|
||||||
|
$ESD7x86 = $sDisk & "install_7_x86.esd"
|
||||||
|
If FileExists($sDisk & "autounattend\unattend11.xml") Then
|
||||||
|
$UN11 = " /unattend:" & $sDisk & "autounattend\unattend11.xml"
|
||||||
|
Else
|
||||||
|
$UN11 = ''
|
||||||
|
EndIf
|
||||||
|
If FileExists($sDisk & "autounattend\unattend10x64.xml") Then
|
||||||
|
$UN10x64 = " /unattend:" & $sDisk & "autounattend\unattend10x64.xml"
|
||||||
|
Else
|
||||||
|
$UN10x64 = ''
|
||||||
|
EndIf
|
||||||
|
If FileExists($sDisk & "autounattend\unattend10x86.xml") Then
|
||||||
|
$UN10x86 = " /unattend:" & $sDisk & "autounattend\unattend10x86.xml"
|
||||||
|
Else
|
||||||
|
$UN10x86 = ''
|
||||||
|
EndIf
|
||||||
|
If FileExists($sDisk & "autounattend\unattend7x64.xml") Then
|
||||||
|
$UN7x64 = " /unattend:" & $sDisk & "autounattend\unattend7x64.xml"
|
||||||
|
Else
|
||||||
|
$UN7x64 = ''
|
||||||
|
EndIf
|
||||||
|
If FileExists($sDisk & "autounattend\unattend7x86.xml") Then
|
||||||
|
$UN7x86 = " /unattend:" & $sDisk & "autounattend\unattend7x86.xml"
|
||||||
|
Else
|
||||||
|
$UN7x86 = ''
|
||||||
|
EndIf
|
||||||
|
$OEM11 = " /m:" & $sDisk & "$OEM11$"
|
||||||
|
$OEM10x64 = " /m:" & $sDisk & "$OEM10x64$"
|
||||||
|
$OEM10x86 = " /m:" & $sDisk & "$OEM10x86$"
|
||||||
|
$OEM7x64 = " /m:" & $sDisk & "$OEM7x64$"
|
||||||
|
$OEM7x86 = " /m:" & $sDisk & "$OEM7x86$"
|
||||||
|
$setup = "X:\sources\setup.exe /installfrom:"
|
||||||
|
If FileExists(@WindowsDir & "\SYSWOW64") Then
|
||||||
|
; preview skip
|
||||||
|
_x64()
|
||||||
|
Else
|
||||||
|
; preview skip
|
||||||
|
_x86()
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
Func _LoadFonts()
|
||||||
|
Local $reg = @TempDir & "\Montserrat-Regular.ttf"
|
||||||
|
Local $bold = @TempDir & "\Montserrat-Bold.ttf"
|
||||||
|
FileInstall("assets\Montserrat-Regular.ttf", $reg, 1)
|
||||||
|
FileInstall("assets\Montserrat-Bold.ttf", $bold, 1)
|
||||||
|
Local $r1 = DllCall("gdi32.dll", "int", "AddFontResourceExW", "wstr", $reg, "dword", 0x10, "ptr", 0)
|
||||||
|
Local $r2 = DllCall("gdi32.dll", "int", "AddFontResourceExW", "wstr", $bold, "dword", 0x10, "ptr", 0)
|
||||||
|
If IsArray($r1) And IsArray($r2) Then
|
||||||
|
If $r1[0] > 0 Or $r2[0] > 0 Then $bFontOk = True
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _Font()
|
||||||
|
If $bFontOk Then Return "Montserrat"
|
||||||
|
Return "Segoe UI"
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _x86()
|
||||||
|
$detect_efi = EnvGet("firmware_type")
|
||||||
|
If $detect_efi = "Legacy" Then
|
||||||
|
$hGUI = GUICreate("Windows Setup by Paravis", 410, 250, 307, 259, $WS_POPUP, $WS_EX_LAYERED)
|
||||||
|
GUISetBkColor(0xABCDEF)
|
||||||
|
GUICtrlSetState(-1, $GUI_DISABLE)
|
||||||
|
GUISetState()
|
||||||
|
_WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF, 255)
|
||||||
|
$iBtn10 = GUICtrlCreateButton("Установить Windows 10", 5, 5, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtn7 = GUICtrlCreateButton("Установить Windows 7", 5, 45, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnTC = GUICtrlCreateButton("Total Commander", 5, 105, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnR = GUICtrlCreateButton("Перезагрузка", 5, 145, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
GUISetState()
|
||||||
|
_checkesd86()
|
||||||
|
While 1
|
||||||
|
Switch GUIGetMsg()
|
||||||
|
Case $GUI_EVENT_CLOSE
|
||||||
|
Case $iBtn10
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD10x86 & $OEM10x86 & $UN10x86)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtn7
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD7x86 & $OEM7x86 & $UN7x86)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnTC
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($sDiskS & '\TotalCommander\TOTALCMD.EXE /I="%%COMMANDER_PATH%%\tcmdmain.ini"')
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnR
|
||||||
|
Exit
|
||||||
|
EndSwitch
|
||||||
|
WEnd
|
||||||
|
Else
|
||||||
|
If Not FileExists($sDisk & "install_10_x86.esd") Then
|
||||||
|
MsgBox(48, 'Предупреждение!', 'Не найден образ Windows 10 x86. Система будет перезагружена.')
|
||||||
|
Exit
|
||||||
|
EndIf
|
||||||
|
$hGUI = GUICreate("Windows Setup by Paravis", 360, 190, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
|
||||||
|
GUISetBkColor(0xABCDEF)
|
||||||
|
GUICtrlSetState(-1, $GUI_DISABLE)
|
||||||
|
GUISetState()
|
||||||
|
_WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF, 255)
|
||||||
|
$iBtn10 = GUICtrlCreateButton("Установить Windows 10", 5, 5, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnTC = GUICtrlCreateButton("Total Commander", 5, 65, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnR = GUICtrlCreateButton("Перезагрузка", 5, 105, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
GUISetState()
|
||||||
|
While 1
|
||||||
|
Switch GUIGetMsg()
|
||||||
|
Case $GUI_EVENT_CLOSE
|
||||||
|
Case $iBtn10
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD10x86 & $OEM10x86 & $UN10x86)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnTC
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($sDiskS & '\TotalCommander\TOTALCMD.EXE /I="%%COMMANDER_PATH%%\tcmdmain.ini"')
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnR
|
||||||
|
Exit
|
||||||
|
EndSwitch
|
||||||
|
WEnd
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _x64()
|
||||||
|
$hGUI = GUICreate("Windows Setup by Paravis", 410, 250, 307, 259, $WS_POPUP, $WS_EX_LAYERED)
|
||||||
|
GUISetBkColor(0xABCDEF)
|
||||||
|
GUICtrlSetState(-1, $GUI_DISABLE)
|
||||||
|
GUISetState()
|
||||||
|
_WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF, 255)
|
||||||
|
$iBtn11 = GUICtrlCreateButton("Установить Windows 11", 5, 5, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtn10 = GUICtrlCreateButton("Установить Windows 10", 5, 45, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtn7 = GUICtrlCreateButton("Установить Windows 7", 5, 85, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnTC = GUICtrlCreateButton("Total Commander", 5, 145, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnR = GUICtrlCreateButton("Перезагрузка", 5, 185, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
GUISetState()
|
||||||
|
_checkesd64()
|
||||||
|
While 1
|
||||||
|
Switch GUIGetMsg()
|
||||||
|
Case $GUI_EVENT_CLOSE
|
||||||
|
Case $iBtn11
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD11 & $OEM11 & $UN11)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtn10
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD10x64 & $OEM10x64 & $UN10x64)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtn7
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD7x64 & $OEM7x64 & $UN7x64)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnTC
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($sDiskS & '\TotalCommander\TOTALCMD64.EXE /I="%%COMMANDER_PATH%%\tcmdmain.ini"')
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnR
|
||||||
|
Exit
|
||||||
|
EndSwitch
|
||||||
|
WEnd
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _checkesd64()
|
||||||
|
Return
|
||||||
|
If Not FileExists($sDisk & "install_11.esd") Then
|
||||||
|
GUICtrlSetState($iBtn11, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
If Not FileExists($sDisk & "install_10_x64.esd") Then
|
||||||
|
GUICtrlSetState($iBtn10, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
If Not FileExists($sDisk & "install_7_x64.esd") Then
|
||||||
|
GUICtrlSetState($iBtn7, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _checkesd86()
|
||||||
|
Return
|
||||||
|
If Not FileExists($sDisk & "install_10_x86.esd") Then
|
||||||
|
GUICtrlSetState($iBtn10, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
If Not FileExists($sDisk & "install_7_x86.esd") Then
|
||||||
|
GUICtrlSetState($iBtn7, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
#NoTrayIcon
|
||||||
|
#include <Array.au3>
|
||||||
|
#include <File.au3>
|
||||||
|
#include <GUIConstantsEx.au3>
|
||||||
|
#include <WindowsConstants.au3>
|
||||||
|
#include <WinAPI.au3>
|
||||||
|
#include <AutoItConstants.au3>
|
||||||
|
|
||||||
|
Global $aArray = DriveGetDrive($DT_ALL), $sDisk, $iBtn11, $iBtn10, $iBtn7, $PathEr, $sDiskS, $UN11, $UN10x64, $UN10x86, $UN7x64, $UN7x86
|
||||||
|
Global $bFontOk = False, $font = "Segoe UI", $hBg
|
||||||
|
|
||||||
|
_LoadFonts()
|
||||||
|
$font = _Font()
|
||||||
|
_ShowWallpaper()
|
||||||
|
|
||||||
|
For $i = 1 To $aArray[0]
|
||||||
|
$aFileList = _FileListToArrayRec($aArray[$i] & "\WindowsESD", "NOT.DEL", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
|
||||||
|
If Not @error Then
|
||||||
|
$sDisk = $aArray[$i] & "\WindowsESD\"
|
||||||
|
$PathEr = 1
|
||||||
|
ExitLoop
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
For $i = 1 To $aArray[0]
|
||||||
|
$aFileList = _FileListToArrayRec($aArray[$i] & "\efi\Paravis\Windows", "NOT.DEL", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
|
||||||
|
If Not @error Then
|
||||||
|
$sDisk = $aArray[$i] & "\efi\Paravis\Windows\"
|
||||||
|
$PathEr += 1
|
||||||
|
ExitLoop
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
If $PathEr > 1 Then
|
||||||
|
MsgBox(48, 'Предупреждение!', 'В системе больше одной папки с образами. Проверьте и удалите лишние (читаем ReadMe.txt). Система будет перезагружена.')
|
||||||
|
Exit
|
||||||
|
EndIf
|
||||||
|
For $i = 1 To $aArray[0]
|
||||||
|
$aFileList = _FileListToArrayRec($aArray[$i] & "\efi\Paravis\Boot", "NOT.DEL", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
|
||||||
|
If Not @error Then
|
||||||
|
$sDiskS = $aArray[$i] & "\efi\Paravis\Boot"
|
||||||
|
ExitLoop
|
||||||
|
EndIf
|
||||||
|
Next
|
||||||
|
|
||||||
|
$ESD11 = $sDisk & "install_11.esd"
|
||||||
|
$ESD10x64 = $sDisk & "install_10_x64.esd"
|
||||||
|
$ESD10x86 = $sDisk & "install_10_x86.esd"
|
||||||
|
$ESD7x64 = $sDisk & "install_7_x64.esd"
|
||||||
|
$ESD7x86 = $sDisk & "install_7_x86.esd"
|
||||||
|
If FileExists($sDisk & "autounattend\unattend11.xml") Then
|
||||||
|
$UN11 = " /unattend:" & $sDisk & "autounattend\unattend11.xml"
|
||||||
|
Else
|
||||||
|
$UN11 = ''
|
||||||
|
EndIf
|
||||||
|
If FileExists($sDisk & "autounattend\unattend10x64.xml") Then
|
||||||
|
$UN10x64 = " /unattend:" & $sDisk & "autounattend\unattend10x64.xml"
|
||||||
|
Else
|
||||||
|
$UN10x64 = ''
|
||||||
|
EndIf
|
||||||
|
If FileExists($sDisk & "autounattend\unattend10x86.xml") Then
|
||||||
|
$UN10x86 = " /unattend:" & $sDisk & "autounattend\unattend10x86.xml"
|
||||||
|
Else
|
||||||
|
$UN10x86 = ''
|
||||||
|
EndIf
|
||||||
|
If FileExists($sDisk & "autounattend\unattend7x64.xml") Then
|
||||||
|
$UN7x64 = " /unattend:" & $sDisk & "autounattend\unattend7x64.xml"
|
||||||
|
Else
|
||||||
|
$UN7x64 = ''
|
||||||
|
EndIf
|
||||||
|
If FileExists($sDisk & "autounattend\unattend7x86.xml") Then
|
||||||
|
$UN7x86 = " /unattend:" & $sDisk & "autounattend\unattend7x86.xml"
|
||||||
|
Else
|
||||||
|
$UN7x86 = ''
|
||||||
|
EndIf
|
||||||
|
$OEM11 = " /m:" & $sDisk & "$OEM11$"
|
||||||
|
$OEM10x64 = " /m:" & $sDisk & "$OEM10x64$"
|
||||||
|
$OEM10x86 = " /m:" & $sDisk & "$OEM10x86$"
|
||||||
|
$OEM7x64 = " /m:" & $sDisk & "$OEM7x64$"
|
||||||
|
$OEM7x86 = " /m:" & $sDisk & "$OEM7x86$"
|
||||||
|
$setup = "X:\sources\setup.exe /installfrom:"
|
||||||
|
If FileExists(@WindowsDir & "\SYSWOW64") Then
|
||||||
|
RunWait($sDiskS & "\src_x64.exe auto2")
|
||||||
|
_x64()
|
||||||
|
Else
|
||||||
|
RunWait($sDiskS & "\src_x86.exe auto2")
|
||||||
|
_x86()
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
Func _LoadFonts()
|
||||||
|
Local $reg = @TempDir & "\Montserrat-Regular.ttf"
|
||||||
|
Local $bold = @TempDir & "\Montserrat-Bold.ttf"
|
||||||
|
FileInstall("assets\Montserrat-Regular.ttf", $reg, 1)
|
||||||
|
FileInstall("assets\Montserrat-Bold.ttf", $bold, 1)
|
||||||
|
Local $r1 = DllCall("gdi32.dll", "int", "AddFontResourceExW", "wstr", $reg, "dword", 0x10, "ptr", 0)
|
||||||
|
Local $r2 = DllCall("gdi32.dll", "int", "AddFontResourceExW", "wstr", $bold, "dword", 0x10, "ptr", 0)
|
||||||
|
If IsArray($r1) And IsArray($r2) Then
|
||||||
|
If $r1[0] > 0 Or $r2[0] > 0 Then $bFontOk = True
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _Font()
|
||||||
|
If $bFontOk Then Return "Montserrat"
|
||||||
|
Return "Segoe UI"
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _ShowWallpaper()
|
||||||
|
Local $bg = @TempDir & "\paravis_wallpaper.bmp"
|
||||||
|
FileInstall("assets\wallpaper-install.bmp", $bg, 1)
|
||||||
|
$hBg = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW)
|
||||||
|
GUICtrlCreatePic($bg, 0, 0, @DesktopWidth, @DesktopHeight)
|
||||||
|
GUISetState(@SW_SHOW, $hBg)
|
||||||
|
EndFunc
|
||||||
|
Func _x86()
|
||||||
|
$detect_efi = EnvGet("firmware_type")
|
||||||
|
If $detect_efi = "Legacy" Then
|
||||||
|
$hGUI = GUICreate("Windows Setup by Paravis", 410, 250, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
|
||||||
|
GUISetBkColor(0xABCDEF)
|
||||||
|
GUICtrlSetState(-1, $GUI_DISABLE)
|
||||||
|
GUISetState()
|
||||||
|
_WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF, 255)
|
||||||
|
WinSetOnTop($hGUI, "", 1)
|
||||||
|
$iBtn10 = GUICtrlCreateButton("Установить Windows 10", 5, 5, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtn7 = GUICtrlCreateButton("Установить Windows 7", 5, 45, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnTC = GUICtrlCreateButton("Total Commander", 5, 105, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnR = GUICtrlCreateButton("Перезагрузка", 5, 145, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
GUISetState()
|
||||||
|
_checkesd86()
|
||||||
|
While 1
|
||||||
|
Switch GUIGetMsg()
|
||||||
|
Case $GUI_EVENT_CLOSE
|
||||||
|
Case $iBtn10
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD10x86 & $OEM10x86 & $UN10x86)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtn7
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD7x86 & $OEM7x86 & $UN7x86)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnTC
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($sDiskS & '\TotalCommander\TOTALCMD.EXE /I="%%COMMANDER_PATH%%\tcmdmain.ini"')
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnR
|
||||||
|
Exit
|
||||||
|
EndSwitch
|
||||||
|
WEnd
|
||||||
|
Else
|
||||||
|
If Not FileExists($sDisk & "install_10_x86.esd") Then
|
||||||
|
MsgBox(48, 'Предупреждение!', 'Не найден образ Windows 10 x86. Система будет перезагружена.')
|
||||||
|
Exit
|
||||||
|
EndIf
|
||||||
|
$hGUI = GUICreate("Windows Setup by Paravis", 360, 190, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
|
||||||
|
GUISetBkColor(0xABCDEF)
|
||||||
|
GUICtrlSetState(-1, $GUI_DISABLE)
|
||||||
|
GUISetState()
|
||||||
|
_WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF, 255)
|
||||||
|
WinSetOnTop($hGUI, "", 1)
|
||||||
|
$iBtn10 = GUICtrlCreateButton("Установить Windows 10", 5, 5, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnTC = GUICtrlCreateButton("Total Commander", 5, 65, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnR = GUICtrlCreateButton("Перезагрузка", 5, 105, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
GUISetState()
|
||||||
|
While 1
|
||||||
|
Switch GUIGetMsg()
|
||||||
|
Case $GUI_EVENT_CLOSE
|
||||||
|
Case $iBtn10
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD10x86 & $OEM10x86 & $UN10x86)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnTC
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($sDiskS & '\TotalCommander\TOTALCMD.EXE /I="%%COMMANDER_PATH%%\tcmdmain.ini"')
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnR
|
||||||
|
Exit
|
||||||
|
EndSwitch
|
||||||
|
WEnd
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _x64()
|
||||||
|
$hGUI = GUICreate("Windows Setup by Paravis", 410, 250, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
|
||||||
|
GUISetBkColor(0xABCDEF)
|
||||||
|
GUICtrlSetState(-1, $GUI_DISABLE)
|
||||||
|
GUISetState()
|
||||||
|
_WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF, 255)
|
||||||
|
WinSetOnTop($hGUI, "", 1)
|
||||||
|
$iBtn11 = GUICtrlCreateButton("Установить Windows 11", 5, 5, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtn10 = GUICtrlCreateButton("Установить Windows 10", 5, 45, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtn7 = GUICtrlCreateButton("Установить Windows 7", 5, 85, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnTC = GUICtrlCreateButton("Total Commander", 5, 145, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
$iBtnR = GUICtrlCreateButton("Перезагрузка", 5, 185, 350, 40)
|
||||||
|
GUICtrlSetFont(-1, 13, 500, 0, $font)
|
||||||
|
GUISetState()
|
||||||
|
_checkesd64()
|
||||||
|
While 1
|
||||||
|
Switch GUIGetMsg()
|
||||||
|
Case $GUI_EVENT_CLOSE
|
||||||
|
Case $iBtn11
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD11 & $OEM11 & $UN11)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtn10
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD10x64 & $OEM10x64 & $UN10x64)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtn7
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($setup & $ESD7x64 & $OEM7x64 & $UN7x64)
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnTC
|
||||||
|
GUISetState(@SW_HIDE)
|
||||||
|
RunWait($sDiskS & '\TotalCommander\TOTALCMD64.EXE /I="%%COMMANDER_PATH%%\tcmdmain.ini"')
|
||||||
|
GUISetState(@SW_SHOW)
|
||||||
|
Case $iBtnR
|
||||||
|
Exit
|
||||||
|
EndSwitch
|
||||||
|
WEnd
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _checkesd64()
|
||||||
|
If Not FileExists($sDisk & "install_11.esd") Then
|
||||||
|
GUICtrlSetState($iBtn11, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
If Not FileExists($sDisk & "install_10_x64.esd") Then
|
||||||
|
GUICtrlSetState($iBtn10, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
If Not FileExists($sDisk & "install_7_x64.esd") Then
|
||||||
|
GUICtrlSetState($iBtn7, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func _checkesd86()
|
||||||
|
If Not FileExists($sDisk & "install_10_x86.esd") Then
|
||||||
|
GUICtrlSetState($iBtn10, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
If Not FileExists($sDisk & "install_7_x86.esd") Then
|
||||||
|
GUICtrlSetState($iBtn7, $GUI_DISABLE)
|
||||||
|
EndIf
|
||||||
|
EndFunc
|
||||||
@@ -0,0 +1,627 @@
|
|||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <windowsx.h>
|
||||||
|
#include <objbase.h>
|
||||||
|
#include <gdiplus.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cwchar>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const wchar_t* kMainClass = L"ParavisWindowsSetupMain";
|
||||||
|
const wchar_t* kWallClass = L"ParavisWindowsSetupWallpaper";
|
||||||
|
|
||||||
|
const COLORREF CLR_KEY = RGB(0xAB, 0xCD, 0xEF);
|
||||||
|
const int IDI_APP = 1;
|
||||||
|
const int IDR_FONT_REGULAR = 101;
|
||||||
|
const int IDR_FONT_BOLD = 102;
|
||||||
|
const int IDR_WALLPAPER = 201;
|
||||||
|
|
||||||
|
HINSTANCE g_hInst = nullptr;
|
||||||
|
HWND g_wallHwnd = nullptr;
|
||||||
|
HWND g_mainHwnd = nullptr;
|
||||||
|
HBITMAP g_wallBitmap = nullptr;
|
||||||
|
int g_wallWidth = 0;
|
||||||
|
int g_wallHeight = 0;
|
||||||
|
HBRUSH g_keyBrush = nullptr;
|
||||||
|
HFONT g_buttonFont = nullptr;
|
||||||
|
std::wstring g_fontFace = L"Segoe UI";
|
||||||
|
std::wstring g_imageRoot;
|
||||||
|
std::wstring g_bootRoot;
|
||||||
|
bool g_preview = false;
|
||||||
|
bool g_is64 = true;
|
||||||
|
bool g_x86Legacy = false;
|
||||||
|
bool g_busy = false;
|
||||||
|
bool g_gdiplusStarted = false;
|
||||||
|
ULONG_PTR g_gdiplusToken = 0;
|
||||||
|
|
||||||
|
enum class Action {
|
||||||
|
Win11,
|
||||||
|
Win10x64,
|
||||||
|
Win7x64,
|
||||||
|
Win10x86,
|
||||||
|
Win7x86,
|
||||||
|
TotalCmd64,
|
||||||
|
TotalCmd86,
|
||||||
|
Reboot
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ButtonDef {
|
||||||
|
int id = 0;
|
||||||
|
std::wstring text;
|
||||||
|
int y = 0;
|
||||||
|
Action action = Action::Reboot;
|
||||||
|
bool enabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<ButtonDef> g_buttons;
|
||||||
|
|
||||||
|
void FillRectColor(HDC dc, const RECT& rect, COLORREF color)
|
||||||
|
{
|
||||||
|
HBRUSH brush = CreateSolidBrush(color);
|
||||||
|
FillRect(dc, &rect, brush);
|
||||||
|
DeleteObject(brush);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring Lower(std::wstring value)
|
||||||
|
{
|
||||||
|
for (wchar_t& ch : value) {
|
||||||
|
ch = static_cast<wchar_t>(towlower(ch));
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartsWith(const std::wstring& value, const std::wstring& prefix)
|
||||||
|
{
|
||||||
|
return value.size() >= prefix.size() &&
|
||||||
|
_wcsnicmp(value.c_str(), prefix.c_str(), prefix.size()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasPreviewArg()
|
||||||
|
{
|
||||||
|
std::wstring name = Lower(GetExeFileName());
|
||||||
|
if (StartsWith(name, L"setup_preview")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::wstring commandLine = Lower(GetCommandLineW());
|
||||||
|
return commandLine.find(L"/preview") != std::wstring::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring FirmwareType()
|
||||||
|
{
|
||||||
|
wchar_t buffer[64] = {};
|
||||||
|
DWORD length = GetEnvironmentVariableW(L"firmware_type", buffer,
|
||||||
|
static_cast<DWORD>(std::size(buffer)));
|
||||||
|
if (length == 0 || length >= std::size(buffer)) {
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
return std::wstring(buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring LoadFonts()
|
||||||
|
{
|
||||||
|
std::wstring temp = GetTempDir();
|
||||||
|
std::wstring regular = temp + L"Montserrat-Regular.ttf";
|
||||||
|
std::wstring bold = temp + L"Montserrat-Bold.ttf";
|
||||||
|
|
||||||
|
bool loaded = false;
|
||||||
|
if (ExtractResourceToFile(g_hInst, IDR_FONT_REGULAR, RT_RCDATA, regular)) {
|
||||||
|
if (AddFontResourceExW(regular.c_str(), FR_PRIVATE, nullptr) > 0) {
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ExtractResourceToFile(g_hInst, IDR_FONT_BOLD, RT_RCDATA, bold)) {
|
||||||
|
if (AddFontResourceExW(bold.c_str(), FR_PRIVATE, nullptr) > 0) {
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugLog(L"fonts loaded=%d regular=%s bold=%s", loaded ? 1 : 0,
|
||||||
|
regular.c_str(), bold.c_str());
|
||||||
|
return loaded ? L"Montserrat" : L"Segoe UI";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadWallpaper()
|
||||||
|
{
|
||||||
|
HRSRC resource = FindResourceW(g_hInst, MAKEINTRESOURCEW(IDR_WALLPAPER),
|
||||||
|
RT_RCDATA);
|
||||||
|
if (!resource) {
|
||||||
|
DebugLog(L"wallpaper PNG resource not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD size = SizeofResource(g_hInst, resource);
|
||||||
|
HGLOBAL loaded = LoadResource(g_hInst, resource);
|
||||||
|
const void* data = loaded ? LockResource(loaded) : nullptr;
|
||||||
|
if (!data || size == 0) {
|
||||||
|
DebugLog(L"wallpaper PNG resource load failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HGLOBAL memory = GlobalAlloc(GMEM_MOVEABLE, size);
|
||||||
|
if (!memory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void* destination = GlobalLock(memory);
|
||||||
|
if (!destination) {
|
||||||
|
GlobalFree(memory);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(destination, data, size);
|
||||||
|
GlobalUnlock(memory);
|
||||||
|
|
||||||
|
IStream* stream = nullptr;
|
||||||
|
if (FAILED(CreateStreamOnHGlobal(memory, TRUE, &stream))) {
|
||||||
|
GlobalFree(memory);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gdiplus::Bitmap bitmap(stream, FALSE);
|
||||||
|
if (bitmap.GetLastStatus() == Gdiplus::Ok) {
|
||||||
|
HBITMAP handle = nullptr;
|
||||||
|
if (bitmap.GetHBITMAP(Gdiplus::Color(255, 255, 255), &handle) ==
|
||||||
|
Gdiplus::Ok && handle) {
|
||||||
|
g_wallBitmap = handle;
|
||||||
|
g_wallWidth = static_cast<int>(bitmap.GetWidth());
|
||||||
|
g_wallHeight = static_cast<int>(bitmap.GetHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream->Release();
|
||||||
|
|
||||||
|
DebugLog(L"wallpaper PNG %dx%d loaded=%d", g_wallWidth, g_wallHeight,
|
||||||
|
g_wallBitmap ? 1 : 0);
|
||||||
|
return g_wallBitmap != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaintWallpaper(HWND hwnd)
|
||||||
|
{
|
||||||
|
PAINTSTRUCT paint{};
|
||||||
|
HDC dc = BeginPaint(hwnd, &paint);
|
||||||
|
RECT client{};
|
||||||
|
GetClientRect(hwnd, &client);
|
||||||
|
|
||||||
|
if (g_wallBitmap) {
|
||||||
|
HDC memory = CreateCompatibleDC(dc);
|
||||||
|
HGDIOBJ old = SelectObject(memory, g_wallBitmap);
|
||||||
|
SetStretchBltMode(dc, COLORONCOLOR);
|
||||||
|
StretchBlt(dc, 0, 0, client.right, client.bottom,
|
||||||
|
memory, 0, 0, g_wallWidth, g_wallHeight, SRCCOPY);
|
||||||
|
SelectObject(memory, old);
|
||||||
|
DeleteDC(memory);
|
||||||
|
} else {
|
||||||
|
FillRectColor(dc, client, RGB(0xF0, 0xF0, 0xF0));
|
||||||
|
}
|
||||||
|
EndPaint(hwnd, &paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK WallpaperProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (message) {
|
||||||
|
case WM_ERASEBKGND:
|
||||||
|
return 1;
|
||||||
|
case WM_PAINT:
|
||||||
|
PaintWallpaper(hwnd);
|
||||||
|
return 0;
|
||||||
|
case WM_CLOSE:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProcW(hwnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ContainsMarkerRecursive(const std::wstring& folder, const wchar_t* marker,
|
||||||
|
int depth)
|
||||||
|
{
|
||||||
|
if (depth > 32 || !DirectoryExists(folder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW data{};
|
||||||
|
HANDLE find = FindFirstFileW((folder + L"\\*").c_str(), &data);
|
||||||
|
if (find == INVALID_HANDLE_VALUE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
do {
|
||||||
|
if (wcscmp(data.cFileName, L".") == 0 ||
|
||||||
|
wcscmp(data.cFileName, L"..") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
|
if ((data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
|
||||||
|
std::wstring child = folder + L"\\" + data.cFileName;
|
||||||
|
if (ContainsMarkerRecursive(child, marker, depth + 1)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_wcsicmp(data.cFileName, marker) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (FindNextFileW(find, &data));
|
||||||
|
|
||||||
|
FindClose(find);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowWarning(const std::wstring& text)
|
||||||
|
{
|
||||||
|
MessageBoxW(g_wallHwnd, text.c_str(), L"Предупреждение!",
|
||||||
|
MB_ICONWARNING | MB_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SearchPaths()
|
||||||
|
{
|
||||||
|
int pathCount = 0;
|
||||||
|
|
||||||
|
for (wchar_t letter = L'A'; letter <= L'Z'; ++letter) {
|
||||||
|
std::wstring root{ letter, L':', L'\\' };
|
||||||
|
if (GetDriveTypeW(root.c_str()) == DRIVE_NO_ROOT_DIR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ContainsMarkerRecursive(root + L"WindowsESD", L"NOT.DEL", 0)) {
|
||||||
|
g_imageRoot = root + L"WindowsESD\\";
|
||||||
|
++pathCount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (wchar_t letter = L'A'; letter <= L'Z'; ++letter) {
|
||||||
|
std::wstring root{ letter, L':', L'\\' };
|
||||||
|
if (GetDriveTypeW(root.c_str()) == DRIVE_NO_ROOT_DIR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ContainsMarkerRecursive(root + L"efi\\Paravis\\Windows", L"NOT.DEL", 0)) {
|
||||||
|
g_imageRoot = root + L"efi\\Paravis\\Windows\\";
|
||||||
|
++pathCount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathCount > 1) {
|
||||||
|
ShowWarning(L"В системе больше одной папки с образами. "
|
||||||
|
L"Проверьте и удалите лишние (читаем ReadMe.txt). "
|
||||||
|
L"Система будет перезагружена.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (wchar_t letter = L'A'; letter <= L'Z'; ++letter) {
|
||||||
|
std::wstring root{ letter, L':', L'\\' };
|
||||||
|
if (GetDriveTypeW(root.c_str()) == DRIVE_NO_ROOT_DIR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ContainsMarkerRecursive(root + L"efi\\Paravis\\Boot", L"NOT.DEL", 0)) {
|
||||||
|
g_bootRoot = root + L"efi\\Paravis\\Boot";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugLog(L"imageRoot=%s bootRoot=%s paths=%d",
|
||||||
|
g_imageRoot.c_str(), g_bootRoot.c_str(), pathCount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasEsd(const wchar_t* name)
|
||||||
|
{
|
||||||
|
return FileExists(g_imageRoot + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring UnattendArgument(const wchar_t* file)
|
||||||
|
{
|
||||||
|
std::wstring path = g_imageRoot + L"autounattend\\" + file;
|
||||||
|
if (FileExists(path)) {
|
||||||
|
return L" /unattend:" + path;
|
||||||
|
}
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring SetupCommand(const wchar_t* esd, const wchar_t* oem,
|
||||||
|
const wchar_t* unattend)
|
||||||
|
{
|
||||||
|
std::wstring command = L"X:\\sources\\setup.exe /installfrom:" +
|
||||||
|
g_imageRoot + esd + L" /m:" + g_imageRoot + oem;
|
||||||
|
command += UnattendArgument(unattend);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring TotalCmdCommand()
|
||||||
|
{
|
||||||
|
const wchar_t* exe = g_is64 ? L"TOTALCMD64.EXE" : L"TOTALCMD.EXE";
|
||||||
|
return g_bootRoot + L"\\TotalCommander\\" + exe +
|
||||||
|
L" /I=\"%%COMMANDER_PATH%%\\tcmdmain.ini\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunInstallerCommand(const std::wstring& command)
|
||||||
|
{
|
||||||
|
DebugLog(L"run: %s", command.c_str());
|
||||||
|
g_busy = true;
|
||||||
|
ShowWindow(g_mainHwnd, SW_HIDE);
|
||||||
|
RunWait(command, false);
|
||||||
|
ShowWindow(g_mainHwnd, SW_SHOW);
|
||||||
|
SetWindowPos(g_mainHwnd, HWND_TOPMOST, 0, 0, 0, 0,
|
||||||
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
|
||||||
|
g_busy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleButton(int id)
|
||||||
|
{
|
||||||
|
if (g_busy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ButtonDef* selected = nullptr;
|
||||||
|
for (const ButtonDef& button : g_buttons) {
|
||||||
|
if (button.id == id) {
|
||||||
|
selected = &button;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!selected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (selected->action) {
|
||||||
|
case Action::Win11:
|
||||||
|
RunInstallerCommand(SetupCommand(L"install_11.esd", L"$OEM11$",
|
||||||
|
L"unattend11.xml"));
|
||||||
|
break;
|
||||||
|
case Action::Win10x64:
|
||||||
|
RunInstallerCommand(SetupCommand(L"install_10_x64.esd", L"$OEM10x64$",
|
||||||
|
L"unattend10x64.xml"));
|
||||||
|
break;
|
||||||
|
case Action::Win7x64:
|
||||||
|
RunInstallerCommand(SetupCommand(L"install_7_x64.esd", L"$OEM7x64$",
|
||||||
|
L"unattend7x64.xml"));
|
||||||
|
break;
|
||||||
|
case Action::Win10x86:
|
||||||
|
RunInstallerCommand(SetupCommand(L"install_10_x86.esd", L"$OEM10x86$",
|
||||||
|
L"unattend10x86.xml"));
|
||||||
|
break;
|
||||||
|
case Action::Win7x86:
|
||||||
|
RunInstallerCommand(SetupCommand(L"install_7_x86.esd", L"$OEM7x86$",
|
||||||
|
L"unattend7x86.xml"));
|
||||||
|
break;
|
||||||
|
case Action::TotalCmd64:
|
||||||
|
case Action::TotalCmd86:
|
||||||
|
RunInstallerCommand(TotalCmdCommand());
|
||||||
|
break;
|
||||||
|
case Action::Reboot:
|
||||||
|
ExitProcess(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildButtonDefs()
|
||||||
|
{
|
||||||
|
g_buttons.clear();
|
||||||
|
int id = 1001;
|
||||||
|
|
||||||
|
if (g_is64) {
|
||||||
|
g_buttons.push_back({ id++, L"Установить Windows 11", 5, Action::Win11,
|
||||||
|
g_preview || HasEsd(L"install_11.esd") });
|
||||||
|
g_buttons.push_back({ id++, L"Установить Windows 10", 45, Action::Win10x64,
|
||||||
|
g_preview || HasEsd(L"install_10_x64.esd") });
|
||||||
|
g_buttons.push_back({ id++, L"Установить Windows 7", 85, Action::Win7x64,
|
||||||
|
g_preview || HasEsd(L"install_7_x64.esd") });
|
||||||
|
g_buttons.push_back({ id++, L"Total Commander", 145, Action::TotalCmd64, true });
|
||||||
|
g_buttons.push_back({ id++, L"Перезагрузка", 185, Action::Reboot, true });
|
||||||
|
} else if (g_x86Legacy) {
|
||||||
|
g_buttons.push_back({ id++, L"Установить Windows 10", 5, Action::Win10x86,
|
||||||
|
g_preview || HasEsd(L"install_10_x86.esd") });
|
||||||
|
g_buttons.push_back({ id++, L"Установить Windows 7", 45, Action::Win7x86,
|
||||||
|
g_preview || HasEsd(L"install_7_x86.esd") });
|
||||||
|
g_buttons.push_back({ id++, L"Total Commander", 105, Action::TotalCmd86, true });
|
||||||
|
g_buttons.push_back({ id++, L"Перезагрузка", 145, Action::Reboot, true });
|
||||||
|
} else {
|
||||||
|
g_buttons.push_back({ id++, L"Установить Windows 10", 5, Action::Win10x86, true });
|
||||||
|
g_buttons.push_back({ id++, L"Total Commander", 65, Action::TotalCmd86, true });
|
||||||
|
g_buttons.push_back({ id++, L"Перезагрузка", 105, Action::Reboot, true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateMainWindow()
|
||||||
|
{
|
||||||
|
int width = (g_is64 || g_x86Legacy) ? 410 : 360;
|
||||||
|
int height = (g_is64 || g_x86Legacy) ? 250 : 190;
|
||||||
|
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
int x = (screenWidth - width) / 2;
|
||||||
|
int y = (screenHeight - height) / 2;
|
||||||
|
|
||||||
|
if (g_preview && width == 410) {
|
||||||
|
x = 307;
|
||||||
|
y = 259;
|
||||||
|
}
|
||||||
|
|
||||||
|
HDC screen = GetDC(nullptr);
|
||||||
|
int dpi = GetDeviceCaps(screen, LOGPIXELSY);
|
||||||
|
ReleaseDC(nullptr, screen);
|
||||||
|
if (dpi <= 0) {
|
||||||
|
dpi = 96;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fontHeight = -(13 * dpi / 72);
|
||||||
|
g_buttonFont = CreateFontW(fontHeight, 0, 0, 0, 500, FALSE, FALSE, FALSE,
|
||||||
|
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||||
|
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||||
|
DEFAULT_PITCH | FF_DONTCARE, g_fontFace.c_str());
|
||||||
|
|
||||||
|
g_mainHwnd = CreateWindowExW(
|
||||||
|
WS_EX_LAYERED, kMainClass, L"Windows Setup by Paravis",
|
||||||
|
WS_POPUP | WS_CLIPCHILDREN, x, y, width, height,
|
||||||
|
nullptr, nullptr, g_hInst, nullptr);
|
||||||
|
if (!g_mainHwnd) {
|
||||||
|
DebugLog(L"main window creation failed error=%lu", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLayeredWindowAttributes(g_mainHwnd, CLR_KEY, 0, LWA_COLORKEY);
|
||||||
|
|
||||||
|
for (const ButtonDef& button : g_buttons) {
|
||||||
|
HWND control = CreateWindowExW(
|
||||||
|
0, L"BUTTON", button.text.c_str(),
|
||||||
|
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
|
||||||
|
5, button.y, 350, 40,
|
||||||
|
g_mainHwnd, reinterpret_cast<HMENU>(static_cast<INT_PTR>(button.id)),
|
||||||
|
g_hInst, nullptr);
|
||||||
|
if (!control) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (g_buttonFont) {
|
||||||
|
SendMessageW(control, WM_SETFONT,
|
||||||
|
reinterpret_cast<WPARAM>(g_buttonFont), TRUE);
|
||||||
|
}
|
||||||
|
if (!button.enabled) {
|
||||||
|
EnableWindow(control, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(g_mainHwnd, HWND_TOPMOST, x, y, width, height, SWP_SHOWWINDOW);
|
||||||
|
UpdateWindow(g_mainHwnd);
|
||||||
|
SetForegroundWindow(g_mainHwnd);
|
||||||
|
DebugLog(L"main window %dx%d at %d,%d buttons=%zu", width, height, x, y,
|
||||||
|
g_buttons.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateWallpaperWindow()
|
||||||
|
{
|
||||||
|
int width = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
int height = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
DWORD exStyle = WS_EX_TOOLWINDOW;
|
||||||
|
|
||||||
|
if (g_preview) {
|
||||||
|
width = 1024;
|
||||||
|
height = 768;
|
||||||
|
exStyle |= WS_EX_TOPMOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_wallHwnd = CreateWindowExW(
|
||||||
|
exStyle, kWallClass, L"", WS_POPUP,
|
||||||
|
0, 0, width, height, nullptr, nullptr, g_hInst, nullptr);
|
||||||
|
if (!g_wallHwnd) {
|
||||||
|
DebugLog(L"wallpaper window creation failed error=%lu", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowWindow(g_wallHwnd, SW_SHOWNOACTIVATE);
|
||||||
|
UpdateWindow(g_wallHwnd);
|
||||||
|
DebugLog(L"wallpaper window %dx%d", width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK MainProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (message) {
|
||||||
|
case WM_ERASEBKGND: {
|
||||||
|
HDC dc = reinterpret_cast<HDC>(wParam);
|
||||||
|
RECT rect{};
|
||||||
|
GetClientRect(hwnd, &rect);
|
||||||
|
FillRectColor(dc, rect, CLR_KEY);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
case WM_COMMAND:
|
||||||
|
if (HIWORD(wParam) == BN_CLICKED) {
|
||||||
|
HandleButton(LOWORD(wParam));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case WM_CLOSE:
|
||||||
|
return 0;
|
||||||
|
case WM_DESTROY:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProcW(hwnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int)
|
||||||
|
{
|
||||||
|
g_hInst = hInstance;
|
||||||
|
g_preview = HasPreviewArg();
|
||||||
|
|
||||||
|
Gdiplus::GdiplusStartupInput gdiplusInput;
|
||||||
|
g_gdiplusStarted =
|
||||||
|
Gdiplus::GdiplusStartup(&g_gdiplusToken, &gdiplusInput, nullptr) ==
|
||||||
|
Gdiplus::Ok;
|
||||||
|
|
||||||
|
g_keyBrush = CreateSolidBrush(CLR_KEY);
|
||||||
|
|
||||||
|
WNDCLASSEXW wallpaperClass{};
|
||||||
|
wallpaperClass.cbSize = sizeof(wallpaperClass);
|
||||||
|
wallpaperClass.lpfnWndProc = WallpaperProc;
|
||||||
|
wallpaperClass.hInstance = hInstance;
|
||||||
|
wallpaperClass.hCursor = LoadCursorW(nullptr, IDC_ARROW);
|
||||||
|
wallpaperClass.lpszClassName = kWallClass;
|
||||||
|
wallpaperClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
|
||||||
|
if (!RegisterClassExW(&wallpaperClass)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
WNDCLASSEXW mainClass{};
|
||||||
|
mainClass.cbSize = sizeof(mainClass);
|
||||||
|
mainClass.lpfnWndProc = MainProc;
|
||||||
|
mainClass.hInstance = hInstance;
|
||||||
|
mainClass.hCursor = LoadCursorW(nullptr, IDC_ARROW);
|
||||||
|
mainClass.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_APP));
|
||||||
|
mainClass.hIconSm = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_APP));
|
||||||
|
mainClass.lpszClassName = kMainClass;
|
||||||
|
mainClass.hbrBackground = g_keyBrush;
|
||||||
|
if (!RegisterClassExW(&mainClass)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_fontFace = LoadFonts();
|
||||||
|
LoadWallpaper();
|
||||||
|
CreateWallpaperWindow();
|
||||||
|
|
||||||
|
if (!SearchPaths()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_is64 = DirectoryExists(GetWindowsDir() + L"\\SYSWOW64");
|
||||||
|
std::wstring firmware = FirmwareType();
|
||||||
|
g_x86Legacy = !g_is64 && _wcsicmp(firmware.c_str(), L"Legacy") == 0;
|
||||||
|
DebugLog(L"is64=%d firmware=%s legacy86=%d", g_is64 ? 1 : 0,
|
||||||
|
firmware.c_str(), g_x86Legacy ? 1 : 0);
|
||||||
|
|
||||||
|
if (!g_preview && !g_bootRoot.empty()) {
|
||||||
|
std::wstring source = g_bootRoot +
|
||||||
|
(g_is64 ? L"\\src_x64.exe" : L"\\src_x86.exe");
|
||||||
|
if (FileExists(source)) {
|
||||||
|
DebugLog(L"running source helper: %s auto2", source.c_str());
|
||||||
|
RunWait(source + L" auto2", false);
|
||||||
|
} else {
|
||||||
|
DebugLog(L"source helper not found: %s", source.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_is64 && !g_x86Legacy) {
|
||||||
|
if (!FileExists(g_imageRoot + L"install_10_x86.esd")) {
|
||||||
|
ShowWarning(L"Не найден образ Windows 10 x86. "
|
||||||
|
L"Система будет перезагружена.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildButtonDefs();
|
||||||
|
CreateMainWindow();
|
||||||
|
if (!g_mainHwnd) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MSG message{};
|
||||||
|
while (GetMessageW(&message, nullptr, 0, 0) > 0) {
|
||||||
|
TranslateMessage(&message);
|
||||||
|
DispatchMessageW(&message);
|
||||||
|
}
|
||||||
|
if (g_gdiplusStarted) {
|
||||||
|
Gdiplus::GdiplusShutdown(g_gdiplusToken);
|
||||||
|
}
|
||||||
|
return static_cast<int>(message.wParam);
|
||||||
|
}
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
std::wstring Format(const wchar_t* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
va_list copy;
|
||||||
|
va_copy(copy, args);
|
||||||
|
int needed = _vscwprintf(fmt, copy);
|
||||||
|
va_end(copy);
|
||||||
|
|
||||||
|
if (needed < 0) {
|
||||||
|
va_end(args);
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring result(static_cast<size_t>(needed), L'\0');
|
||||||
|
if (needed > 0) {
|
||||||
|
_vsnwprintf_s(result.data(), result.size() + 1, _TRUNCATE, fmt, args);
|
||||||
|
}
|
||||||
|
va_end(args);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring GetExeDir()
|
||||||
|
{
|
||||||
|
wchar_t buffer[MAX_PATH * 4] = {};
|
||||||
|
DWORD length = GetModuleFileNameW(nullptr, buffer, static_cast<DWORD>(std::size(buffer)));
|
||||||
|
if (length == 0) {
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
std::wstring path(buffer, length);
|
||||||
|
size_t slash = path.find_last_of(L"\\/");
|
||||||
|
if (slash != std::wstring::npos) {
|
||||||
|
path.resize(slash);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring GetExeFileName()
|
||||||
|
{
|
||||||
|
wchar_t buffer[MAX_PATH * 4] = {};
|
||||||
|
DWORD length = GetModuleFileNameW(nullptr, buffer, static_cast<DWORD>(std::size(buffer)));
|
||||||
|
if (length == 0) {
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
std::wstring path(buffer, length);
|
||||||
|
size_t slash = path.find_last_of(L"\\/");
|
||||||
|
if (slash != std::wstring::npos) {
|
||||||
|
path = path.substr(slash + 1);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring GetWindowsDir()
|
||||||
|
{
|
||||||
|
wchar_t buffer[MAX_PATH] = {};
|
||||||
|
UINT length = GetWindowsDirectoryW(buffer, MAX_PATH);
|
||||||
|
if (length == 0) {
|
||||||
|
return L"C:\\Windows";
|
||||||
|
}
|
||||||
|
return std::wstring(buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring GetTempDir()
|
||||||
|
{
|
||||||
|
wchar_t buffer[MAX_PATH + 1] = {};
|
||||||
|
DWORD length = GetTempPathW(MAX_PATH, buffer);
|
||||||
|
if (length == 0 || length >= MAX_PATH) {
|
||||||
|
wchar_t windows[MAX_PATH] = {};
|
||||||
|
GetWindowsDirectoryW(windows, MAX_PATH);
|
||||||
|
return std::wstring(windows) + L"\\Temp\\";
|
||||||
|
}
|
||||||
|
std::wstring path(buffer, length);
|
||||||
|
if (path.empty() || path.back() != L'\\') {
|
||||||
|
path.push_back(L'\\');
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileExists(const std::wstring& path)
|
||||||
|
{
|
||||||
|
DWORD attributes = GetFileAttributesW(path.c_str());
|
||||||
|
return attributes != INVALID_FILE_ATTRIBUTES &&
|
||||||
|
(attributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DirectoryExists(const std::wstring& path)
|
||||||
|
{
|
||||||
|
DWORD attributes = GetFileAttributesW(path.c_str());
|
||||||
|
return attributes != INVALID_FILE_ATTRIBUTES &&
|
||||||
|
(attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtractResourceToFile(HINSTANCE instance, int resourceId, const wchar_t* type,
|
||||||
|
const std::wstring& path)
|
||||||
|
{
|
||||||
|
HRSRC resource = FindResourceW(instance, MAKEINTRESOURCEW(resourceId), type);
|
||||||
|
if (!resource) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DWORD size = SizeofResource(instance, resource);
|
||||||
|
HGLOBAL loaded = LoadResource(instance, resource);
|
||||||
|
if (!loaded) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const void* data = LockResource(loaded);
|
||||||
|
if (!data || size == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE file = CreateFileW(path.c_str(), GENERIC_WRITE, 0, nullptr,
|
||||||
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (file == INVALID_HANDLE_VALUE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DWORD written = 0;
|
||||||
|
bool ok = WriteFile(file, data, size, &written, nullptr) != FALSE && written == size;
|
||||||
|
CloseHandle(file);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PumpMessages()
|
||||||
|
{
|
||||||
|
MSG message{};
|
||||||
|
while (PeekMessageW(&message, nullptr, 0, 0, PM_REMOVE)) {
|
||||||
|
if (message.message == WM_QUIT) {
|
||||||
|
PostQuitMessage(static_cast<int>(message.wParam));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TranslateMessage(&message);
|
||||||
|
DispatchMessageW(&message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int RunWait(const std::wstring& commandLine, bool hidden)
|
||||||
|
{
|
||||||
|
STARTUPINFOW startup{};
|
||||||
|
startup.cb = sizeof(startup);
|
||||||
|
DWORD creationFlags = 0;
|
||||||
|
if (hidden) {
|
||||||
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
||||||
|
startup.wShowWindow = SW_HIDE;
|
||||||
|
creationFlags = CREATE_NO_WINDOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROCESS_INFORMATION process{};
|
||||||
|
std::vector<wchar_t> buffer(commandLine.begin(), commandLine.end());
|
||||||
|
buffer.push_back(L'\0');
|
||||||
|
|
||||||
|
if (!CreateProcessW(nullptr, buffer.data(), nullptr, nullptr, FALSE,
|
||||||
|
creationFlags, nullptr, nullptr, &startup, &process)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(process.hThread);
|
||||||
|
for (;;) {
|
||||||
|
DWORD result = MsgWaitForMultipleObjects(1, &process.hProcess, FALSE,
|
||||||
|
30, QS_ALLINPUT);
|
||||||
|
if (result == WAIT_OBJECT_0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PumpMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD exitCode = 1;
|
||||||
|
GetExitCodeProcess(process.hProcess, &exitCode);
|
||||||
|
CloseHandle(process.hProcess);
|
||||||
|
return static_cast<int>(exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
COLORREF ColorFromHex(DWORD rgb)
|
||||||
|
{
|
||||||
|
return RGB((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugLog(const wchar_t* fmt, ...)
|
||||||
|
{
|
||||||
|
wchar_t enabled[8] = {};
|
||||||
|
if (GetEnvironmentVariableW(L"PARAVIS_DEBUG_LOG", enabled,
|
||||||
|
static_cast<DWORD>(std::size(enabled))) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
wchar_t message[4096] = {};
|
||||||
|
_vsnwprintf_s(message, std::size(message), _TRUNCATE, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
SYSTEMTIME st{};
|
||||||
|
GetLocalTime(&st);
|
||||||
|
std::wstring line = Format(L"%02d:%02d:%02d.%03d [%lu] %s\r\n",
|
||||||
|
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
|
||||||
|
GetCurrentThreadId(), message);
|
||||||
|
|
||||||
|
wchar_t temp[MAX_PATH] = {};
|
||||||
|
DWORD length = GetTempPathW(MAX_PATH, temp);
|
||||||
|
std::wstring path;
|
||||||
|
if (length > 0) {
|
||||||
|
path.assign(temp, length);
|
||||||
|
}
|
||||||
|
path += L"winsetup_cpp_debug.log";
|
||||||
|
|
||||||
|
int needed = WideCharToMultiByte(CP_UTF8, 0, line.c_str(),
|
||||||
|
static_cast<int>(line.size()), nullptr, 0,
|
||||||
|
nullptr, nullptr);
|
||||||
|
if (needed > 0) {
|
||||||
|
std::string bytes(static_cast<size_t>(needed), '\0');
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, line.c_str(),
|
||||||
|
static_cast<int>(line.size()), bytes.data(), needed,
|
||||||
|
nullptr, nullptr);
|
||||||
|
HANDLE file = CreateFileW(path.c_str(), FILE_APPEND_DATA,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||||
|
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (file != INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD written = 0;
|
||||||
|
WriteFile(file, bytes.data(), static_cast<DWORD>(bytes.size()),
|
||||||
|
&written, nullptr);
|
||||||
|
CloseHandle(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::wstring Format(const wchar_t* fmt, ...);
|
||||||
|
std::wstring GetExeDir();
|
||||||
|
std::wstring GetExeFileName();
|
||||||
|
std::wstring GetWindowsDir();
|
||||||
|
std::wstring GetTempDir();
|
||||||
|
bool FileExists(const std::wstring& path);
|
||||||
|
bool DirectoryExists(const std::wstring& path);
|
||||||
|
bool ExtractResourceToFile(HINSTANCE instance, int resourceId, const wchar_t* type,
|
||||||
|
const std::wstring& path);
|
||||||
|
int RunWait(const std::wstring& commandLine, bool hidden = false);
|
||||||
|
void PumpMessages();
|
||||||
|
COLORREF ColorFromHex(DWORD rgb);
|
||||||
|
void DebugLog(const wchar_t* fmt, ...);
|
||||||