microsoft / windows-rs

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

How to use `HPCON` as a pointer? #779

Closed ibigbug closed 3 years ago

ibigbug commented 3 years ago

Hi,

I'd like to pass in an HPCON into this function UpdateProcThreadAttribute as the lpValue with takes a PVOID (or *mut c_void).

Looking at the type definition, an HPCON is a newtype of isize, which I understand is often used as an offset of a pointer.

And if it takes an usize, I can attempt to convert an hpCon.0 into a pointer(which I'm not if that's a right thing to do).

I also think maybe just take the address and pass it in(which is also I'm not sure how to do it correctly) and give me the below error:

...
        &hPC as *mut HPCON as _,
...

error[E0606]: casting `&terminal::process::bindings::Windows::Win32::SystemServices::HPCON` as `*mut terminal::process::bindings::Windows::Win32::SystemServices::HPCON` is invalid
  --> terminal\src\windows\process.rs:75:9
   |
75 |         &hPC as *mut HPCON as _,
   |         ^^^^^^^^^^^^^^^^^^

So to pass in an HPCON into the above function correctly?

thanks.

MarijnS95 commented 3 years ago

Looking at the type definition, an HPCON is a newtype of isize, which I understand is often used as an offset of a pointer.

That doesn't seem relevant here. HPCON appears to be an opaque handle (its name starts with H) and applications should not regard itself with the true meaning besides using it through Win32 APIs to reference a pseudoconsole.

Secondly, your example is close. & gives an immutable borrow which you then try to convert into a mutable raw pointer; that's not allowed. I don't know why the compiler isn't more helpful in stating that you need to mutably borrow hPC instead through &mut. The function takes a void pointer (generic pointer to "something"), so you'll need to cast again. I personally prefer safe casts that cannot modify mutability, and the end result would look something like (&mut hPC as *mut HPCON).cast::<c_void>().

However this is such a common pattern that HPCON implements the Abi trait which provides .set_abi() that returns a raw mutable pointer to HPCON, and the best way to write the final result is hPC.set_abi().cast::<c_void>().

ibigbug commented 3 years ago

thanks again @MarijnS95

That doesn't seem relevant here. HPCON appears to be an opaque handle (its name starts with H) and applications should not regard itself with the true meaning besides using it through Win32 APIs to reference a pseudoconsole.

The reason I post it here is that I couldn't find a way to convert the HPCON into a pointer directly and thought that I could use the .0 pattern to extract the mem address and then build the pointer from the address so I was expecting a usize more or less, and it seems the Abi trait does the work, hence, becomes a language related question again :)

Secondly, your example is close

I was actually doing all of them blindly. I knew my goal is to build a pointer (void *) and there were so many related documentations, Box, std::ptr, as_mut_ptr(), as etc, so I guess it just takes some time for me to get familiar with all of them.

thanks so much again and I really learnt so much these days !

ibigbug commented 3 years ago

one more follow up:

I'm getting this, do I need to use the Abi trait or something?

error[E0599]: no method named `set_abi` found for struct `terminal::process::bindings::Windows::Win32::SystemServices::HPCON` in the current scope
    --> terminal\src\windows\process.rs:75:13
     |
75   |         hPC.set_abi().cast::<c_void>(),
     |             ^^^^^^^ method not found in `terminal::process::bindings::Windows::Win32::SystemServices::HPCON`
     |
    ::: F:\projects\PowerSession\target\debug\build\terminal-dc090c32d1cb5b3e\out/windows.rs:3490:13
     |
3490 |             pub struct HPCON(pub isize);
     |             ---------------------------- method `set_abi` not found for this
     |
     = help: items from traits can only be used if the trait is in scope
     = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
             `use windows::Abi;`

error: aborting due to 3 previous errors; 17 warnings emitted
MarijnS95 commented 3 years ago

The reason I post it here is that I couldn't find a way to convert the HPCON into a pointer directly and thought that I could use the .0 pattern to extract the mem address and then build the pointer from the address so I was expecting a usize more or less, and it seems the Abi trait does the work, hence, becomes a language related question again :)

In general when needing a pointer to some type you don't want to look at interior fields/members as those represent something else. In this case the function wants a pointer to a HPCON, which is an isize type under the hood.

I'm getting this, do I need to use the Abi trait or something?

"Dunno", what does the error say? Take advantage of the Rust compiler being friendly and helpful most of the time :)

ibigbug commented 3 years ago

In this case the function wants a pointer to a HPCON, which is an isize type under the hood.

I think the isize initially confused me because I wasn't sure why a negative pointer pointer can be used and after sighting the IntPtr in C# representative so many times I get why it's an isize.

"Dunno"

Okay I've learnt so much from here, thanks a ton :)