crtsys 0.1.42

dotnet add package crtsys --version 0.1.42
                    
NuGet\Install-Package crtsys -Version 0.1.42
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="crtsys" Version="0.1.42" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="crtsys" Version="0.1.42" />
                    
Directory.Packages.props
<PackageReference Include="crtsys" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add crtsys --version 0.1.42
                    
#r "nuget: crtsys, 0.1.42"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package crtsys@0.1.42
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=crtsys&version=0.1.42
                    
Install as a Cake Addin
#tool nuget:?package=crtsys&version=0.1.42
                    
Install as a Cake Tool

crtsys NuGet Package

crtsys is a lightweight C/C++ runtime + helper set for Windows kernel drivers. It brings managed access to selected MSVC/C++ runtime, CRT/STL style APIs, and NTL abstractions so WDK driver code can be written in a more natural C++ flow.

This NuGet package is for Visual Studio/MSBuild consumers (crtsys.<version>.nupkg).

Quick start

For modern MSBuild projects, add a PackageReference:

<ItemGroup>
  <PackageReference Include="crtsys" Version="<version>" />
</ItemGroup>

Then restore and build with MSBuild:

msbuild .\my_driver.vcxproj /restore /p:Configuration=Debug /p:Platform=x64

For x86 driver projects, use the MSBuild Win32 platform name:

msbuild .\my_driver.vcxproj /restore /p:Configuration=Debug /p:Platform=Win32

For Visual Studio Package Manager Console:

Install-Package crtsys
  • App projects get compatibility headers/includes.
  • User-mode app projects automatically receive the packaged gzip, RFC 1950 deflate, and Brotli headers and static libraries used by NTL HTTP, WebSocket, and gRPC transforms, including the stateful incremental Content-Encoding stream API. Set <CrtSysUseNtlContentCodecs>false</CrtSysUseNtlContentCodecs> only when the app does not use those standard codecs or supplies its own registries.
  • User and driver projects receive the exact public msquic.h revision used by NTL's optional QUIC backends. The package supplies this compile-time ABI only; it does not install msquic.dll or a kernel NMR provider. Set <CrtSysUseNtlMsQuicHeaders>false</CrtSysUseNtlMsQuicHeaders> only when the project does not compile an MsQuic-backed NTL header or deliberately supplies the same pinned ABI through another include directory.
  • Driver projects (WDK) get automatic WDK linkage for crtsys.lib / Ldk.lib (x86/x64/ARM/ARM64 depending on the selected MSVC toolset).
  • Kernel MsQuic is an explicit deployment choice. Enable NTL kernel MsQuic backend on the driver-model property page, or set <CrtSysUseNtlKernelMsQuic>true</CrtSysUseNtlKernelMsQuic> in a driver project to select the Windows 10 version-2004-or-newer contract and link netio.lib, which resolves the documented NMR client calls used by ntl::net::kernel::msquic_provider. Merely making the pinned headers available does not raise the minimum OS version of every driver.

Driver model selection

Choose the entry model under Project Properties > Driver Settings > Driver Model:

Project model Select Implement Package behavior
WDM NTL WDM ntl::main Uses the NTL WDM entry wrapper
KMDF NTL KMDF ntl::kmdf::main Uses the NTL KMDF entry wrapper while WDF retains PnP, power, and dispatch ownership
Minifilter NTL Minifilter ntl::flt::main Uses the Filter Manager entry wrapper and links fltmgr.lib
WFP callout NTL WFP ntl::main Applies the WFP/NDIS target definitions and links fwpkclnt.lib and the kernel content codecs

Select No NTL entry point to keep the project's existing DriverEntry, WdfDriverCreate, minifilter, or WFP entry path. For model-specific APIs and complete examples, see the KMDF guide, minifilter guide, WFP guide, and the example catalog.

What this NuGet package is for:

  • Modern C++ ownership for control-plane code (ntl::driver, ntl::device, unload callback)
  • Small, readable status/error flow with ntl::status
  • Shared user/kernel contracts from a single header source (shared/*.hpp)
  • Reliable RAII-style lifecycle for driver resources and cleanup

Example (minimal driver entry):

#include <ntl/driver>

ntl::status ntl::main(ntl::driver& driver,
                      const std::wstring& registry_path) {
  (void)registry_path;
  driver.on_unload([]() {});
  return ntl::status::ok();
}

IOCTL sample (kernel + app pair)

Shared header (shared/demo_ioctl.hpp):

// shared/demo_ioctl.hpp
#pragma once

#define DEMO_DEVICE_NAME L"demo_device"
#define DEMO_IOCTL_ECHO \
  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

Kernel side:

#include <string>
#include <wdm.h>
#include <ntl/driver>
#include "shared/demo_ioctl.hpp" // DEMO_DEVICE_NAME/DEMO_IOCTL_*

ntl::status ntl::main(ntl::driver& driver,
                      const std::wstring& registry_path) {
  (void)registry_path;

  auto options = ntl::device_options()
    .name(DEMO_DEVICE_NAME)
    .type(FILE_DEVICE_UNKNOWN)
    .exclusive(false);

  auto device = driver.create_device<void>(options);
  device->on_device_control([](const ntl::device_control::code& code,
                               const ntl::device_control::in_buffer& in,
                               ntl::device_control::out_buffer& out) {
    // register IRP_MJ_DEVICE_CONTROL logic without switch-heavy boilerplate
    if (code == DEMO_IOCTL_ECHO && in.ptr && out.ptr) {
      const auto bytes = in.size < out.size ? in.size : out.size;
      RtlCopyMemory(out.ptr, in.ptr, bytes);
      out.size = bytes;
    }
  });

  driver.on_unload([device]() mutable {
    // keep cleanup in one place; shared_ptr reset happens on unload
    device.reset();
  });

  return ntl::status::ok();
}

App side:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winioctl.h>
#include <iostream>
#include "shared/demo_ioctl.hpp"

int wmain() {
  const HANDLE device = CreateFileW(
      L"\\\\?\\Global\\GLOBALROOT\\Device\\" DEMO_DEVICE_NAME,
      GENERIC_READ | GENERIC_WRITE,
      0, nullptr, OPEN_EXISTING, 0, nullptr);

  if (device == INVALID_HANDLE_VALUE) {
    std::cerr << "failed to open device\n";
    return 1;
  }

  char request[] = "hello";
  char reply[sizeof request] = {};
  DWORD returned = 0;
  const BOOL ok = DeviceIoControl(device,
                                  DEMO_IOCTL_ECHO,
                                  request,
                                  static_cast<DWORD>(sizeof request),
                                  reply,
                                  static_cast<DWORD>(sizeof reply),
                                  &returned,
                                  nullptr);
  CloseHandle(device);
  if (!ok) {
    std::cerr << "DeviceIoControl failed\n";
    return 1;
  }
  return 0;
}

RPC sample (kernel + app pair)

Shared header (shared/demo_rpc.hpp):

// shared/demo_rpc.hpp
#pragma once

NTL_RPC_BEGIN(demo_rpc)

NTL_ADD_CALLBACK_ID_2(demo_rpc, 0x801, int, add, int, left, int, right, {
  return left + right;
})

NTL_ADD_CALLBACK_ID_1(demo_rpc, 0x802, int, negate, int, value, {
  return -value;
})

NTL_RPC_END(demo_rpc)

Kernel side:

#include <memory>
#include <ntl/driver>
#include <ntl/rpc/server>
#include "shared/demo_rpc.hpp"

ntl::status ntl::main(ntl::driver& driver,
                      const std::wstring& registry_path) {
  (void)registry_path;

  auto rpc_server = demo_rpc::init(driver);

  driver.on_unload([rpc_server]() mutable {
    rpc_server.reset(); // remove endpoint before driver unload completes
  });

  return ntl::status::ok();
}

App side:

#include <exception>
#include <iostream>
#include <ntl/rpc/client>
#include "shared/demo_rpc.hpp"

int wmain() {
  try {
    ntl::rpc::client client(L"demo_rpc");
    std::wcout << L"40 + 2 = " << demo_rpc::add(40, 2) << L"\n";
    auto value = client.invoke(demo_rpc::negate_1_method, 7);
    std::wcout << L"negate(7) = " << value << L"\n";
  } catch (const std::exception& e) {
    std::cerr << "RPC call failed: " << e.what() << "\n";
    return 1;
  }
  return 0;
}

This package does not install the WDK/SDK itself and does not convert a normal C++ project into a driver project.

Contents

  • include/ headers
  • native MSBuild props/targets (build/native)
  • pinned MsQuic public ABI header (build/native/msquic/include/msquic.h)
  • prebuilt libs by MSVC toolset, architecture, and configuration: build/native/lib/native/<toolset>/{x86,x64,ARM,ARM64}/{Debug,Release}/(crtsys.lib|Ldk.lib). For example, VS2019 uses build/native/lib/native/v142/x64/Release, VS2022 uses build/native/lib/native/v143/x64/Release, and VS2026 uses build/native/lib/native/v145/x64/Release. ARM is provided for v142/v143; v145 carries x86/x64/ARM64.

Package CI compiles and links a real codec consumer for every packaged toolset, architecture, and Debug/Release combination. x86 and x64 consumers also execute gzip, deflate, Brotli, and chained gzip+Brotli one-byte-split incremental round trips; ARM and ARM64 are cross-link validation on the hosted Windows runners.

Package CI also compiles both the user HTTP/3 backend and kernel NMR wrapper against the redistributed, SHA-256-verified MsQuic header. Runtime deployment of the corresponding user DLL or kernel provider remains a product decision.

The NTL minifilter entry supports Windows 7+ consumers even though the prebuilt library itself is compiled with the Windows 8 Filter Manager declarations. Its public owner layouts are target-version invariant, and the native FLT_REGISTRATION is created and destroyed by the consumer translation unit so that its size and version match the project's NTDDI_VERSION.

Release artifacts

  • crtsys-<version>-prebuilt.zip
    A prebuilt bundle containing headers, libraries, documentation, and CMake helpers. It includes CrtSys.cmake and find_package(crtsys CONFIG) support for CMake-based consumers, and also carries the same native MSBuild build support files.
  • crtsys-<version>-SHA256SUMS.txt
    Checksum file for offline/manual verification.

This package README is intentionally self-contained for nuget.org. The package metadata carries the project URL, repository URL, license, and release asset links separately, so this document avoids repository-relative documentation links that do not resolve on the package page.

Product Compatible and additional computed target framework versions.
native native is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.42 116 8/13/2026
0.1.41 92 8/11/2026
0.1.40 92 8/11/2026
0.1.39 118 8/7/2026
0.1.38 152 7/25/2026
0.1.37 145 7/24/2026
0.1.36 141 7/22/2026
0.1.35 147 7/22/2026
0.1.34 157 7/20/2026
0.1.33 167 7/16/2026
0.1.32 158 7/14/2026
0.1.31 154 7/13/2026
0.1.30 162 7/13/2026
0.1.29 164 7/11/2026
0.1.28 151 7/11/2026
0.1.27 155 7/11/2026
0.1.26 165 7/10/2026
0.1.25 166 7/10/2026
0.1.24 157 7/8/2026
0.1.23 180 7/5/2026
Loading failed