Build more secure software with Rust for Windows

Microsoft has released an early version of its Rust tool for Windows development. It’s well worth a look.

Microsoft has been interested in Rust for some time now, investigating its use as a type-safe and memory-safe alternative to C and C++ in systems programming tasks. With more and more of Microsoft’s business reliant on cloud services, tools such as Rust are going to be essential to building those services, increasing both reliability and security.

Systems programming tools have their roots in operating system development, where you need to have very little between your code and your hardware, and where the overhead associated with runtimes and with garbage collection adds unwanted latency. Those characteristics aren’t only for operating systems; they’re critical to building any reliable application where you want code to run safely without memory leaks and where it’s hard for an attacker to step outside your code’s own section of system memory.

By building in Rust, you’re making your code safer. It’s a first line of defense, built into the very language and tools used to build your code. Maybe you’re building drivers or maybe you’re building banking software; what’s important is that your code needs to be trustworthy and you need to manage risk. So where you might have used JavaScript, you can use Rust running in WebAssembly, and where you’d have used C or C++, you’re using the Windows or Linux versions.

Microsoft, Rust, and Windows

Microsoft’s commitment to Rust is shown in its position as a founding member of the Rust Foundation and in the number of language and tools developers who’ve joined the company in recent months. Microsoft has now announced its own set of tools for building and developing Windows code using Rust, tools based on the same Windows features that allowed it to deliver its C++/WinRT API projections.

At the heart of Rust for Windows is a Rust crate that supports Windows API metadata to generate API code on the fly. You will need the C++ build tools in your development environment, either using the standalone tools in Visual Studio Code or a full Visual Studio install. That does mean it’s not free software: You will need a Visual Studio license to use the C++ tools. (The free Community edition is an option if you’re building on an open source project or are an individual developer.)

You can download the Rust compiler for Windows from the Rust site, with 32- and 64-bit versions. The rustup tool downloads all the appropriate components for your development system, with a simple command line tool to help customize your installation. If you’re using Code there are a couple of additional extensions to install: rust-analyzer to add a Rust language server for IntelliSense code highlighting and hinting, and either CodeLLDB or Microsoft’s C/C++ extension for debugging. Once those are in place you can start to work with Rust for Windows.

Inside the Rust for Windows crate

One of the most important tools for Windows developers is its support for language projection. This is a technique that allows development tools to generate language-specific APIs from the metadata Windows has for its SDKs. With language projection support there’s no need for Microsoft to write APIs for each supported language, adding to the complexity of the ever-growing Windows SDKs and making it harder to keep every supported language in sync with Windows.

The technique ensures that all that’s needed for Rust to get Windows support is an appropriate language projection; the APIs are then automatically generated as needed. There’s no need for Microsoft to deliver SDKs for supported languages, and all any new language needs is its own language projection to get support from Windows. That’s a much less complex development task, and as new Windows APIs are released (for example, in Project Reunion) all that’s needed from the API team is a metadata definition.

You can use the Rust tools in Visual Studio and Visual Studio Code to write Rust modules that can run anywhere, but if you’re planning on using it for Windows development, you’re going to need to install the Rust for Windows tools to access the Windows APIs. Microsoft’s Rust services are an open source project available on GitHub. The current release is available as a Rust crate and can be installed from the Rust crate repository.

Using Rust for Windows

The Windows Rust crate installs from Rust’s Cargo as a package using standard Rust features. Once installed, you can use Rust’s build tools to create the appropriate bindings for the Windows APIs you want to use in your project. This approach delivers code for only the APIs you want to use; you can add new bindings as you add APIs and remove any that you don’t need to support. Keeping API support only with what’s needed adds additional security to your code. There’s no way for it to call unsupported APIs and any attack surface is kept to a minimum.

Rust development on Windows is still under development, so you will need to step outside your usual development environment at times. New projects need to be created from Cargo, using the command line. Once you’ve created a project, you set up a bindings crate to host your Rust for Windows APIs. This is created in your project’s cargo.toml file, adding dependencies for the Windows crate. This will install the right version for your code. You will need to manually update the version number for new releases (currently this will be 0.8.0).

What’s interesting about how Rust for Windows generates API bindings is that you can focus right down on the part of an API namespace that you want to use. Once you’ve chosen a namespace, add it to a file in the bindings folder. Microsoft provides a macro to create the API bindings and using it will automatically create any dependencies that are needed, while many key APIs are built into the Windows crate and can be used without having to build bindings for standard APIs like Windows.Foundation. There’s documentation for the Windows API to help you get started.

You can then include links to the bindings file in your code, ready to start using them. What’s really important about this process is that you can mix and match the APIs that you’re using, working with Direct3D for GPU compute and XAML tooling for your UI in the same application. It’s also ready for new APIs, taking advantage of their metadata as soon as they are released. This approach is going to be increasingly important as Microsoft accelerates API development by decoupling the Windows SDK from the Windows release cycle.

The result is a flexible and powerful way of building complete Windows applications in Rust. By using Rust for Windows to handle API calls, your code will be more secure—and ready for future changes in the Windows APIs with just a rebuild and recompile as new and updated APIs roll out.

Copyright © 2021 IDG Communications, Inc.