A standalone WDM driver that watches a dedicated registry subtree, rejects selected operations, and explains its decisions through a secure command-line controller.
Educational, scoped, and monitoring-only by default. Load the native driver only in a disposable Windows test VM.
REGISTRY / PRE-OPERATIONDESIGN VIEW
Watched lab root
HKLM\SOFTWARE\RegDriverTest
01 / An application makes a requestWindows registry API
RegSetValueEx
02 / Configuration Manager calls usInspect the operation
PreSetValue
03 / Match scope and snapshot policyAllow or deny this attempt
NTSTATUS
04 / Record bounded metadataReport through the controller
IOCTL
Architecture sketch, not a captured execution. An allow decision is not proof the operation ultimately succeeded.
Handled notifications
10pre-operation classes
Independent deny flags
7one scoped policy
Event ring capacity
128oldest overwritten when full
Records per read
16bounded buffered IOCTL
01 / Why this exists
From a registry request to an explainable policy decision.
A practical exercise in callbacks, ownership, synchronization, and the boundary between user mode and kernel mode.
The Windows registry stores configuration used by applications and the operating system. Programs can query values, enumerate keys, write settings, and delete or rename entries.
This project places a callback in that flow. It resolves the requested key, checks whether it falls inside the selected lab subtree, and applies an operation-specific deny mask. Registry applications do not need to open the driver's device or change how they call Windows.
The useful outcome is not a claim of complete protection. It is a readable implementation of where a policy decision happens, how it reaches the caller, and what can safely be reported afterward.
02 / Policy desk
Change the rule. Understand the consequence.
Browser-only explanation
Use fixed examples to explore the documented deny bits. This is not a live driver, not a native trace, and not a complete Windows registry emulator. It never opens a device, executes a command, or touches your registry.
An application attempts to set a value on the selected Demo key.
Key / source
HKLM\SOFTWARE\RegDriverTest\Demo
Requested operation
RegNtPreSetValueKey
Scope rule
Inside the watched subtree
Predicted filter decisionAllow this attemptSTATUS_SUCCESS
No deny flags are selected. Windows and other filters still decide whether the operation completes.
Equivalent controller command
.\RegDriverCtl.exe policy 'HKLM\SOFTWARE\RegDriverTest\Demo' 'none' on
For an elevated terminal in your configured test VM. A policy command replaces all settings; it does not merge them. Copying does not execute it.
What this model leaves out: real callback timing, Unicode namespace resolution, Windows permissions, driver-loading rules, other filters, and queue contention. The C implementation and VM results are authoritative.
03 / Architecture
Two paths. One shared contract.
Registry activity drives the callback. The controller configures it over a separate, secured IOCTL path.
DATA PATH
Observe → decide → report
Registry applicationMakes normal Windows registry calls.
Configuration ManagerInvokes RegDriverCallback with typed notification information.
Common reporting helperRegDrvReportIfWatched resolves names, snapshots policy, decides, records, and releases resources.
Return the filter decisionA denial returns STATUS_ACCESS_DENIED; an allow lets normal processing continue.
CONTROL PATH
Configure → inspect → recover
Elevated C controllerOpens \\.\RegDriver. The device defaults to administrators and SYSTEM.
Buffered IOCTLFixed-width, versioned structures; no kernel pointers in the wire contract.
Kernel dispatchRegDrvDispatch validates lengths, flags, and scope. The I/O manager enforces handle access bits.
Shared state and repliesReplace policy, read counters, or consume events. reset restores monitoring-only policy.
KERNEL / C
RegDriver.c
The original teaching-oriented driver, extended in place. One callback, readable operation cases, common name helpers, controlled state, and ordered cleanup.
Small boundaries. Important engineering decisions.
01 / NAMES
Counted strings, not substring guesses.
Kernel names are counted UNICODE_STRING values. The driver resolves objects, joins relative create/open names, and requires an exact-key or subkey boundary. Rename checks also consider destinations and relevant lab ancestors.
02 / CONCURRENCY
A coherent policy snapshot.
A fast mutex protects shared state. Each callback takes one policy and generation snapshot, then performs matching outside the lock. An in-flight request can finish under an older generation.
03 / OWNERSHIP
Acquire, use, release.
Names acquired from Configuration Manager are released on the helper's exit paths. Temporary joined names have explicit ownership. The callback does not read registry value-data buffers for logging.
04 / TELEMETRY
Bounded, useful, deliberately lossy.
The ring stores 128 records, each 824 bytes. Reads consume up to 16. Records include key/name text, PID/TID, time, decision, sequence, and policy generation—not payloads or kernel pointers.
103 KiB
Event-ring storage only, excluding other state and temporary names. Not a total-memory benchmark.
BEST-EFFORT
Oldest records are overwritten on overflow. Readers share one destructive queue. Sequence and drop counts expose loss, not replay.
PRE-OPERATION
An event reports this filter's decision. It does not claim the final Windows operation succeeded.
05 / Run it yourself
Build on the host. Experiment in a test VM.
The website needs no driver. The native project needs the Windows development tools and a deliberate test-signing setup.
01
Build the C solution and run local checks
Use Visual Studio 2026, MSVC v145, a compatible SDK/WDK, and the kernel-driver toolset. All three native projects compile as C17. Run from the repository root in Developer PowerShell.
Use a matching architecture and Windows 10 version 2004 or later, subject to your WDK's target requirements. Take a snapshot, configure test signing and certificate trust, and stage the freshly built binaries. Keep the matching PDB on the host for WinDbg.
Do not change host boot/security settings or load the driver on a daily-use machine. This site does not supply a trusted production driver binary.
After the driver is loaded, use an elevated VM terminal in the staging directory. Use a disposable Demo key containing no valuable data. These are native commands to review and run yourself—not actions executed by this page.
VM ONLY / DRIVER ALREADY LOADED
.\RegDriverCtl.exe policy 'HKLM\SOFTWARE\RegDriverTest\Demo' none on
reg.exe add 'HKLM\SOFTWARE\RegDriverTest\Demo' /v Example /t REG_DWORD /d 1 /f /reg:64
.\RegDriverCtl.exe policy 'HKLM\SOFTWARE\RegDriverTest\Demo' set on
reg.exe add 'HKLM\SOFTWARE\RegDriverTest\Demo' /v Example /t REG_DWORD /d 2 /f /reg:64
.\RegDriverCtl.exe events
.\RegDriverCtl.exe reset
Expected: the second value write is denied. Confirm its actual result and inspect events. Reset changes policy, not counters or queued records. Close controller handles before unloading; delete only your disposable lab keys.
06 / Evidence, not assumptions
Different checks answer different questions.
LOCAL CHECKS
Build and shared logic
The native project has been built locally in x64 Debug and Release. Local checks cover ABI sizes, path boundaries, independent masks, controller parsing, and JSON escaping.
A build and unit run do not prove kernel runtime enforcement.
--expect-access-denied checks the control device from a non-elevated terminal.
These runtime results are not demonstrated or certified by this website.
SEPARATE WEBSITE CHECKS
Presentation and interaction
The browser walkthrough is tested against the header's operation IDs and deny bits. Site checks cover assets and links; browser smoke tests cover controls, keyboard use, mobile layouts, and no-JavaScript reading.
Website checks are not native-driver tests.
07 / Honest limits
A learning project. Not a security product.
The strongest part of a systems project is knowing what it does not guarantee.
Not complete registry mediation. Metadata/security queries, hive and transaction operations, aliases, and redirected views are not comprehensively covered.
Resolution can fail open. Failure before a decision is counted but leaves the operation allowed. An already-selected denial is retained if reporting later fails.
No durable audit or policy store. State is in memory, events can be lost, and a reload starts fresh. An administrator can change policy or unload the driver.
No performance or certification claim. ARM64 runtime, concurrency stress, fault injection, and production hardening require separate validation.
08 / Go deeper
Follow the design all the way to the C.
The implementation keeps its original function names, detailed commentary, and nine spaced learning sections in one active driver file.