rodrigocfd / winsafe

Windows API and GUI in safe, idiomatic Rust.
https://crates.io/crates/winsafe
MIT License
520 stars 30 forks source link

How about `GetModuleHandleExW`? #141

Closed justanotheranonymoususer closed 1 week ago

justanotheranonymoususer commented 2 weeks ago

This is a really nifty crate, kudos!

How about being able to implement something like this without unsafe:

https://github.com/rust-lang/rust/blob/279604832887abeaea0cb31c20590c43dea497ae/compiler/rustc_session/src/filesearch.rs#L119-L152

rodrigocfd commented 1 week ago

Does this work for you?

use winsafe::{self as w, prelude::*, co};

fn main() {
    let file_name = current_dll_path().unwrap();
    println!("{file_name}");
}

fn current_dll_path() -> w::AnyResult<String> {
    let module = w::HINSTANCE::GetModuleHandleEx(
        w::AddrStr::Addr(current_dll_path as _),
        co::GET_MODULE_HANDLE_EX_FLAG::NoValue,
    )?;

    let file_name = module.GetModuleFileName()?;

    Ok(file_name)
}
justanotheranonymoususer commented 1 week ago

Yes, looks good, thanks

    ///
    /// The `GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT` flag is never used,
    /// for safety reasons.

I assume you could return enum, return whatever GetModuleHandle returns in that case? And also handle pinning better, as no FreeLibrary needed in that case?

rodrigocfd commented 1 week ago

I assume you could return enum, return whatever GetModuleHandle returns in that case? And also handle pinning better, as no FreeLibrary needed in that case?

Can you write me a sketch of your suggestion?

justanotheranonymoususer commented 1 week ago

I can't rn, on mobile, but an enum of:

SysResult<HINSTANCE> (if not bumped count)

SysResult<FreeLibraryGuard> (if bumped by one)

And if pinned, not sure, maybe same as not bumped?

rodrigocfd commented 1 week ago

I don't really like the idea of returning an enum:

let hmodule = match GetModuleHandleEx(FLAG_REFCOUNTED) {
    Counted(hmodule) => hmodule,
    NotCounted(_) => panic!("This never happens!"),
};

The problem with the C version is that you must remember calling FreeLibrary afterwards, and the non-refcounted flag alleviates this burden. In my implementation, you receive a guard, which will always call FreeLibrary for you.

But maybe I don't know some corner case... do you have an actual use case for the non-refcounted version?

justanotheranonymoususer commented 1 week ago

Good point, I agree. I can think of these alternative solutions:

do you have an actual use case for the non-refcounted version?

Like the use-case for GetModuleHandle, sometimes it's just possible to know that it's not necessary.

On Sat, Nov 16, 2024 at 6:17 PM Rodrigo @.***> wrote:

I don't really like the idea of returning an enum:

let hmodule = match GetModuleHandleEx(FLAGREFCOUNTED) { Counted(hmodule) => hmodule, NotCounted() => panic!("This never happens!"),};

The problem with the C version is that you must remember calling FreeLibrary afterwards, and the non-refcounted flag alleviates this burden. In my implementation, you receive a guard, which will always call FreeLibrary for you.

But maybe I don't know some corner case... do you have an actual use case for the non-refcounted version?

— Reply to this email directly, view it on GitHub https://github.com/rodrigocfd/winsafe/issues/141#issuecomment-2480636620, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABMDRPDEJ3N6JM33DBFQAVL2A5VYXAVCNFSM6AAAAABRI4WBN6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIOBQGYZTMNRSGA . You are receiving this because you authored the thread.Message ID: @.***>