winvd 0.0.30

Provides functions for accessing Windows 11 virtual desktop API
Documentation
# COM Guidance by David Risney:


> 1. When a COM object is passed from caller to callee as an input parameter to
>    a method, the caller is expected to keep a reference on the object for the
>    duration of the method call. The callee shouldn't need to call `AddRef` or
>    `Release` for the synchronous duration of that method call. For example, if
>    you're the callee implementing one of the async completed handler or event
>    handler `Invoke` methods, the WebView2 code will call your Invoke method
>    and pass in a COM object and you don't need to call `AddRef` or `Release`
>    on it.

> 2. When a COM object is passed from callee to caller as an out parameter from
>    a method the object is provided to the caller with a reference already
>    taken and the caller owns the reference. Which is to say, it is the
>    caller's responsibility to call `Release` when they're done with the
>    object. For example, if you call
>    `ICoreWebView2::get_Settings(ICoreWebView2Settings**)`, the `get_Settings`
>    code will call `AddRef` on the `ICoreWebView2Settings` it hands back to you
>    and its up to you only to call `Release` when you're done.

> 3. When making a copy of a COM object pointer you need to call `AddRef` and
>    `Release`. The `AddRef` must be called before you call `Release` on the
>    original COM object pointer. If for example you have an async method call
>    completion handler method that receives a COM object as an in parameter but
>    you need to deal with that COM object asynchronously later, you'll need to
>    make a copy of the COM object pointer and call `AddRef` during the
>    completion handler and then `Release` later after you finish your async
>    work with the object.

https://github.com/MicrosoftEdge/WebView2Feedback/issues/2133

## IVirtualDesktopNotification


To sum it up according to COM guidance the caller increases the reference count
with `AddRef()` and the callee should use `Release()` when getting the value
through `Out` parameter. However, when it's an `In` parameter the caller ensures
the value is held alive during the call and you must not call `Release()`.

Notice that `IVirtualDesktopNotification` is an interface this code implements,
we don't call the methods on it, but Windows shell calls those, this means that
all values we get should have been added with a reference by the Windows shell
for us.

This means the interface **must** be using `ManuallyDrop<T>`:

```rust
pub unsafe trait IVirtualDesktopNotification: IUnknown {
    pub unsafe fn virtual_desktop_created(
        &self,
        monitors: ManuallyDrop<IObjectArray>,
        desktop: ManuallyDrop<IVirtualDesktop>,
    ) -> HRESULT;

    pub unsafe fn virtual_desktop_destroy_begin(
        &self,
        monitors: ManuallyDrop<IObjectArray>,
        desktop_destroyed: ManuallyDrop<IVirtualDesktop>,
        desktop_fallback: ManuallyDrop<IVirtualDesktop>,
    ) -> HRESULT;
    // ...
}
```

And we must never call `Release()` ourselves on the values.

Naively one would think it can be done like this:

```rust
pub unsafe trait IVirtualDesktopNotification: IUnknown {
    pub unsafe fn virtual_desktop_created(
        &self,
        monitors: IObjectArray, // This is wrong, should be ManuallyDrop<IObjectArray>
        desktop: IVirtualDesktop, // This is wrong, should be ManuallyDrop<IVirtualDesktop>
    ) -> HRESULT;

    pub unsafe fn virtual_desktop_destroy_begin(
        &self,
        monitors: IObjectArray, // This is wrong, should be ManuallyDrop<IObjectArray>
        desktop_destroyed: IVirtualDesktop, // This is wrong, should be ManuallyDrop<IVirtualDesktop>
        desktop_fallback: IVirtualDesktop, // This is wrong, should be ManuallyDrop<IVirtualDesktop>
    ) -> HRESULT;
    // ...
}
```

Because `windows-rs` COM objects call `Release()` during `drop` it will cause a
subtle bug. If I allow calls to `drop` the crash occurs but after switching
desktops repeatedly for ~2000-3000 times. This is not an easy bug to make
happen.