Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ jobs:
shell: pwsh
run: .\scripts\build.ps1 -Configuration Release

- name: Upload portable executable
- name: Upload Legacy portable executable
uses: actions/upload-artifact@v4
with:
name: CryptoProCleanup-win32-${{ github.sha }}
path: build/Release/CryptoProCleanup.exe
name: CryptoProCleanup-Legacy-x86-${{ github.sha }}
path: build/Win32/Release/CryptoProCleanupLegacy.exe
if-no-files-found: error
retention-days: 14
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ build/
dist/
Debug/
Release/
packages/
artifacts/
.referer/
Generated Files/
obj/
*.obj
*.pdb
*.idb
Expand Down
384 changes: 384 additions & 0 deletions App.xaml

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions App.xaml.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "pch.h"
#include "App.xaml.h"
#include "MainWindow.xaml.h"
#include "src/cleanup.hpp"

#include <shellapi.h>
#include <sstream>

namespace winrt::CryptoProCleanupModern::implementation
{
App::App()
{
}

void App::OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&)
{
int argc = 0;
wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
const cpc::CommandLineOptions options = cpc::ParseCommandLine(argc, argv);
if (argv) LocalFree(argv);

if (options.showHelp)
{
const std::wstring heading = std::wstring(L"CryptoPro Cleanup Utility ") + cpc::kVersion + L"\r\n\r\n";
MessageBoxW(nullptr,
(heading +
L"--scan Safe scan only\r\n"
L"--offline-scan <path> Safe disconnected-Windows scan\r\n"
L"--report <path> Report path\r\n"
L"--lang ru|en Interface/report language\r\n"
L"--resume <token> Internal restart continuation").c_str(),
L"CryptoPro Cleanup Utility", MB_OK | MB_ICONINFORMATION);
ExitProcess(0);
}
if (!options.offlineWindowsPath.empty()) ExitProcess(cpc::RunOfflineScanCommand(options));
if (options.scanOnly) ExitProcess(cpc::RunScanCommand(options));
// A resumed cleanup is an exact residual pass over the protected state.
// It must never fall through to the normal uninstaller confirmation UI.
if (!options.resumeToken.empty()) ExitProcess(cpc::RunResumeCommand(options.resumeToken, true));

try
{
auto mainWindow = winrt::make_self<MainWindow>();
mainWindow->InitializeSession(options.language, {}, options.languageExplicit);
window = *mainWindow;
window.Activate();
}
catch (winrt::hresult_error const& error)
{
const std::wstring detail = std::wstring(L"Modern UI initialization failed (0x") +
[&]() { std::wostringstream value; value << std::hex << static_cast<unsigned long>(error.code().value); return value.str(); }() +
L"): " + std::wstring(error.message().c_str());
OutputDebugStringW((detail + L"\r\n").c_str());
MessageBoxW(nullptr, detail.c_str(), L"CryptoPro Cleanup Utility", MB_OK | MB_ICONERROR);
}
}
}
16 changes: 16 additions & 0 deletions App.xaml.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "App.xaml.g.h"
#include "pch.h"

namespace winrt::CryptoProCleanupModern::implementation
{
struct App : AppT<App>
{
App();
void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&);

private:
Microsoft::UI::Xaml::Window window{nullptr};
};
}
75 changes: 75 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,81 @@

All notable project changes are documented here. The project follows semantic versioning after the first generally available release.

## [0.5.3-rc1] - 2026-08-21

### Changed

- Introduced shared spacing tokens and semantic content, statistic, table, callout, and navigation card styles across Modern; product and offline-result rows now use dedicated table insets instead of accumulated per-card padding.
- Restored the studio accent palette and fixed button label inheritance in Dark, Light, System, and High Contrast resources.
- Made the page header, backup selector, certificate toolbar, offline selector, Settings rows, Reports actions, About actions, and dialogs adapt to narrow windows without truncating known RU/EN labels.
- Added a dedicated Legacy low-resolution layout: the minimum window is now 640×480, all six navigation entries and page actions remain visible at 800×600/1024×768, and the effective 768×528 work-area layout compacts tables, settings, reports, About links, and Offline Windows controls without overlapping buttons.
- Replaced generic completion text with operation-specific semantic states and preserved the originating operation when asynchronous failures are reported.
- Split backup validation into side-effect-free inspection and a debounced background write probe. The UI now shows free and required space; advanced offline cleanup estimates complete hive and verified quarantine-copy size with a safety margin.
- Kept invalid offline diagnostics accessible, invalidated product-set confirmation on every selection change, corrected live/offline license-dialog context, and made cleanup-result wording explicitly conservative.
- Reports now use actual stage outcomes, compact safe-scan summaries, an optional technical log, complete session-file discovery, and a warning before confidential files are opened.
- Theme refresh updates runtime rows and badges in place without rebuilding their models, selections, or handlers. Dead retained execution state was removed.
- Fixed stale Light-theme brushes on the compact Modern navigation rail: Dark now refreshes every button background, selected state, border, and icon foreground after startup and every theme change.

### Safety and validation

- Added static layout-resource checks and expanded safe native tests for no-side-effect backup inspection, path ancestry, write-probe cleanup, offline space estimation, and `NotBuilt`/`Ready`/`Stale` plan state.
- Modern UI automation now samples compact-navigation pixels in Dark theme and fails if a button keeps a light background or its symbol loses contrast.
- Local Release Win32 Legacy and x64 Modern builds, native x86/x64 unit tests, theme/layout checks, and non-destructive UI automation passed. Modern screenshots cover 1024×760 and 1280×720; Legacy screenshots cover 800×600, 1024×768, and a simulated 768×528 work area at the development system's 100% DPI. OS-level High Contrast and 125–200% DPI sessions were not executed.
- No destructive CryptoPro cleanup, offline-disk write, real RunOnce registration, reboot, or live resume execution was performed during 0.5.3-rc1 validation.

## [0.5.2-dev] - 2026-08-21

### Changed

- Replaced the forced-dark Modern theme with matching Dark, Light, and High Contrast resource dictionaries; System follows Windows at runtime, including dialogs and title bar.
- Added generation-bound asynchronous operations, semantic status preservation, complete plan-input revisions, selected-only plan counts, detailed target categories, and stricter conflict gating.
- Bound every offline result to its scanned path, added explicit product-set confirmation, richer certificate selection/diagnostics, another-volume backup validation, and correct offline redaction context.
- Hardened FORCE/resume authorization, transactional helper deployment, runner identity/hash validation, bounded retries, and retained failed state for manual inspection.
- Added real certificate-date sorting and status filters, filtered-only bulk selection, keyboard/UI Automation rows, session-specific Reports actions/timeline, emergency redacted logs, and executable signature/SHA-256 inspection in About.
- Window placement is monitor-validated and bounded; reduced motion now also honors the Windows animation setting.

### Safety and validation

- Added a theme-resource consistency checker to every local build and expanded non-destructive unit tests for operation generations, plan revisions, redaction boundaries, backup validation, certificate sorting/selection, FORCE authorization, and tampered resume helpers.
- No destructive cleanup, real RunOnce registration, reboot, or live resume execution was performed during 0.5.2-dev development validation.

## [0.5.1-dev] - 2026-08-21

### Changed

- Stabilized the Modern x64 operation model with one explicit state gate, scan/selection plan revisions, blocked overlapping commands, and guarded window closing.
- Restored the full uninstall-first workflow in Modern: mandatory backup, registered MSI/EXE pass, exact `FORCE` confirmation after uninstaller failure, verified residual pass, verification, redacted logs, and structured reports.
- Added a compact native x64 `CryptoProCleanupResume.exe`. Its protected versioned state contains only the preverified residual plan; the helper never reruns registered uninstallers and never restarts Windows.
- Expanded disconnected-Windows selection, diagnostics, certificate choices, exact `OFFLINE` confirmation, recovery-backed result logging, and post-cleanup rescan.
- Added persisted Modern settings, dark title-bar integration, certificate validity/sort/bulk filters, a searchable categorized plan inspector, and a structured Reports page.

### Safety and validation

- Added isolated tests for operation gating, plan revisions, exact confirmation phrases, execution-result merging, sensitive log redaction, and resume state/runner/load/cleanup without RunOnce or HKLM writes.
- Local Release Win32/x64 builds and non-destructive tests are required by the package script. No destructive CryptoPro, offline-disk, RunOnce, or reboot test is performed on the development machine.

## [0.5.0-dev] - 2026-08-20

### Added

- Separate native C++/WinUI 3 x64 application for Windows 10/11, closely following the supplied dark Fluent mockups; the Windows 7-compatible x86 Win32 edition remains available as Legacy.
- Sidebar navigation, overview/status cards, dedicated certificate, Offline Windows, reports, settings, and about pages, typed destructive confirmations, and a read-only cleanup-plan inspector.
- Responsive layout that collapses the sidebar and stacks cards/details as the window narrows, while retaining native DPI scaling and keyboard-accessible controls.
- Confidential full-license dialog with copy support for both the running and offline Windows scans. Full values remain excluded from JSON and the redacted log.
- Self-contained Windows App SDK 2.4 runtime packaging, including the official runtime resource index extracted reproducibly from Microsoft's NuGet MSIX.

### Fixed

- Prevented early WinUI `SelectionChanged` events from accessing not-yet-connected XAML controls during startup.
- RU/EN switching now refreshes the footer status immediately instead of retaining the language used by the completed scan.
- XAML resources stored in project subdirectories no longer produce mismatched unpackaged `ms-appx` paths.

### Validation

- Modern Release x64 starts successfully in both framework-dependent diagnostic and self-contained portable layouts on Windows 11 x64.
- Automated UI Automation checks confirmed immediate RU-to-EN status translation and opening of the confidential license dialog without emitting license values to test output.
- Wide and 1024×760 layouts were launched and visually checked; no destructive cleanup operation was executed during development.

## [0.4.0-rc4] - 2026-08-20

### Added
Expand Down
24 changes: 24 additions & 0 deletions CryptoProCleanup.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,44 @@ Project("{BC8A1FFA-BEE3-4634-8014-F334798102B3}") = "CryptoProCleanup", "CryptoP
EndProject
Project("{BC8A1FFA-BEE3-4634-8014-F334798102B3}") = "CryptoProCleanupTests", "CryptoProCleanupTests.vcxproj", "{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}"
EndProject
Project("{BC8A1FFA-BEE3-4634-8014-F334798102B3}") = "CryptoProCleanupModern", "CryptoProCleanupModern.vcxproj", "{75C5D9BA-5B7D-4DD7-8E19-2785DBDCD31D}"
EndProject
Project("{BC8A1FFA-BEE3-4634-8014-F334798102B3}") = "CryptoProCleanupResume", "CryptoProCleanupResume.vcxproj", "{A9B645B3-5600-4EA8-8772-1803483B77B2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4F4EAB45-CC51-451B-8298-7904B312DF4A}.Debug|Win32.ActiveCfg = Debug|Win32
{4F4EAB45-CC51-451B-8298-7904B312DF4A}.Debug|Win32.Build.0 = Debug|Win32
{4F4EAB45-CC51-451B-8298-7904B312DF4A}.Debug|x64.ActiveCfg = Debug|x64
{4F4EAB45-CC51-451B-8298-7904B312DF4A}.Release|Win32.ActiveCfg = Release|Win32
{4F4EAB45-CC51-451B-8298-7904B312DF4A}.Release|Win32.Build.0 = Release|Win32
{4F4EAB45-CC51-451B-8298-7904B312DF4A}.Release|x64.ActiveCfg = Release|x64
{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}.Debug|Win32.ActiveCfg = Debug|Win32
{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}.Debug|Win32.Build.0 = Debug|Win32
{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}.Debug|x64.ActiveCfg = Debug|x64
{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}.Debug|x64.Build.0 = Debug|x64
{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}.Release|Win32.ActiveCfg = Release|Win32
{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}.Release|Win32.Build.0 = Release|Win32
{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}.Release|x64.ActiveCfg = Release|x64
{12A1286B-DF22-4CA5-98F8-ACAB826E64AE}.Release|x64.Build.0 = Release|x64
{75C5D9BA-5B7D-4DD7-8E19-2785DBDCD31D}.Debug|Win32.ActiveCfg = Debug|x64
{75C5D9BA-5B7D-4DD7-8E19-2785DBDCD31D}.Debug|x64.ActiveCfg = Debug|x64
{75C5D9BA-5B7D-4DD7-8E19-2785DBDCD31D}.Debug|x64.Build.0 = Debug|x64
{75C5D9BA-5B7D-4DD7-8E19-2785DBDCD31D}.Release|Win32.ActiveCfg = Release|x64
{75C5D9BA-5B7D-4DD7-8E19-2785DBDCD31D}.Release|x64.ActiveCfg = Release|x64
{75C5D9BA-5B7D-4DD7-8E19-2785DBDCD31D}.Release|x64.Build.0 = Release|x64
{A9B645B3-5600-4EA8-8772-1803483B77B2}.Debug|Win32.ActiveCfg = Debug|x64
{A9B645B3-5600-4EA8-8772-1803483B77B2}.Debug|x64.ActiveCfg = Debug|x64
{A9B645B3-5600-4EA8-8772-1803483B77B2}.Debug|x64.Build.0 = Debug|x64
{A9B645B3-5600-4EA8-8772-1803483B77B2}.Release|Win32.ActiveCfg = Release|x64
{A9B645B3-5600-4EA8-8772-1803483B77B2}.Release|x64.ActiveCfg = Release|x64
{A9B645B3-5600-4EA8-8772-1803483B77B2}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Loading
Loading