microsoft / windows-rs

Rust for Windows
https://kennykerr.ca/rust-getting-started/
Apache License 2.0
10.23k stars 475 forks source link

Add support for freeing handles automatically #3013

Closed kennykerr closed 3 months ago

kennykerr commented 3 months ago

The Win32 metadata includes information about how to free certain kinds of handles. Since ownership is often unknown or contextual, this is not used to implement the standard Drop trait. Instead, a new Free trait provided by the windows-core crate is implemented for all handles with appropriate metadata. The free function can be used to free the handle manually, but an Owned<T> wrapper is provided to call free automatically when the owned handle is dropped.

This is supported by nearly 150 different handle types - not just HANDLE - including various crypto handle types, registry, GDI and USER32 types, and many more.

Workarounds are provided for the following Win32 metadata bugs:

Here's an example.

Before:

let event = CreateEventW(None, true, false, None)?;
SetEvent(event)?;
WaitForSingleObject(event, 0);
_ = CloseHandle(event);

After:

let event = Owned::new(CreateEventW(None, true, false, None)?);
SetEvent(*event)?;
WaitForSingleObject(*event, 0);

The BCrypt test provides a more comprehensive example: https://github.com/microsoft/windows-rs/pull/3013/commits/e386c51e024b91451e4b817fd4bfd154b12b685a

Previously, the test was just leaking. You can see how Owned supports all kinds of BCrypt handle types through type inference.

Related: #2638 #2468 #2222

MarijnS95 commented 3 months ago

This looks like really nice stuff! Is the metadata enriched to know when functions like CreateEventW() return an owned handle so that they could possibly return Owned<> straight away in the future, forcing the user to handle automatic lifetime management?

kennykerr commented 3 months ago

This looks like really nice stuff! Is the metadata enriched to know when functions like CreateEventW() return an owned handle so that they could possibly return Owned<> straight away in the future, forcing the user to handle automatic lifetime management?

This isn't very clear today. Hopefully in future...