Skip to content

mveril/wslplugins-rs

WSLPlugins-rs

Crates.io Docs.rs Build Status License: Apache-2.0 License: MIT Platform

WSLPlugins-rs is a Rust framework for building WSL plugins. It wraps the raw WSL plugin API with safer, more idiomatic Rust types and provides a procedural macro for generating plugin entry points and hook wiring. The project is intended for Windows hosts that load plugins through WSL. It includes:

  • a runtime crate: wslplugins-rs
  • a proc-macro crate: wslplugins-macro
  • examples that build real plugin DLLs

Features

  • Safe and ergonomic wrappers around the WSL plugin API
  • A #[wsl_plugin_v1(...)] macro that generates the exported entry points
  • Support for WSL metadata, session information, and command execution
  • Examples that can be built, signed, and loaded into WSL

Prerequisites

Install the following tools on Windows:

  • Rust stable and Cargo
  • PowerShell
  • OpenSSL for certificate generation in the signing script
  • SignTool.exe from the Windows SDK

Notes:

  • SignTool.exe is easiest to access from a Visual Studio Developer Command Prompt or a shell where the Windows SDK tools are on PATH.
  • sign-plugin.ps1 requires an elevated PowerShell session.
  • Running the signing step with -Trust installs the generated certificate into the local machine trusted root store.

Workspace Overview

The workspace is organized around a small public API surface and separate macro implementation crates:

  • wslplugins-rs: the main framework crate, with safe wrappers around the WSL plugin API, shared plugin context, typed identifiers, and plugin traits.
  • wslplugins-macro: the procedural macro crate re-exported by wslplugins-rs when the macro feature is enabled.
  • wslplugins-macro-core: the internal parsing and code generation implementation used by the procedural macro.
  • wslplugins-macro-tests: compile-time tests for macro-generated plugin code.

This split keeps plugin authors focused on wslplugins-rs, while the macro parsing and generated WSL entry-point wiring stay isolated in internal crates.

Quick Start

Add the crate with the macro feature:

[dependencies]
wslplugins-rs = { version = "0.1.0-beta.3", features = ["macro"] }

Then implement a plugin:

use wslplugins_rs::prelude::*;

pub(crate) struct MyPlugin {
    context: &'static WSLContext,
}

#[wsl_plugin_v1(2, 0, 5)]
impl WSLPluginV1 for MyPlugin {
    fn try_new(context: &'static WSLContext) -> WinResult<Self> {
        Ok(Self { context })
    }
}

The macro feature re-exports the wsl_plugin_v1 attribute and generates the WSL entry points for a WSLPluginV1 implementation.

Running Commands in WSL

Use ApiV1::new_command to build and execute a Linux command from a plugin session.

use wslplugins_rs::api::{ApiV1, WSLCommandExecution};
use wslplugins_rs::SessionID;

fn run_version(api: &ApiV1) -> Result<(), Box<dyn std::error::Error>> {
    let stream = api
        .new_command(SessionID::from(0), "/bin/cat")
        .with_arg("/proc/version")
        .execute()?;

    drop(stream);
    Ok(())
}

Notes:

  • Program paths must be Linux UTF-8 paths such as /bin/echo
  • argv[0] defaults to the program path and can be overridden with with_arg0
  • with_distribution_id targets a specific user distribution
  • execute() returns a TcpStream connected to process stdin/stdout
  • stderr is forwarded to Linux dmesg

Examples

Two example plugins are included:

  • examples/minimal: a close Rust translation of Microsoft's sample plugin
  • examples/dist-info: a plugin focused on distribution metadata and tracing

Build one of them in release mode:

cargo build --release -p minimal

or:

cargo build --release -p dist-info

The resulting plugin DLLs are produced in target\release\.

Signing a Plugin

Sign the built DLL with the provided PowerShell script:

.\sign-plugin.ps1 -PluginPath .\target\release\minimal.dll -Trust

or:

.\sign-plugin.ps1 -PluginPath .\target\release\dist_info.dll -Trust

If you do not want to install the certificate automatically, omit -Trust.

Microsoft's WSL plugin documentation also requires Windows test signing for test-signed plugin DLLs. If WSL rejects a locally signed plugin with TRUST_E_NOSIGNATURE, enable test signing on the test machine and reboot if required:

Bcdedit.exe -set TESTSIGNING ON

Registering the Plugin in WSL

Register the signed DLL in the WSL plugins registry key:

reg.exe add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\Plugins" /v minimal /d "C:\path\to\wslplugins-rs\target\release\minimal.dll" /t REG_SZ

Adjust the registry value name and DLL path for the plugin you want to load.

Restart the WSL service after registration, then run a WSL command to load the plugin:

Stop-Service -Name "wslservice" -Force
wsl.exe echo "test"

Verification

After loading the plugin:

  • inspect the log output produced by the example
  • verify the DLL path in the registry
  • confirm the DLL was signed successfully

The minimal example writes to C:\wsl-plugin-demo.txt.

Release Checks

The repository release workflow is centered on these commands:

cargo test --workspace --all-features
cargo clippy --workspace --all-targets --all-features
cargo fmt --all -- --check
cargo publish --workspace --dry-run

Contributing

Contributions are welcome. See CONTRIBUTING.md for branch, validation, and pull request guidance.

Please report security issues privately. See SECURITY.md.

License

Licensed under either MIT or Apache-2.0.

About

An idiomatic WSL plugin framework for rust

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors