One clean DLL for the Windows recovery primitives every system tool ends up re-implementing: System Restore points, VSS shadow-storage status, the Recycle Bin, installed programs, startup entries, services, and drivers.
Built for the tools that need these on day one — uninstallers, backup and recovery apps, driver managers — and for any language that can call C: Rust, C/C++, C#, Python (ctypes), Go, AutoHotkey, and more.
Every Windows system utility re-writes the same fragile glue:
- Shelling out to PowerShell for
Get-ComputerRestorePoint, then parsing its JSON by hand. - Loading
srclient.dllat runtime to delete a restore point. - Declaring
SHQueryRecycleBinWand its struct correctly — again. - Walking three different uninstall registry roots (64-bit, WOW6432Node, per-user) and deduplicating what comes back.
- The two-call
EnumServicesStatusExWsizing dance.
WinRecovery does each of these once, behind a small, stable C ABI, with the parsing logic unit-tested off-Windows.
- Zero dependencies. The Rust crate declares its Win32 bindings by hand; the DLL imports only Windows system libraries and the C runtime.
- One calling convention for everything. Enumerations return a JSON
string (free it with
wr_free_string); failures returnNULL/WR_ERR_*plus a human-readable, thread-localwr_last_error(). - No panics across the ABI. Every entry point is wrapped so a bug
becomes
WR_ERR_INTERNAL, never a crash in the host process. - Honest errors. Reading is mostly unprivileged; creating/deleting restore points needs elevation and Windows' own error is reported — nothing is faked or silently skipped.
- Small. ~315 KB release build (host build measured; Windows build is comparable).
#include "winrecovery.h"
#include <stdio.h>
int main(void) {
printf("WinRecovery %s\n", wr_version());
char *json = wr_list_restore_points_json();
if (!json) {
fprintf(stderr, "error %d: %s\n", wr_last_error_code(), wr_last_error());
return 1;
}
printf("%s\n", json);
wr_free_string(json);
return 0;
}import ctypes, json
wr = ctypes.CDLL("winrecovery.dll")
wr.wr_list_installed_programs_json.restype = ctypes.c_void_p
ptr = wr.wr_list_installed_programs_json()
if not ptr:
raise RuntimeError(ctypes.c_char_p(wr.wr_last_error()).value.decode())
data = json.loads(ctypes.c_char_p(ptr).value)
wr.wr_free_string(ptr)
print(f"{len(data)} programs installed")| Function | Returns |
|---|---|
wr_version() / wr_version_major/minor/patch() |
static version string / parts (do not free) |
wr_last_error() / wr_last_error_code() |
thread-local error detail |
wr_free_string(p) |
frees any *_json result |
wr_list_restore_points_json() |
JSON array, newest first |
wr_create_restore_point(desc) |
WR_OK or error (needs elevation) |
wr_delete_restore_point(seq) |
WR_OK or error (needs elevation) |
wr_restore_point_protection_json() |
enabled / used / max shadow-storage bytes |
wr_recycle_bin_info_json(drive_or_null) |
item count + total size |
wr_recycle_bin_empty(drive_or_null, no_confirmation) |
WR_OK or error |
wr_list_installed_programs_json() |
JSON array (3 uninstall roots) |
wr_list_startup_entries_json() |
Run/RunOnce + Startup folders |
wr_list_services_json() |
services + drivers with state/PID |
wr_list_drivers_json() |
drivers only |
Full shapes and error codes: include/winrecovery.h
and docs/API.md.
cargo build --release # produces the cdylib for the host target
cargo test # pure-logic tests run on any OS
cargo check --target x86_64-pc-windows-msvc --all-targetsWindows release artifacts are built by CI on windows-latest and uploaded as
the winrecovery-windows-x64 artifact — winrecovery.dll,
winrecovery.dll.lib, and winrecovery.h together, so no local Windows
toolchain is needed to consume or verify the library.
Labels follow the project standard: Verified (ran and passed), Partially verified (ran, but does not cover live system state), Unverified (has not run).
- Verified — unit tests for parsing, JSON shapes, and the FFI error
contract: 9 passing off-Windows, 8 natively on Windows in CI (the ninth
asserts the non-Windows
WR_ERR_NOT_SUPPORTEDpath and iscfg-gated out there). - Verified —
cargo fmt --all --check,cargo clippy --all-targets -- -D warnings, and the release build onwindows-latest. - Verified — Windows-target compile from a non-Windows host
(
cargo clippy/check --target x86_64-pc-windows-msvc --all-targets,ubuntu-latestjob). On Windows this is a no-op, since the host triple already is the MSVC target; this job is what keeps the cross-target gate honest. - Partially verified — C consumer contract test
(
examples/c/contract.c): compiled with MSVC against the built import library and run in CI, green on awindows-latestrunner whose toolchain is Visual Studio 18 (2026) Enterprise. It proves the exported symbols link, the ownership rules hold, and every read-only call either returns valid JSON or fails with aWR_ERR_*code plus a non-emptywr_last_error(). It does not prove the returned data is correct — a CI runner has no meaningful restore points, Recycle Bin contents, or installed programs, and a clean failure satisfies the contract just as a success does. - Unverified — the enumeration and mutation calls against a live Windows machine's real data: restore-point create/list/delete, Recycle Bin contents and emptying, System Protection status, SCM service and driver enumeration on a populated system, and the installed-program and startup lists on a real desktop. Until that pass is recorded, v0.1.0 is a foundation build and is not tagged.
examples/powershell/smoke-test.ps1
runs the pass, and docs/VERIFICATION.md is the
record it should be written into — including, for each function, the Windows
source to cross-check against (Get-ComputerRestorePoint, vssadmin,
services.msc, Task Manager's Startup tab), because a call returning JSON is
not the same as that JSON being correct.
By default the script is read-only and changes nothing. Two opt-in phases go further:
-IncludeMutationscreates one restore point whose description containsé ü € 中, verifies it appears and reads back byte-for-byte, then deletes exactly that point. The round trip is self-cleaning, and the delete runs in afinallyblock, so an interrupted run does not strand a restore point. Needs elevation and System Protection enabled.-EmptyRecycleBinirreversibly empties the Recycle Bin. It is a separate switch, never implied by-IncludeMutations: it previews the item count and size, then requires you to typeEMPTY. If input is redirected it refuses rather than destroying data unattended.
Results are reported as PASS / FAIL / BLOCKED / SKIP and end in a
verdict. BLOCKED means the check could not run for an environmental reason
(not elevated, System Protection off) rather than that the library
misbehaved — keeping those apart is what stops a skipped check from being
misread as a verified one. -ReportPath writes the results as markdown.
CI also parse-checks the script on every run, so a syntax error cannot survive until the moment someone finally runs it on a real machine.
WinRecovery is #1 of a planned set of eight single-purpose Windows DLLs —
see ROADMAP.md. Next up: FastSearch.dll (instant NTFS
file search).
MIT — see LICENSE.