Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support additional VARIANT types #2877

Closed
mzdk100 opened this issue Feb 24, 2024 · 12 comments · Fixed by #2892
Closed

Support additional VARIANT types #2877

mzdk100 opened this issue Feb 24, 2024 · 12 comments · Fixed by #2892
Labels
enhancement New feature or request

Comments

@mzdk100
Copy link

mzdk100 commented Feb 24, 2024

Summary

I encountered a problem when updating Windows rs to 0.53.0. I am using the AccessibleChildren function, which may return a VARIANT type of IDispatch, but I am unable to convert it to IDispatch;

let mut arr = vec![VARIANT::default())];
let mut cnt = unsafe { std::mem::zeroed() };
match unsafe { AccessibleChildren(&acc, 0, &mut arr, &mut cnt) } {
    Err(e) => Err(e),
    Ok(_) => {
        dbg!(IDispatch::try_from(&arr[0]));
    }
}
cargo run
error[E0277]: the trait bound `IDispatch: From<&windows_core::variant::VARIANT>` is not satisfied
   --> object.rs:?:?
    |
444 |                     dbg!(IDispatch::try_from(&arr[0]));
    |                          ^^^^^^^^^ the trait `From<&windows_core::variant::VARIANT>` is not implemented for `IDispatch`
    |
    = help: the following other types implement trait `From<T>`:
              <IDispatch as From<IDispatchEx>>
              <IDispatch as From<IFontDisp>>
              <IDispatch as From<IFontEventsDisp>>
              <IDispatch as From<IPictureDisp>>
              <IDispatch as From<DICounterItem>>
              <IDispatch as From<DILogFileItem>>
              <IDispatch as From<DISystemMonitor>>
              <IDispatch as From<DISystemMonitorEvents>>
            and 148 others
    = note: required for `&windows_core::variant::VARIANT` to implement `Into<IDispatch>`
    = note: required for `IDispatch` to implement `TryFrom<&windows_core::variant::VARIANT>`

Crate manifest

[dependencies.windows]
version = "0.53.0"
features = [
    "implement",
    "Foundation",
    "Foundation_Collections",
    "Win32_Foundation",
    "Win32_System_Diagnostics_Debug",
    "Win32_System_Kernel",
    "Win32_System_SystemServices",
    "Win32_System_Variant",
    "Win32_Storage_FileSystem",
    "Win32_System_LibraryLoader",
    "Win32_Security",
    "Storage_Streams",
    "Win32_System_Com",
    "Win32_System_Ole",
    "Win32_UI_WindowsAndMessaging",
    "UI_Accessibility",
    "Win32_UI_Accessibility",
    "UI_UIAutomation"
]

Crate code

use windows::Win32::System::Com::IDispatch;
use windows::Win32::UI::Accessibility::{AccessibleChildren, IAccessible};
use windows::core::{BSTR, VARIANT, Interface, IUnknown};

fn main() {
    ...
    let mut arr = vec![VARIANT::default())];
    let mut cnt = unsafe { std::mem::zeroed() };
    match unsafe { AccessibleChildren(&acc, 0, &mut arr, &mut cnt) } {
        Err(e) => Err(e),
        Ok(_) => {
            dbg!(IDispatch::try_from(&arr[0]));
        }
    }
}
@mzdk100 mzdk100 added the bug Something isn't working label Feb 24, 2024
@kennykerr kennykerr added question Further information is requested and removed bug Something isn't working labels Feb 24, 2024
@kennykerr
Copy link
Collaborator

You can use VT_UNKNOWN and then cast that to IDispatch if needed: #2788

@mzdk100
Copy link
Author

mzdk100 commented Feb 24, 2024

I tried, but the transition from VARIANT to IUnknown was unsuccessful:

dbg!(IUnknown::try_from(&arr[0]));
IUnknown::try_from(&arr[0]) = Err(
    Error {
        code: HRESULT(0x80028CA0),
        message: "类型不匹配。",
    },
)

@kennykerr
Copy link
Collaborator

Ah, I meant to support both but looks like I may not have got around to that.

@mzdk100
Copy link
Author

mzdk100 commented Feb 24, 2024

Is there a way for me to implement it myself without using the windows-sys crate?
Otherwise, do I have to revert back to version 0.52.0?

@kennykerr kennykerr added enhancement New feature or request and removed question Further information is requested labels Feb 24, 2024
@hcldan
Copy link

hcldan commented Feb 26, 2024

I also ran into this in #2876.

This 0.53 update was a massive change in the COM space and several things I was doing were basically made impossible. I would have hoped things would have been migrated in a way that did not make it impossible to upgrade as changes were being made.

Getting an IDispatch from a VARIANT is vital to being able to use COM apis. IMO, this should not have been released if you "hadn't gotten around to it yet".

@mzdk100
Copy link
Author

mzdk100 commented Feb 26, 2024

I have downgraded to version 0.52.0 and am waiting for further processing.

@kennykerr kennykerr changed the title Unable to convert VARIANT to IDispatch. Support additional VARIANT types Feb 26, 2024
@kennykerr
Copy link
Collaborator

To summarize, I'm hearing the following:

  • Support conversion for additional types, specifically IDispatch and DECIMAL.
  • Support direct access to the underlying VARIANT data structure.

The latter can be achieved today using windows-sys or windows-bindgen directly, but I'm not opposed to adding something like as_raw/as_mut_raw that would let you directly access the internal data structure as before.

Thoughts?

@mzdk100
Copy link
Author

mzdk100 commented Feb 26, 2024

I hope to support VARIANT conversion to IDispatch, which is an elegant implementation.

@hcldan
Copy link

hcldan commented Feb 27, 2024

I'm not opposed to adding something like as_raw/as_mut_raw that would let you directly access the internal data structure as before.

Thoughts?

Could you also add from_raw, even if hidden, so that I can construct a VARIANT from an imp::VARIANT?
I'd also like to know if there are any memory implications for dealing with the "raw" structures?

@kennykerr
Copy link
Collaborator

You should be able to transmute your way back and forth. The safer alternatives provide memory safety and convenience. I'm not sure what more you expect. If you decide to directly access imp::VARIANT - which you're free to do - you are necessarily jumping into unsafe territory and you're on your own to figure out what the implications are. If you're referring to memory representation, the wrappers use [repr(transparent)] so you're guaranteed that the memory layout is the same.

@kennykerr
Copy link
Collaborator

Let me know what you think of this: #2892

@hcldan
Copy link

hcldan commented Feb 27, 2024

I think that will do nicely, thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants