Extract WindowsESD.pf separately
This commit is contained in:
1 parent
a69409e526
commit
3c807fbcf2
6 files changed
+129
-46
No files matched your search
@@ -34,8 +34,12 @@ build\Release\ParavisInstaller.exe
|
||||
и защита системного диска Windows.
|
||||
- Разметка через diskpart: FAT32 `PARAVIS` 16 ГБ, FAT `VTOYEFI` 32 МБ,
|
||||
exFAT `DATA` (оставшийся объём).
|
||||
- Галочка «Не копировать Windows ESD» (по умолчанию снята): если включить,
|
||||
папка `WindowsESD` копируется, но файлы `*.esd` из неё удаляются с DATA.
|
||||
- Если рядом с установщиком есть `WindowsESD.pf`, после `Data.pf` он
|
||||
распаковывается на раздел DATA (статус «Распаковка Windows ESD»).
|
||||
- Галочка «Не копировать Windows ESD» (по умолчанию снята) пропускает
|
||||
распаковку `WindowsESD.pf`. Если файла нет, галочка неактивна и
|
||||
распаковка пропускается; если файл не является WIM — ошибка
|
||||
«WindowsESD.pf повреждён».
|
||||
- Отключённый диск переводится в онлайн перед разметкой.
|
||||
- Проверка разметки по таблице разделов и меткам томов.
|
||||
- Распаковка DISM: образ 1 → `PARAVIS`, 2 → `VTOYEFI`, 3 → `DATA`, с
|
||||
|
||||
@@ -78,6 +78,8 @@ public:
|
||||
std::wstring sig = L"-";
|
||||
std::wstring runStamp;
|
||||
std::wstring wimPath;
|
||||
std::wstring esdPfPath;
|
||||
bool esdPfAvailable = false;
|
||||
int testDisk = -1;
|
||||
std::wstring workText;
|
||||
std::wstring labelText = L"Выбран накопитель:";
|
||||
@@ -122,6 +124,7 @@ public:
|
||||
void CheckInstalled();
|
||||
void Apply();
|
||||
int ApplyImages(int disk, const std::wstring& wim);
|
||||
int ApplyWindowsEsd(int disk);
|
||||
bool DismApply(const std::wstring& wim, int index, const std::wstring& dir,
|
||||
const std::wstring& caption);
|
||||
int RunCmd(const std::wstring& commandLine, const std::wstring& caption);
|
||||
|
||||
+81
-37
@@ -6,7 +6,6 @@
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cwchar>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -214,6 +213,12 @@ void App::Apply()
|
||||
return;
|
||||
}
|
||||
|
||||
if (esdPfAvailable && !IsWimFile(esdPfPath)) {
|
||||
ShowMessage(MB_ICONERROR | MB_OK, L"WindowsESD.pf повреждён",
|
||||
L"Файл WindowsESD.pf не является WIM-архивом:\r\n" + esdPfPath);
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring message =
|
||||
Format(L"Накопитель (%.1f ГБ)\r\n\r\n",
|
||||
static_cast<double>(sizeBytes) / 1073741824.0);
|
||||
@@ -224,9 +229,14 @@ void App::Apply()
|
||||
static_cast<double>(p3) / 1024.0);
|
||||
message += L"Затем на разделы будут распакованы файлы из архива Data.pf\r\n";
|
||||
message += L"(1 -> PARAVIS, 2 -> VTOYEFI, 3 -> DATA).\r\n\r\n";
|
||||
if (noEsd) {
|
||||
message += L"Файлы *.esd из папки WindowsESD копироваться не будут\r\n";
|
||||
message += L"(остальные файлы папки будут скопированы).\r\n\r\n";
|
||||
if (esdPfAvailable) {
|
||||
if (noEsd) {
|
||||
message += L"WindowsESD.pf распаковываться не будет.\r\n\r\n";
|
||||
} else {
|
||||
message += L"После Data.pf будет распакован WindowsESD.pf.\r\n\r\n";
|
||||
}
|
||||
} else {
|
||||
message += L"WindowsESD.pf не найден - Windows ESD не будет распакован.\r\n\r\n";
|
||||
}
|
||||
message += L"ВНИМАНИЕ! ВСЕ ДАННЫЕ НА ЭТОМ ДИСКЕ БУДУТ УНИЧТОЖЕНЫ.\r\n";
|
||||
message += L"Продолжить?";
|
||||
@@ -341,6 +351,30 @@ void App::Apply()
|
||||
DebugLog(L"ApplyImages result=%d applied=%d cancel=%d", result, applied, cancel ? 1 : 0);
|
||||
|
||||
if (result == 1) {
|
||||
if (!noEsd && esdPfAvailable) {
|
||||
int esdResult = ApplyWindowsEsd(disk);
|
||||
if (esdResult == 3) {
|
||||
SetWork(L"Отменено");
|
||||
HideProgress();
|
||||
BusySet(false);
|
||||
HideProgress();
|
||||
ShowMessage(MB_ICONINFORMATION | MB_OK, L"Отменено",
|
||||
L"Операция отменена пользователем.\r\n\r\n"
|
||||
L"Диск размечен, Windows ESD не распакован.");
|
||||
return;
|
||||
}
|
||||
if (esdResult == 2) {
|
||||
SetWork(L"Ошибка Windows ESD");
|
||||
HideProgress();
|
||||
ShowMessage(MB_ICONERROR | MB_OK, L"Ошибка Windows ESD",
|
||||
L"Не удалось распаковать WindowsESD.pf.\r\n\r\n"
|
||||
L"Проверьте, что файл не повреждён.");
|
||||
BusySet(false);
|
||||
HideProgress();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring first = GetPartitionLetter(disk, 0);
|
||||
DebugLog(L"partition0=%s", first.c_str());
|
||||
|
||||
@@ -456,39 +490,6 @@ int App::ApplyImages(int disk, const std::wstring& wim)
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (i == 2 && noEsd) {
|
||||
std::wstring esdDir = dir + L"WindowsESD";
|
||||
std::error_code ec;
|
||||
if (std::filesystem::exists(esdDir, ec)) {
|
||||
std::filesystem::recursive_directory_iterator it(
|
||||
esdDir, std::filesystem::directory_options::skip_permission_denied, ec);
|
||||
const std::filesystem::recursive_directory_iterator end;
|
||||
while (it != end) {
|
||||
if (ec) {
|
||||
DebugLog(L"skip ESD: scan stopped ec=%d", ec.value());
|
||||
break;
|
||||
}
|
||||
const std::filesystem::directory_entry& entry = *it;
|
||||
std::error_code fileEc;
|
||||
if (entry.is_regular_file(fileEc)) {
|
||||
std::wstring ext = entry.path().extension().wstring();
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(),
|
||||
[](wchar_t c) {
|
||||
return static_cast<wchar_t>(towlower(c));
|
||||
});
|
||||
if (ext == L".esd") {
|
||||
std::error_code removeEc;
|
||||
std::filesystem::remove(entry.path(), removeEc);
|
||||
DebugLog(L"skip ESD: %s removed=%d ec=%d",
|
||||
entry.path().c_str(),
|
||||
removeEc ? 0 : 1, removeEc.value());
|
||||
}
|
||||
}
|
||||
it.increment(ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++applied;
|
||||
|
||||
if (cancel) {
|
||||
@@ -499,6 +500,49 @@ int App::ApplyImages(int disk, const std::wstring& wim)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int App::ApplyWindowsEsd(int disk)
|
||||
{
|
||||
std::wstring dir;
|
||||
for (int attempt = 0; attempt < 15; ++attempt) {
|
||||
dir = GetPartitionLetter(disk, 2);
|
||||
if (!dir.empty()) {
|
||||
break;
|
||||
}
|
||||
SleepPump(1000);
|
||||
}
|
||||
|
||||
if (dir.empty()) {
|
||||
ShowMessage(MB_ICONERROR | MB_OK, L"Ошибка",
|
||||
L"Не удалось определить букву раздела DATA.");
|
||||
return 2;
|
||||
}
|
||||
if (cancel) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (!IsWimFile(esdPfPath)) {
|
||||
ShowMessage(MB_ICONERROR | MB_OK, L"WindowsESD.pf повреждён",
|
||||
L"Файл WindowsESD.pf не является WIM-архивом:\r\n" + esdPfPath);
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::wstring caption = L"Распаковка Windows ESD";
|
||||
DebugLog(L"ApplyWindowsEsd %s -> %s", esdPfPath.c_str(), dir.c_str());
|
||||
phase = 2;
|
||||
ShowProgress(0);
|
||||
SetWork(caption);
|
||||
|
||||
bool ok = DismApply(esdPfPath, 1, dir, caption);
|
||||
phase = 0;
|
||||
if (!ok) {
|
||||
if (cancel) {
|
||||
return 3;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool App::DismApply(const std::wstring& wim, int index, const std::wstring& dir,
|
||||
const std::wstring& caption)
|
||||
{
|
||||
|
||||
+15
-7
@@ -187,6 +187,10 @@ bool App::Init(HWND window)
|
||||
}
|
||||
CreateFonts();
|
||||
|
||||
esdPfPath = JoinPath(GetExeDir(), L"WindowsESD.pf");
|
||||
esdPfAvailable = FileExists(esdPfPath);
|
||||
DebugLog(L"WindowsESD.pf: %s available=%d", esdPfPath.c_str(), esdPfAvailable ? 1 : 0);
|
||||
|
||||
hProgress = CreateWindowExW(0, PROGRESS_CLASSW, nullptr,
|
||||
WS_CHILD | PBS_SMOOTH,
|
||||
14, 152, 348, 5,
|
||||
@@ -500,13 +504,17 @@ void App::Paint(HDC dc)
|
||||
const int cbX = 16;
|
||||
const int cbY = 114;
|
||||
const int cbSize = 14;
|
||||
FillRectColor(memory, cbX, cbY, cbSize, cbSize, RGB(255, 255, 255));
|
||||
bool checkEnabled = esdPfAvailable && !busy;
|
||||
COLORREF boxFill = checkEnabled ? RGB(255, 255, 255) : ColorFromHex(0xF2F3F5);
|
||||
COLORREF boxBorder = checkEnabled ? checkBorder : ColorFromHex(0xD5DAE3);
|
||||
COLORREF boxText = checkEnabled ? checkFg : ColorFromHex(0xA0A6B1);
|
||||
FillRectColor(memory, cbX, cbY, cbSize, cbSize, boxFill);
|
||||
RECT cbRect{ cbX, cbY, cbX + cbSize - 1, cbY + cbSize - 1 };
|
||||
HBRUSH cbBrush = CreateSolidBrush(checkBorder);
|
||||
HBRUSH cbBrush = CreateSolidBrush(boxBorder);
|
||||
FrameRect(memory, &cbRect, cbBrush);
|
||||
DeleteObject(cbBrush);
|
||||
if (noEsd) {
|
||||
COLORREF markColor = dimmed ? ColorFromHex(0xA0A6B1) : ColorFromHex(0x2563EB);
|
||||
if (noEsd && esdPfAvailable) {
|
||||
COLORREF markColor = checkEnabled ? ColorFromHex(0x2563EB) : ColorFromHex(0xA0A6B1);
|
||||
HPEN pen = CreatePen(PS_SOLID, 2, markColor);
|
||||
HGDIOBJ oldPen = SelectObject(memory, pen);
|
||||
MoveToEx(memory, cbX + 3, cbY + 7, nullptr);
|
||||
@@ -516,7 +524,7 @@ void App::Paint(HDC dc)
|
||||
DeleteObject(pen);
|
||||
}
|
||||
DrawTextRect(memory, L"Не копировать Windows ESD", fontText, 36, 112, 300, 18,
|
||||
checkFg, DT_LEFT | DT_VCENTER);
|
||||
boxText, DT_LEFT | DT_VCENTER);
|
||||
|
||||
if (busy) {
|
||||
DrawTextRect(memory, workText, fontBold, 14, 132, 348, 18,
|
||||
@@ -725,7 +733,7 @@ void App::OnPoll()
|
||||
checkDown = true;
|
||||
} else if (checkDown) {
|
||||
checkDown = false;
|
||||
if (hit == Hit::Check && !leftDown) {
|
||||
if (hit == Hit::Check && !leftDown && esdPfAvailable) {
|
||||
noEsd = !noEsd;
|
||||
DebugLog(L"checkbox noEsd=%d", noEsd ? 1 : 0);
|
||||
InvalidateAll();
|
||||
@@ -799,7 +807,7 @@ void App::OnPoll()
|
||||
(hit == Hit::Combo || hit == Hit::Drop || hit == Hit::DropName ||
|
||||
hit == Hit::DropSize || hit == Hit::Arrow);
|
||||
comboFrame = comboHover ? ColorFromHex(0x7FA6F0) : ColorFromHex(0xD5DAE3);
|
||||
checkBorder = (hit == Hit::Check) ? ColorFromHex(0x7FA6F0) : ColorFromHex(0x9AA3B2);
|
||||
checkBorder = (esdPfAvailable && hit == Hit::Check) ? ColorFromHex(0x7FA6F0) : ColorFromHex(0x9AA3B2);
|
||||
|
||||
if (!disks.empty() &&
|
||||
(hit == Hit::Drop || hit == Hit::Arrow || hit == Hit::DropName ||
|
||||
|
||||
@@ -82,6 +82,29 @@ bool FileExists(const std::wstring& path)
|
||||
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
|
||||
}
|
||||
|
||||
bool IsWimFile(const std::wstring& path)
|
||||
{
|
||||
HANDLE file = CreateFileW(path.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, 0, nullptr);
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char signature[8] = {};
|
||||
DWORD read = 0;
|
||||
BOOL ok = ReadFile(file, signature, sizeof(signature), &read, nullptr);
|
||||
CloseHandle(file);
|
||||
if (!ok || read != sizeof(signature)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return signature[0] == 'M' && signature[1] == 'S' &&
|
||||
signature[2] == 'W' && signature[3] == 'I' &&
|
||||
signature[4] == 'M' && signature[5] == 0 &&
|
||||
signature[6] == 0 && signature[7] == 0;
|
||||
}
|
||||
|
||||
bool IsAdmin()
|
||||
{
|
||||
HANDLE token = nullptr;
|
||||
|
||||
@@ -10,6 +10,7 @@ std::wstring GetExeDir();
|
||||
std::wstring GetRunStamp();
|
||||
std::wstring JoinPath(const std::wstring& dir, const std::wstring& name);
|
||||
bool FileExists(const std::wstring& path);
|
||||
bool IsWimFile(const std::wstring& path);
|
||||
bool IsAdmin();
|
||||
std::string WideToAnsi(const std::wstring& text, UINT codepage = CP_ACP);
|
||||
std::wstring AnsiToWide(const std::string& text, UINT codepage = CP_ACP);
|
||||
|
||||
Reference in new issue
Block a user