Will HMODULE be automatically freed?

Hello, I have a question. When using windows crates, Free is implemented in the HMODULE tuple structure. Will the handle be automatically freed when the structure is dropped without explicitly calling FreeLibrary?

impl windows_core::Free for HMODULE {
    #[inline]
    unsafe fn free(&mut self) {
        if !self.is_invalid() {
            windows_link::link!("kernel32.dll" "system" fn FreeLibrary(hlibmodule : *mut core::ffi::c_void) -> i32);
            unsafe {
                FreeLibrary(self.0);
            }
        }
    }
}

thanks!

The compiler does not know that method is a destructor.

The documentation for windows_core::Free says:

Custom code to free a handle.

This is similar to the Drop trait, and may be used to implement Drop, but allows handles to be dropped depending on context.

HMODULE does not impl Drop. The compiler will not call its free() method for you automatically. But you may create a newtype that implements Drop to call the free() method.

6 Likes

Ugh. I can't stand it. That code really bothers me.

This is superfluous. The Windows API already checks that a handle is valid. And it does a really good job of it. Dave Cutler has even talked about how that made the operating system so very much better.

Why not set self.0 to INVALID_HANDLE after the FreeLibrary call? That would make it crystal clear to all interested parties that the handle was indeed no longer valid.

Finally, previously Microsoft had done something similar with import definitions; create them where they're needed. A side effect is that the import table ended up huge. Which made program loading noticeably slower. Hopefully, their linker is a now a bit smarter. Or, they stop over-defining imports.

thanks for applying!
@Coding-Badly , @parasyte

i find Owned tuple structure in windows_core crates.
Owned

Since HMODULE implements Free, it seems that Drop is automatically called when wrapped with Owned. Because Owned implements Drop.

Finally, if you wrap it with Owned, it seems that it will be released automatically without explicitly calling CloseHandle. If you don't wrap it, you have to explicitly call CloseHandle.

If there's anything wrong, please point it out.!!

1 Like

This is really useful I didn't know about it!

This is not how I read the code. The Drop impl only delegates to the previously mentioned Free trait. For HMODULE, that calls FreeLibrary(), not CloseHandle().

Maybe there is something specific to the Win32 API, like the former calling the latter. But any such relation is unapparent to those unfamiliar to Win32 internals.

This is pretty interesting -- I hadn't looked into windows-core; I've just been treating the windows-sys as a C-API-in-Rust.

So basically they allow you to opt-in to auto-dropping by wrapping "handle" types (that implement Free) in Owned?

I wonder what other minor ergonomic improvements I've missed by completely ignoring windows-core..

That could be useful to let the optimizer know that it can elide a call to close... but honestly you shouldn't even be able to form an invalid handle at a higher wrapper so yeah, it's just cruft at this level.

In general windows is the "nice" API. It has a bit more churn as the ergonomics are worked on, and it's not to the level (like some non -sys wrappers) that it makes the APIs safe - you still need to validate against the documented behavior - but it does quite a few small things to smooth over the mismatch between Rust and Win32 in an automated process based on the API metadata. The big ones are turning pointer, length pairs into slices and moving error code returns and out pointer parameters into a Result, that goes a huge way to simplifying API usage. String parameters are still pretty hit or miss, unfortunately.

2 Likes

https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Foundation/struct.HANDLE.html#impl-Free-for-HANDLE
If you check this document, there is no source code.
I think it would be safer to explicitly close HANDLE and HMODULE

I think Owned needs more testing
Thanks guys