Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1 @@
{"files":{"Cargo.toml":"2e83268d97f74f748659dd819cff376687ea4bcd22894ffadab816b4845ba105","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"b208c347114a90fd6ceda1959113fabe9262eec2b7a461837cbb659dd8b3581a","src/agile_reference.rs":"aeca8437136c09a51ef45cface5ae8e6720f67d23681faa12a84b14a79cfeed2","src/array.rs":"50afdb247feb5e0b575a9cfeda2359719fe0db7bd4b12c687d699f3821d15eee","src/as_impl.rs":"b9d36d6634de33928cc78b8e0824483c5b6561ca3872d5a9b267fb196db3d07e","src/com_object.rs":"c52c3aae2343c70462dd4912194b9da076606eabb6770f52e3143ad5bf17343d","src/event.rs":"0780bad7a130718701b3f9dec5bc41c5cbecb2172d9ee5285dec9bfde6beeb80","src/guid.rs":"27f3e764fb5787cf8dbf2e284e643e1555a3bd1ae5d0d70b76a9193cd051792f","src/handles.rs":"c5f53785605cc14059c4ad0272e310b435ed2f48405e8e4052fb1d5e40ee4d78","src/imp/bindings.rs":"a408255214aa69bb2628ae8b8000ca0ea5e77e426fc882cca70d84bb4a9bd251","src/imp/can_into.rs":"d06228653f20c07dcfd8a4004cd6be7a19a8da0a79226d42653ab2f3bf290816","src/imp/com_bindings.rs":"7b550c5812e03777f92b7e9c7a9155d710013056c4b8bbdbe4791b7bd0a04c09","src/imp/delay_load.rs":"3b8ee4b72acbed9c6323ade5dc451366521cff49252fee3b8a45defe751c16fe","src/imp/factory_cache.rs":"e7be1040fa818dbaeb512bc2b1260131651bad4822819f16d0e9ff973c857389","src/imp/generic_factory.rs":"340e2a75a5c4ec36bc7ea442c7211b3be4f8d3a537fda99316f9ce15bde02555","src/imp/heap.rs":"c245a4a5f9518f6d283eca43b729bfaae5ef2d17d1e0f5387b3be6e3ebe16b79","src/imp/mod.rs":"b21082a84f18ecd49b08cad304a25699bbf0103c8ad91709c1f1bb5c731e5ca3","src/imp/ref_count.rs":"d2d9cf27bcf2b5206ea1270107c77efd2216faf4e74ec731ef1c39b47bb07520","src/imp/sha1.rs":"bf8707becd6f32e13d23da0b5ecad906858f42af9626b130a3a88bf8b4f0975e","src/imp/waiter.rs":"fd36d737ac2fda4f3771b036dab0f36a247df4715e24e6b9f6975151c164d327","src/imp/weak_ref_count.rs":"abe25a382b8840e71a9b2fd6263a8d3be4407f5f34b98a65ddcdfef5be4aba36","src/inspectable.rs":"7ee2e0902ef87d243e2250022745ef4b2d6c4692ca4228976ed5b1c1d0d5e5dd","src/interface.rs":"c3bcbdcef95f91742215f29d57ee9920fae7923914eb635054e81ad34bd06a12","src/lib.rs":"ccf1d7794a1de2d7b5dc50b9d7a09dce49e67cb472febdccae5931a9400eaaaa","src/out_param.rs":"d91dd1a88201c2dbb395d371ba42270bc19191861758496fccba30ad5f8d52e9","src/out_ref.rs":"e12010828943df8c4aa40c9b53316a96f14c208fdb0e860b5206ddc5eedce1d2","src/param.rs":"ae1fc80d1871653da46395a96f8eaf95184bb5e0c1becb49b909e735ef998304","src/param_value.rs":"b1d29ec7589cc7eebba1faf01aaae39f9d401dff13d2a6a5ec382f94b1becce0","src/ref.rs":"9cdceb34ad726190459bef5ec8d2a030b0dbf164b5cd969d215a3d09622897f6","src/runtime_name.rs":"b330db95b0ce32c963d6b43a0b152cd96e136e5b38b92c02223fb53b30f83ecf","src/runtime_type.rs":"23a8e4aa09fd56bb2cb5c08444fe3b1f03b5a2e160f9144c2507189939f58cd2","src/scoped_interface.rs":"57d9dcd0284659e2bf465c08d6c857c2c985e90f0316e5677ebd2a656edb6737","src/strings/bstr.rs":"50d85b6009d2c888f8990b7814729e45e73452843deb11bd3a41cce7bc3883ca","src/strings/hstring.rs":"f025c3529aa4860e9d2d48c0d470971fdf5a785afdddecc6b858f5e0b9b40f6b","src/strings/literals.rs":"08a5ff6547a9ce50d27ab910cb9d8f8a3b647a412bf320f49ea4a124265157d2","src/strings/mod.rs":"95b3e1dc2a2b08ad80236e0326f305c4439865963239061c90683e1dd60b5c4c","src/strings/pcstr.rs":"832f18aea1b97eb12ecab7e58a4f5f16a22f118a4d9d66d4bdb84c83c2fd3d58","src/strings/pcwstr.rs":"120ac5be40ca4822cae867bdbc11829dae39d50c81318986a6653615dc48d1db","src/strings/pstr.rs":"34b4b2035330d192e29914f68a1b9096387562e0bf2e1d4bef2937a9fcce7734","src/strings/pwstr.rs":"d4701cd606421100b896d6b0cc09117df0f2e59f47e95d91eb178dfd431c89fe","src/type.rs":"5fc597506c345df1f2ba01e78ed188d211222e7363d1ad1596b2eaf6d82fa56e","src/unknown.rs":"9b6117025d4d18600ef682aa0bacb904c020b0b6bfe6c1ab6d236c716a3abea1","src/variant.rs":"2708f9ba47369879b222f19c8bc29705d03140b254d0c09ab7557a0f71dd006e","src/weak.rs":"5e21eda4c48c07a9137dd18b50c53e53fc291f73ad3ffbc8f544b82b05add7d2","tests/bindings.rs":"99f55bd950b1594a27426af40374a2b07caf52c8351a0eb43bbc880de35fcf52","tests/bindings.txt":"61698a849bd925326cd916e101cd8f604fd60002dba462f29a66c0a3b7d9cc91","tests/com_bindings.txt":"4029e53fa671a24d4616cfc4a19f10f8007da0045bca3223aa2b42a628ef4a00"},"package":"d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"}

70
vendor/windows-core-0.57.0/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,70 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.70"
name = "windows-core"
version = "0.57.0"
authors = ["Microsoft"]
build = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Rust for Windows"
readme = "readme.md"
categories = ["os::windows-apis"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/microsoft/windows-rs"
[package.metadata.docs.rs]
default-target = "x86_64-pc-windows-msvc"
targets = []
[lib]
name = "windows_core"
path = "src/lib.rs"
[[test]]
name = "bindings"
path = "tests/bindings.rs"
[dependencies.windows-implement]
version = "0.57.0"
[dependencies.windows-interface]
version = "0.57.0"
[dependencies.windows-result]
version = "0.1.1"
[dependencies.windows-targets]
version = "0.52.5"
[dev-dependencies.windows-bindgen]
version = "0.57.0"
[features]
default = ["std"]
std = []
[lints.rust]
missing_docs = "warn"
[lints.rust.rust_2018_idioms]
level = "warn"
priority = -1
[lints.rust.unexpected_cfgs]
level = "warn"
priority = 0
check-cfg = ["cfg(windows_raw_dylib, windows_debugger_visualizer)"]

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (c) Microsoft Corporation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

21
vendor/windows-core-0.57.0/license-mit vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

88
vendor/windows-core-0.57.0/readme.md vendored Normal file
View File

@@ -0,0 +1,88 @@
## Rust for Windows
The [windows](https://crates.io/crates/windows) and [windows-sys](https://crates.io/crates/windows-sys) crates let you call any Windows API past, present, and future using code generated on the fly directly from the [metadata describing the API](https://github.com/microsoft/windows-rs/tree/master/crates/libs/bindgen/default) and right into your Rust package where you can call them as if they were just another Rust module. The Rust language projection follows in the tradition established by [C++/WinRT](https://github.com/microsoft/cppwinrt) of building language projections for Windows using standard languages and compilers, providing a natural and idiomatic way for Rust developers to call Windows APIs.
* [Getting started](https://kennykerr.ca/rust-getting-started/)
* [Samples](https://github.com/microsoft/windows-rs/tree/0.57.0/crates/samples)
* [Releases](https://github.com/microsoft/windows-rs/releases)
Start by adding the following to your Cargo.toml file:
```toml
[dependencies.windows]
version = "0.57"
features = [
"Data_Xml_Dom",
"Win32_Foundation",
"Win32_Security",
"Win32_System_Threading",
"Win32_UI_WindowsAndMessaging",
]
```
Make use of any Windows APIs as needed:
```rust,no_run
use windows::{
core::*, Data::Xml::Dom::*, Win32::Foundation::*, Win32::System::Threading::*,
Win32::UI::WindowsAndMessaging::*,
};
fn main() -> Result<()> {
let doc = XmlDocument::new()?;
doc.LoadXml(h!("<html>hello world</html>"))?;
let root = doc.DocumentElement()?;
assert!(root.NodeName()? == "html");
assert!(root.InnerText()? == "hello world");
unsafe {
let event = CreateEventW(None, true, false, None)?;
SetEvent(event)?;
WaitForSingleObject(event, 0);
CloseHandle(event)?;
MessageBoxA(None, s!("Ansi"), s!("Caption"), MB_OK);
MessageBoxW(None, w!("Wide"), w!("Caption"), MB_OK);
}
Ok(())
}
```
## windows-sys
The `windows-sys` crate is a zero-overhead fallback for the most demanding situations and primarily where the absolute best compile time is essential. It only includes function declarations (externs), structs, and constants. No convenience helpers, traits, or wrappers are provided.
Start by adding the following to your Cargo.toml file:
```toml
[dependencies.windows-sys]
version = "0.52"
features = [
"Win32_Foundation",
"Win32_Security",
"Win32_System_Threading",
"Win32_UI_WindowsAndMessaging",
]
```
Make use of any Windows APIs as needed:
```rust,no_run
use windows_sys::{
core::*, Win32::Foundation::*, Win32::System::Threading::*, Win32::UI::WindowsAndMessaging::*,
};
fn main() {
unsafe {
let event = CreateEventW(std::ptr::null(), 1, 0, std::ptr::null());
SetEvent(event);
WaitForSingleObject(event, 0);
CloseHandle(event);
MessageBoxA(0, s!("Ansi"), s!("Caption"), MB_OK);
MessageBoxW(0, w!("Wide"), w!("Caption"), MB_OK);
}
}
```

View File

@@ -0,0 +1,39 @@
use super::*;
use core::marker::PhantomData;
/// A type representing an agile reference to a COM/WinRT object.
#[repr(transparent)]
#[derive(Clone, PartialEq, Eq)]
pub struct AgileReference<T>(imp::IAgileReference, PhantomData<T>);
impl<T: Interface> AgileReference<T> {
/// Creates an agile reference to the object.
pub fn new(object: &T) -> Result<Self> {
// TODO: this assert is required until we can catch this at compile time using an "associated const equality" constraint.
// For example, <T: Interface<UNKNOWN = true>>
// https://github.com/rust-lang/rust/issues/92827
assert!(T::UNKNOWN);
unsafe {
imp::RoGetAgileReference(
imp::AGILEREFERENCE_DEFAULT,
&T::IID,
core::mem::transmute::<&T, &IUnknown>(object),
)
.map(|reference| Self(reference, Default::default()))
}
}
/// Retrieves a proxy to the target of the `AgileReference` object that may safely be used within any thread context in which get is called.
pub fn resolve(&self) -> Result<T> {
unsafe { self.0.Resolve() }
}
}
unsafe impl<T: Interface> Send for AgileReference<T> {}
unsafe impl<T: Interface> Sync for AgileReference<T> {}
impl<T> core::fmt::Debug for AgileReference<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "AgileReference({:?})", &self.0)
}
}

186
vendor/windows-core-0.57.0/src/array.rs vendored Normal file
View File

@@ -0,0 +1,186 @@
use super::*;
/// A WinRT array stores elements contiguously in a heap-allocated buffer.
pub struct Array<T: Type<T>> {
data: *mut T::Default,
len: u32,
}
impl<T: Type<T>> Default for Array<T> {
fn default() -> Self {
Array {
data: core::ptr::null_mut(),
len: 0,
}
}
}
impl<T: Type<T>> Array<T> {
/// Creates an empty array.
pub fn new() -> Self {
Self::default()
}
/// Creates an array of the given length with default values.
pub fn with_len(len: usize) -> Self {
assert!(len < u32::MAX as usize);
let bytes_amount = len
.checked_mul(core::mem::size_of::<T>())
.expect("Attempted to allocate too large an Array");
// WinRT arrays must be allocated with CoTaskMemAlloc.
// SAFETY: the call to CoTaskMemAlloc is safe to perform
// if len is zero and overflow was checked above.
// We ensured we alloc enough space by multiplying len * size_of::<T>
let data = unsafe { imp::CoTaskMemAlloc(bytes_amount) as *mut T::Default };
assert!(!data.is_null(), "Could not successfully allocate for Array");
// SAFETY: It is by definition safe to zero-initialize WinRT types.
// `write_bytes` will write 0 to (len * size_of::<T>())
// bytes making the entire array zero initialized. We have assured
// above that the data ptr is not null.
unsafe {
core::ptr::write_bytes(data, 0, len);
}
let len = len as u32;
Self { data, len }
}
/// Creates an array by copying the elements from the slice.
pub fn from_slice(values: &[T::Default]) -> Self
where
T::Default: Clone,
{
let mut array = Self::with_len(values.len());
array.clone_from_slice(values);
array
}
/// Creates an array from a pointer and length. The `len` argument is the number of elements, not the number of bytes.
/// # Safety
/// The `data` argument must have been allocated with `CoTaskMemAlloc`.
pub unsafe fn from_raw_parts(data: *mut T::Default, len: u32) -> Self {
Self { data, len }
}
/// Returns a slice containing the entire array.
pub fn as_slice(&self) -> &[T::Default] {
self
}
/// Returns `true` if the array is empty.
pub fn is_empty(&self) -> bool {
self.len == 0
}
/// Returns the length of the array.
pub fn len(&self) -> usize {
self.len as usize
}
/// Clears the contents of the array.
pub fn clear(&mut self) {
if self.is_empty() {
return;
}
let mut data = core::ptr::null_mut();
let mut len = 0;
core::mem::swap(&mut data, &mut self.data);
core::mem::swap(&mut len, &mut self.len);
// SAFETY: At this point, self has been reset to zero so any panics in T's destructor would
// only leak data not leave the array in bad state.
unsafe {
// Call the destructors of all the elements of the old array
// SAFETY: the slice cannot be used after the call to `drop_in_place`
core::ptr::drop_in_place(core::slice::from_raw_parts_mut(data, len as usize));
// Free the data memory where the elements were
// SAFETY: we have unique access to the data pointer at this point
// so freeing it is the right thing to do
imp::CoTaskMemFree(data as _);
}
}
#[doc(hidden)]
/// Get a mutable pointer to the array's length
///
/// # Safety
///
/// This function is safe but writing to the pointer is not. Calling this without
/// a subsequent call to `set_abi` is likely to either leak memory or cause UB
pub unsafe fn set_abi_len(&mut self) -> *mut u32 {
&mut self.len
}
#[doc(hidden)]
/// Turn the array into a pointer to its data and its length
pub fn into_abi(self) -> (*mut T::Abi, u32) {
let abi = (self.data as *mut _, self.len);
core::mem::forget(self);
abi
}
}
impl<T: Type<T>> core::ops::Deref for Array<T> {
type Target = [T::Default];
fn deref(&self) -> &[T::Default] {
if self.is_empty() {
return &[];
}
// SAFETY: data must not be null if the array is not empty
unsafe { core::slice::from_raw_parts(self.data, self.len as usize) }
}
}
impl<T: Type<T>> core::ops::DerefMut for Array<T> {
fn deref_mut(&mut self) -> &mut [T::Default] {
if self.is_empty() {
return &mut [];
}
// SAFETY: data must not be null if the array is not empty
unsafe { core::slice::from_raw_parts_mut(self.data, self.len as usize) }
}
}
impl<T: Type<T>> Drop for Array<T> {
fn drop(&mut self) {
self.clear();
}
}
#[doc(hidden)]
pub struct ArrayProxy<T: Type<T>> {
data: *mut *mut T::Default,
len: *mut u32,
temp: core::mem::ManuallyDrop<Array<T>>,
}
impl<T: Type<T>> ArrayProxy<T> {
pub fn from_raw_parts(data: *mut *mut T::Default, len: *mut u32) -> Self {
Self {
data,
len,
temp: core::mem::ManuallyDrop::new(Array::new()),
}
}
pub fn as_array(&mut self) -> &mut Array<T> {
&mut self.temp
}
}
impl<T: Type<T>> Drop for ArrayProxy<T> {
fn drop(&mut self) {
unsafe {
*self.data = self.temp.data;
*self.len = self.temp.len;
}
}
}

View File

@@ -0,0 +1,20 @@
/// A trait for retrieving the implementation behind a COM or WinRT interface.
///
/// This trait is automatically implemented when using the `implement` macro.
pub trait AsImpl<T> {
/// # Safety
///
/// The caller needs to ensure that `self` is actually implemented by the
/// implementation `T`.
unsafe fn as_impl(&self) -> &T {
self.as_impl_ptr().as_ref()
}
/// Returns a pointer to the implementation object.
///
/// # Safety
///
/// The caller needs to ensure that `self` is actually implemented by the
/// implementation `T`.
unsafe fn as_impl_ptr(&self) -> core::ptr::NonNull<T>;
}

View File

@@ -0,0 +1,332 @@
use crate::imp::Box;
use crate::{AsImpl, IUnknown, IUnknownImpl, Interface, InterfaceRef};
use core::any::Any;
use core::borrow::Borrow;
use core::ops::Deref;
use core::ptr::NonNull;
/// Identifies types that can be placed in [`ComObject`].
///
/// This trait links types that can be placed in `ComObject` with the types generated by the
/// `#[implement]` macro. The `#[implement]` macro generates implementations of this trait.
/// The generated types contain the vtable layouts and refcount-related fields for the COM
/// object implementation.
///
/// This trait is an implementation detail of the Windows crates.
/// User code should not deal directly with this trait.
///
/// This trait is sort of the reverse of [`IUnknownImpl`]. This trait allows user code to use
/// [`ComObject<T>`] instead of `ComObject<T_Impl>`.
pub trait ComObjectInner: Sized {
/// The generated `<foo>_Impl` type (aka the "boxed" type or "outer" type).
type Outer: IUnknownImpl<Impl = Self>;
/// Moves an instance of this type into a new ComObject box and returns it.
///
/// # Safety
///
/// It is important that safe Rust code never be able to acquire an owned instance of a
/// generated "outer" COM object type, e.g. `<foo>_Impl`. This would be unsafe because the
/// `<foo>_Impl` object contains a reference count field and provides methods that adjust
/// the reference count, and destroy the object when the reference count reaches zero.
///
/// Safe Rust code must only be able to interact with these values by accessing them via a
/// `ComObject` reference. `ComObject` handles adjusting reference counts and associates the
/// lifetime of a `&<foo>_Impl` with the lifetime of the related `ComObject`.
///
/// The `#[implement]` macro generates the implementation of this `into_object` method.
/// The generated `into_object` method encapsulates the construction of the `<foo>_Impl`
/// object and immediately places it into the heap and returns a `ComObject` reference to it.
/// This ensures that our requirement -- that safe Rust code never own a `<foo>_Impl` value
/// directly -- is met.
fn into_object(self) -> ComObject<Self>;
}
/// Describes the COM interfaces implemented by a specific COM object.
///
/// The `#[implement]` macro generates implementations of this trait. Implementations are attached
/// to the "outer" types generated by `#[implement]`, e.g. the `MyApp_Impl` type. Each
/// implementation knows how to locate the interface-specific field within `MyApp_Impl`.
///
/// This trait is an implementation detail of the Windows crates.
/// User code should not deal directly with this trait.
pub trait ComObjectInterface<I: Interface> {
/// Gets a borrowed interface that is implemented by `T`.
fn as_interface_ref(&self) -> InterfaceRef<'_, I>;
}
/// A counted pointer to a type that implements COM interfaces, where the object has been
/// placed in the heap (boxed).
///
/// This type exists so that you can place an object into the heap and query for COM interfaces,
/// without losing the safe reference to the implementation object.
///
/// Because the pointer inside this type is known to be non-null, `Option<ComObject<T>>` should
/// always have the same size as a single pointer.
///
/// # Safety
///
/// The contained `ptr` field is an owned, reference-counted pointer to a _pinned_ `Pin<Box<T::Outer>>`.
/// Although this code does not currently use `Pin<T>`, it takes care not to expose any unsafe semantics
/// to safe code. However, code that calls unsafe functions on [`ComObject`] must, like all unsafe code,
/// understand and preserve invariants.
#[repr(transparent)]
pub struct ComObject<T: ComObjectInner> {
ptr: NonNull<T::Outer>,
}
impl<T: ComObjectInner> ComObject<T> {
/// Allocates a heap cell (box) and moves `value` into it. Returns a counted pointer to `value`.
pub fn new(value: T) -> Self {
T::into_object(value)
}
/// Creates a new `ComObject` that points to an existing boxed instance.
///
/// # Safety
///
/// The caller must ensure that `ptr` points to a valid, heap-allocated instance of `T::Outer`.
/// Normally, this pointer comes from using `Box::into_raw(Box::new(...))`.
///
/// The pointed-to box must have a reference count that is greater than zero.
///
/// This function takes ownership of the existing pointer; it does not call `AddRef`.
/// The reference count must accurately reflect all outstanding references to the box,
/// including `ptr` in the count.
pub unsafe fn from_raw(ptr: NonNull<T::Outer>) -> Self {
Self { ptr }
}
/// Gets a reference to the shared object stored in the box.
///
/// [`ComObject`] also implements [`Deref`], so you can often deref directly into the object.
/// For those situations where using the [`Deref`] impl is inconvenient, you can use
/// this method to explicitly get a reference to the contents.
#[inline(always)]
pub fn get(&self) -> &T {
self.get_box().get_impl()
}
/// Gets a reference to the shared object's heap box.
#[inline(always)]
fn get_box(&self) -> &T::Outer {
unsafe { self.ptr.as_ref() }
}
// Note that we _do not_ provide a way to get a mutable reference to the outer box.
// It's ok to return `&mut T`, but not `&mut T::Outer`. That would allow someone to replace the
// contents of the entire object (box and reference count), which could lead to UB.
// This could maybe be solved by returning `Pin<&mut T::Outer>`, but that requires some
// additional thinking.
/// Gets a mutable reference to the object stored in the box, if the reference count
/// is exactly 1. If there are multiple references to this object then this returns `None`.
#[inline(always)]
pub fn get_mut(&mut self) -> Option<&mut T> {
if self.is_reference_count_one() {
// SAFETY: We must only return &mut T, *NOT* &mut T::Outer.
// Returning T::Outer would allow swapping the contents of the object, which would
// allow (incorrectly) modifying the reference count.
unsafe { Some(self.ptr.as_mut().get_impl_mut()) }
} else {
None
}
}
/// If this object has only a single object reference (i.e. this [`ComObject`] is the only
/// reference to the heap allocation), then this method will extract the inner `T`
/// (and return it in an `Ok`) and then free the heap allocation.
///
/// If there is more than one reference to this object, then this returns `Err(self)`.
#[inline(always)]
pub fn take(self) -> Result<T, Self> {
if self.is_reference_count_one() {
let outer_box: Box<T::Outer> = unsafe { core::mem::transmute(self) };
Ok(outer_box.into_inner())
} else {
Err(self)
}
}
/// Casts to a given interface type.
///
/// This always performs a `QueryInterface`, even if `T` is known to implement `I`.
/// If you know that `T` implements `I`, then use [`Self::as_interface`] or [`Self::to_interface`] because
/// those functions do not require a dynamic `QueryInterface` call.
#[inline(always)]
pub fn cast<I: Interface>(&self) -> windows_core::Result<I>
where
T::Outer: ComObjectInterface<IUnknown>,
{
let unknown = self.as_interface::<IUnknown>();
unknown.cast()
}
/// Gets a borrowed reference to an interface that is implemented by `T`.
///
/// The returned reference does not have an additional reference count.
/// You can AddRef it by calling [`Self::to_owned`].
#[inline(always)]
pub fn as_interface<I: Interface>(&self) -> InterfaceRef<'_, I>
where
T::Outer: ComObjectInterface<I>,
{
self.get_box().as_interface_ref()
}
/// Gets an owned (counted) reference to an interface that is implemented by this [`ComObject`].
#[inline(always)]
pub fn to_interface<I: Interface>(&self) -> I
where
T::Outer: ComObjectInterface<I>,
{
self.as_interface::<I>().to_owned()
}
/// Converts `self` into an interface that it implements.
///
/// This does not need to adjust reference counts because `self` is consumed.
#[inline(always)]
pub fn into_interface<I: Interface>(self) -> I
where
T::Outer: ComObjectInterface<I>,
{
unsafe {
let raw = self.get_box().as_interface_ref().as_raw();
core::mem::forget(self);
I::from_raw(raw)
}
}
/// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer"
/// object, e.g. `MyApp_Impl`, not the inner `MyApp` object.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method. However, note that the
/// returned `&dyn Any` refers to the _outer_ implementation object that was generated by
/// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`.
///
/// The returned value is an owned (counted) reference; this function calls `AddRef` on the
/// underlying COM object. If you do not need an owned reference, then you can use the
/// [`Interface::cast_object_ref`] method instead, and avoid the cost of `AddRef` / `Release`.
pub fn cast_from<I>(interface: &I) -> crate::Result<Self>
where
I: Interface,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
interface.cast_object()
}
}
impl<T: ComObjectInner + Default> Default for ComObject<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: ComObjectInner> Drop for ComObject<T> {
fn drop(&mut self) {
unsafe {
T::Outer::Release(self.ptr.as_ptr());
}
}
}
impl<T: ComObjectInner> Clone for ComObject<T> {
#[inline(always)]
fn clone(&self) -> Self {
unsafe {
self.ptr.as_ref().AddRef();
Self { ptr: self.ptr }
}
}
}
impl<T: ComObjectInner> AsRef<T> for ComObject<T>
where
IUnknown: From<T> + AsImpl<T>,
{
#[inline(always)]
fn as_ref(&self) -> &T {
self.get()
}
}
impl<T: ComObjectInner> Deref for ComObject<T> {
type Target = T::Outer;
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.get_box()
}
}
// There is no DerefMut implementation because we cannot statically guarantee
// that the reference count is 1, which is a requirement for getting exclusive
// access to the contents of the object. Use get_mut() for dynamically-checked
// exclusive access.
impl<T: ComObjectInner> From<T> for ComObject<T> {
fn from(value: T) -> ComObject<T> {
ComObject::new(value)
}
}
// Delegate hashing, if implemented.
impl<T: ComObjectInner + core::hash::Hash> core::hash::Hash for ComObject<T> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.get().hash(state);
}
}
// If T is Send (or Sync) then the ComObject<T> is also Send (or Sync).
// Since the actual object storage is in the heap, the object is never moved.
unsafe impl<T: ComObjectInner + Send> Send for ComObject<T> {}
unsafe impl<T: ComObjectInner + Sync> Sync for ComObject<T> {}
impl<T: ComObjectInner + PartialEq> PartialEq for ComObject<T> {
fn eq(&self, other: &ComObject<T>) -> bool {
let inner_self: &T = self.get();
let other_self: &T = other.get();
inner_self == other_self
}
}
impl<T: ComObjectInner + Eq> Eq for ComObject<T> {}
impl<T: ComObjectInner + PartialOrd> PartialOrd for ComObject<T> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
let inner_self: &T = self.get();
let other_self: &T = other.get();
<T as PartialOrd>::partial_cmp(inner_self, other_self)
}
}
impl<T: ComObjectInner + Ord> Ord for ComObject<T> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
let inner_self: &T = self.get();
let other_self: &T = other.get();
<T as Ord>::cmp(inner_self, other_self)
}
}
impl<T: ComObjectInner + core::fmt::Debug> core::fmt::Debug for ComObject<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
<T as core::fmt::Debug>::fmt(self.get(), f)
}
}
impl<T: ComObjectInner + core::fmt::Display> core::fmt::Display for ComObject<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
<T as core::fmt::Display>::fmt(self.get(), f)
}
}
impl<T: ComObjectInner> Borrow<T> for ComObject<T> {
fn borrow(&self) -> &T {
self.get()
}
}

287
vendor/windows-core-0.57.0/src/event.rs vendored Normal file
View File

@@ -0,0 +1,287 @@
use super::*;
use core::marker::PhantomData;
use core::mem::{size_of, transmute_copy};
use core::ptr::null_mut;
use std::sync::Mutex;
/// A type that you can use to declare and implement an event of a specified delegate type.
///
/// The implementation is thread-safe and designed to avoid contention between events being
/// raised and delegates being added or removed.
pub struct Event<T: Interface> {
swap: Mutex<()>,
change: Mutex<()>,
delegates: Array<T>,
}
impl<T: Interface> Default for Event<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Interface> Event<T> {
/// Creates a new, empty `Event<T>`.
pub fn new() -> Self {
Self {
delegates: Array::new(),
swap: Mutex::default(),
change: Mutex::default(),
}
}
/// Registers a delegate with the event object.
pub fn add(&mut self, delegate: &T) -> Result<i64> {
let mut _lock_free_drop = Array::new();
Ok({
let _change_lock = self.change.lock().unwrap();
let mut new_delegates = Array::with_capacity(self.delegates.len() + 1)?;
for delegate in self.delegates.as_slice() {
new_delegates.push(delegate.clone());
}
let delegate = Delegate::new(delegate)?;
let token = delegate.to_token();
new_delegates.push(delegate);
let _swap_lock = self.swap.lock().unwrap();
_lock_free_drop = self.delegates.swap(new_delegates);
token
})
}
/// Revokes a delegate's registration from the event object.
pub fn remove(&mut self, token: i64) -> Result<()> {
let mut _lock_free_drop = Array::new();
{
let _change_lock = self.change.lock().unwrap();
if self.delegates.is_empty() {
return Ok(());
}
let mut capacity = self.delegates.len() - 1;
let mut new_delegates = Array::new();
let mut removed = false;
if capacity == 0 {
removed = self.delegates.as_slice()[0].to_token() == token;
} else {
new_delegates = Array::with_capacity(capacity)?;
for delegate in self.delegates.as_slice() {
if !removed && delegate.to_token() == token {
removed = true;
continue;
}
if capacity == 0 {
break;
}
new_delegates.push(delegate.clone());
capacity -= 1;
}
}
if removed {
let _swap_lock = self.swap.lock().unwrap();
_lock_free_drop = self.delegates.swap(new_delegates);
}
}
Ok(())
}
/// Clears the event, removing all delegates.
pub fn clear(&mut self) {
let mut _lock_free_drop = Array::new();
{
let _change_lock = self.change.lock().unwrap();
if self.delegates.is_empty() {
return;
}
let _swap_lock = self.swap.lock().unwrap();
_lock_free_drop = self.delegates.swap(Array::new());
}
}
/// Invokes all of the event object's registered delegates with the provided callback.
pub fn call<F: FnMut(&T) -> Result<()>>(&mut self, mut callback: F) -> Result<()> {
let lock_free_calls = {
let _swap_lock = self.swap.lock().unwrap();
self.delegates.clone()
};
for delegate in lock_free_calls.as_slice() {
if let Err(error) = delegate.call(&mut callback) {
const RPC_E_SERVER_UNAVAILABLE: HRESULT = HRESULT(-2147023174); // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
if matches!(
error.code(),
imp::RPC_E_DISCONNECTED | imp::JSCRIPT_E_CANTEXECUTE | RPC_E_SERVER_UNAVAILABLE
) {
self.remove(delegate.to_token())?;
}
}
}
Ok(())
}
}
/// A thread-safe reference-counted array of delegates.
struct Array<T: Interface> {
buffer: *mut Buffer<T>,
len: usize,
_phantom: PhantomData<T>,
}
impl<T: Interface> Default for Array<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Interface> Array<T> {
/// Creates a new, empty `Array<T>` with no capacity.
fn new() -> Self {
Self {
buffer: null_mut(),
len: 0,
_phantom: PhantomData,
}
}
/// Creates a new, empty `Array<T>` with the specified capacity.
fn with_capacity(capacity: usize) -> Result<Self> {
Ok(Self {
buffer: Buffer::new(capacity)?,
len: 0,
_phantom: PhantomData,
})
}
/// Swaps the contents of two `Array<T>` objects.
fn swap(&mut self, mut other: Self) -> Self {
unsafe { core::ptr::swap(&mut self.buffer, &mut other.buffer) };
core::mem::swap(&mut self.len, &mut other.len);
other
}
/// Returns `true` if the array contains no delegates.
fn is_empty(&self) -> bool {
self.len == 0
}
/// Returns the number of delegates in the array.
fn len(&self) -> usize {
self.len
}
/// Appends a delegate to the back of the array.
fn push(&mut self, delegate: Delegate<T>) {
unsafe {
(*self.buffer).as_mut_ptr().add(self.len).write(delegate);
self.len += 1;
}
}
/// Returns a slice containing of all delegates.
fn as_slice(&self) -> &[Delegate<T>] {
if self.is_empty() {
&[]
} else {
unsafe { core::slice::from_raw_parts((*self.buffer).as_ptr(), self.len) }
}
}
/// Returns a mutable slice of all delegates.
fn as_mut_slice(&mut self) -> &mut [Delegate<T>] {
if self.is_empty() {
&mut []
} else {
unsafe { core::slice::from_raw_parts_mut((*self.buffer).as_mut_ptr(), self.len) }
}
}
}
impl<T: Interface> Clone for Array<T> {
fn clone(&self) -> Self {
if !self.is_empty() {
unsafe { (*self.buffer).0.add_ref() };
}
Self {
buffer: self.buffer,
len: self.len,
_phantom: PhantomData,
}
}
}
impl<T: Interface> Drop for Array<T> {
fn drop(&mut self) {
unsafe {
if !self.is_empty() && (*self.buffer).0.release() == 0 {
core::ptr::drop_in_place(self.as_mut_slice());
imp::heap_free(self.buffer as _)
}
}
}
}
/// A reference-counted buffer.
#[repr(C)]
#[repr(align(8))]
struct Buffer<T>(imp::RefCount, PhantomData<T>);
impl<T: Interface> Buffer<T> {
/// Creates a new `Buffer` with the specified size in bytes.
fn new(len: usize) -> Result<*mut Self> {
if len == 0 {
Ok(null_mut())
} else {
let alloc_size = size_of::<Self>() + len * size_of::<Delegate<T>>();
let header = imp::heap_alloc(alloc_size)? as *mut Self;
unsafe {
header.write(Self(imp::RefCount::new(1), PhantomData));
}
Ok(header)
}
}
/// Returns a raw pointer to the buffer's contents. The resulting pointer might be uninititalized.
fn as_ptr(&self) -> *const Delegate<T> {
unsafe { (self as *const Self).add(1) as *const _ }
}
/// Returns a raw mutable pointer to the buffer's contents. The resulting pointer might be uninititalized.
fn as_mut_ptr(&mut self) -> *mut Delegate<T> {
unsafe { (self as *mut Self).add(1) as *mut _ }
}
}
/// Holds either a direct or indirect reference to a delegate. A direct reference is typically
/// agile while an indirect reference is an agile wrapper.
#[derive(Clone)]
enum Delegate<T> {
Direct(T),
Indirect(AgileReference<T>),
}
impl<T: Interface> Delegate<T> {
/// Creates a new `Delegate<T>`, containing a suitable reference to the specified delegate.
fn new(delegate: &T) -> Result<Self> {
if delegate.cast::<imp::IAgileObject>().is_ok() {
Ok(Self::Direct(delegate.clone()))
} else {
Ok(Self::Indirect(AgileReference::new(delegate)?))
}
}
/// Returns an encoded token to identify the delegate.
fn to_token(&self) -> i64 {
unsafe {
match self {
Self::Direct(delegate) => imp::EncodePointer(transmute_copy(delegate)) as i64,
Self::Indirect(delegate) => imp::EncodePointer(transmute_copy(delegate)) as i64,
}
}
}
/// Invokes the delegates with the provided callback.
fn call<F: FnMut(&T) -> Result<()>>(&self, mut callback: F) -> Result<()> {
match self {
Self::Direct(delegate) => callback(delegate),
Self::Indirect(delegate) => callback(&delegate.resolve()?),
}
}
}

193
vendor/windows-core-0.57.0/src/guid.rs vendored Normal file
View File

@@ -0,0 +1,193 @@
#![allow(clippy::many_single_char_names)]
use super::*;
/// A globally unique identifier ([GUID](https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid))
/// used to identify COM and WinRT interfaces.
#[repr(C)]
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct GUID {
/// Specifies the first 8 hexadecimal digits.
pub data1: u32,
/// Specifies the first group of 4 hexadecimal digits.
pub data2: u16,
/// Specifies the second group of 4 hexadecimal digits.
pub data3: u16,
/// The first 2 bytes contain the third group of 4 hexadecimal digits. The remaining 6 bytes contain the final 12 hexadecimal digits.
pub data4: [u8; 8],
}
impl GUID {
/// Creates a unique `GUID` value.
pub fn new() -> Result<Self> {
unsafe { imp::CoCreateGuid() }
}
/// Creates a `GUID` represented by the all-zero byte-pattern.
pub const fn zeroed() -> Self {
Self {
data1: 0,
data2: 0,
data3: 0,
data4: [0, 0, 0, 0, 0, 0, 0, 0],
}
}
/// Creates a `GUID` with the given constant values.
pub const fn from_values(data1: u32, data2: u16, data3: u16, data4: [u8; 8]) -> Self {
Self {
data1,
data2,
data3,
data4,
}
}
/// Creates a `GUID` from a `u128` value.
pub const fn from_u128(uuid: u128) -> Self {
Self {
data1: (uuid >> 96) as u32,
data2: (uuid >> 80 & 0xffff) as u16,
data3: (uuid >> 64 & 0xffff) as u16,
data4: (uuid as u64).to_be_bytes(),
}
}
/// Converts a `GUID` to a `u128` value.
pub const fn to_u128(&self) -> u128 {
((self.data1 as u128) << 96)
+ ((self.data2 as u128) << 80)
+ ((self.data3 as u128) << 64)
+ u64::from_be_bytes(self.data4) as u128
}
/// Creates a `GUID` for a "generic" WinRT type.
pub const fn from_signature(signature: imp::ConstBuffer) -> Self {
let data = imp::ConstBuffer::from_slice(&[
0x11, 0xf4, 0x7a, 0xd5, 0x7b, 0x73, 0x42, 0xc0, 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16,
0xad, 0xee,
]);
let data = data.push_other(signature);
let bytes = imp::sha1(&data).bytes();
let first = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let second = u16::from_be_bytes([bytes[4], bytes[5]]);
let mut third = u16::from_be_bytes([bytes[6], bytes[7]]);
third = (third & 0x0fff) | (5 << 12);
let fourth = (bytes[8] & 0x3f) | 0x80;
Self::from_values(
first,
second,
third,
[
fourth, bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
],
)
}
}
impl RuntimeType for GUID {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice(b"g16");
}
impl TypeKind for GUID {
type TypeKind = CopyType;
}
impl core::fmt::Debug for GUID {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"{:08X?}-{:04X?}-{:04X?}-{:02X?}{:02X?}-{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}",
self.data1,
self.data2,
self.data3,
self.data4[0],
self.data4[1],
self.data4[2],
self.data4[3],
self.data4[4],
self.data4[5],
self.data4[6],
self.data4[7]
)
}
}
impl From<&str> for GUID {
fn from(value: &str) -> Self {
assert!(value.len() == 36, "Invalid GUID string");
let mut bytes = value.bytes();
let a = ((bytes.next_u32() * 16 + bytes.next_u32()) << 24)
+ ((bytes.next_u32() * 16 + bytes.next_u32()) << 16)
+ ((bytes.next_u32() * 16 + bytes.next_u32()) << 8)
+ bytes.next_u32() * 16
+ bytes.next_u32();
assert!(bytes.next().unwrap() == b'-', "Invalid GUID string");
let b = ((bytes.next_u16() * 16 + (bytes.next_u16())) << 8)
+ bytes.next_u16() * 16
+ bytes.next_u16();
assert!(bytes.next().unwrap() == b'-', "Invalid GUID string");
let c = ((bytes.next_u16() * 16 + bytes.next_u16()) << 8)
+ bytes.next_u16() * 16
+ bytes.next_u16();
assert!(bytes.next().unwrap() == b'-', "Invalid GUID string");
let d = bytes.next_u8() * 16 + bytes.next_u8();
let e = bytes.next_u8() * 16 + bytes.next_u8();
assert!(bytes.next().unwrap() == b'-', "Invalid GUID string");
let f = bytes.next_u8() * 16 + bytes.next_u8();
let g = bytes.next_u8() * 16 + bytes.next_u8();
let h = bytes.next_u8() * 16 + bytes.next_u8();
let i = bytes.next_u8() * 16 + bytes.next_u8();
let j = bytes.next_u8() * 16 + bytes.next_u8();
let k = bytes.next_u8() * 16 + bytes.next_u8();
Self::from_values(a, b, c, [d, e, f, g, h, i, j, k])
}
}
impl From<u128> for GUID {
fn from(value: u128) -> Self {
Self::from_u128(value)
}
}
impl From<GUID> for u128 {
fn from(value: GUID) -> Self {
value.to_u128()
}
}
trait HexReader {
fn next_u8(&mut self) -> u8;
fn next_u16(&mut self) -> u16;
fn next_u32(&mut self) -> u32;
}
impl HexReader for core::str::Bytes<'_> {
fn next_u8(&mut self) -> u8 {
let value = self.next().unwrap();
match value {
b'0'..=b'9' => value - b'0',
b'A'..=b'F' => 10 + value - b'A',
b'a'..=b'f' => 10 + value - b'a',
_ => panic!(),
}
}
fn next_u16(&mut self) -> u16 {
self.next_u8().into()
}
fn next_u32(&mut self) -> u32 {
self.next_u8().into()
}
}

View File

@@ -0,0 +1,46 @@
/// 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.
pub trait Free {
/// Calls the handle's free function.
///
/// # Safety
/// The handle must be owned by the caller and safe to free.
unsafe fn free(&mut self);
}
/// A wrapper to provide ownership for handles to automatically drop via the handle's [`Free`] trait.
#[repr(transparent)]
#[derive(PartialEq, Eq, Default, Debug)]
pub struct Owned<T: Free>(T);
impl<T: Free> Owned<T> {
/// Takes ownership of the handle.
///
/// # Safety
///
/// The handle must be owned by the caller and safe to free.
pub unsafe fn new(x: T) -> Self {
Self(x)
}
}
impl<T: Free> Drop for Owned<T> {
fn drop(&mut self) {
unsafe { self.0.free() };
}
}
impl<T: Free> core::ops::Deref for Owned<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Free> core::ops::DerefMut for Owned<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

View File

@@ -0,0 +1,678 @@
#![allow(
non_snake_case,
non_upper_case_globals,
non_camel_case_types,
dead_code,
clippy::all
)]
windows_targets::link!("api-ms-win-core-winrt-l1-1-0.dll" "system" fn RoGetActivationFactory(activatableclassid : * mut core::ffi::c_void, iid : *const GUID, factory : *mut *mut core::ffi::c_void) -> HRESULT);
windows_targets::link!("kernel32.dll" "system" fn CloseHandle(hobject : HANDLE) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn CreateEventW(lpeventattributes : *const SECURITY_ATTRIBUTES, bmanualreset : BOOL, binitialstate : BOOL, lpname : PCWSTR) -> HANDLE);
windows_targets::link!("kernel32.dll" "system" fn EncodePointer(ptr : *const core::ffi::c_void) -> *mut core::ffi::c_void);
windows_targets::link!("kernel32.dll" "system" fn FreeLibrary(hlibmodule : HMODULE) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : HMODULE, lpprocname : PCSTR) -> FARPROC);
windows_targets::link!("kernel32.dll" "system" fn GetProcessHeap() -> HANDLE);
windows_targets::link!("kernel32.dll" "system" fn HeapAlloc(hheap : HANDLE, dwflags : HEAP_FLAGS, dwbytes : usize) -> *mut core::ffi::c_void);
windows_targets::link!("kernel32.dll" "system" fn HeapFree(hheap : HANDLE, dwflags : HEAP_FLAGS, lpmem : *const core::ffi::c_void) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn LoadLibraryExA(lplibfilename : PCSTR, hfile : HANDLE, dwflags : LOAD_LIBRARY_FLAGS) -> HMODULE);
windows_targets::link!("kernel32.dll" "system" fn SetEvent(hevent : HANDLE) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn WaitForSingleObject(hhandle : HANDLE, dwmilliseconds : u32) -> WAIT_EVENT);
windows_targets::link!("ole32.dll" "system" fn CoIncrementMTAUsage(pcookie : *mut CO_MTA_USAGE_COOKIE) -> HRESULT);
windows_targets::link!("ole32.dll" "system" fn CoTaskMemAlloc(cb : usize) -> *mut core::ffi::c_void);
windows_targets::link!("ole32.dll" "system" fn CoTaskMemFree(pv : *const core::ffi::c_void));
windows_targets::link!("ole32.dll" "system" fn PropVariantClear(pvar : *mut PROPVARIANT) -> HRESULT);
windows_targets::link!("ole32.dll" "system" fn PropVariantCopy(pvardest : *mut PROPVARIANT, pvarsrc : *const PROPVARIANT) -> HRESULT);
windows_targets::link!("oleaut32.dll" "system" fn SysAllocStringLen(strin : PCWSTR, ui : u32) -> BSTR);
windows_targets::link!("oleaut32.dll" "system" fn SysFreeString(bstrstring : BSTR));
windows_targets::link!("oleaut32.dll" "system" fn SysStringLen(pbstr : BSTR) -> u32);
windows_targets::link!("oleaut32.dll" "system" fn VariantClear(pvarg : *mut VARIANT) -> HRESULT);
windows_targets::link!("oleaut32.dll" "system" fn VariantCopy(pvargdest : *mut VARIANT, pvargsrc : *const VARIANT) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantCompareEx(propvar1 : *const PROPVARIANT, propvar2 : *const PROPVARIANT, unit : PROPVAR_COMPARE_UNIT, flags : PROPVAR_COMPARE_FLAGS) -> i32);
windows_targets::link!("propsys.dll" "system" fn PropVariantToBSTR(propvar : *const PROPVARIANT, pbstrout : *mut BSTR) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToBoolean(propvarin : *const PROPVARIANT, pfret : *mut BOOL) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToDouble(propvarin : *const PROPVARIANT, pdblret : *mut f64) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToInt16(propvarin : *const PROPVARIANT, piret : *mut i16) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToInt32(propvarin : *const PROPVARIANT, plret : *mut i32) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToInt64(propvarin : *const PROPVARIANT, pllret : *mut i64) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToUInt16(propvarin : *const PROPVARIANT, puiret : *mut u16) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToUInt32(propvarin : *const PROPVARIANT, pulret : *mut u32) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToUInt64(propvarin : *const PROPVARIANT, pullret : *mut u64) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn PropVariantToVariant(ppropvar : *const PROPVARIANT, pvar : *mut VARIANT) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToBoolean(varin : *const VARIANT, pfret : *mut BOOL) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToDouble(varin : *const VARIANT, pdblret : *mut f64) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToInt16(varin : *const VARIANT, piret : *mut i16) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToInt32(varin : *const VARIANT, plret : *mut i32) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToInt64(varin : *const VARIANT, pllret : *mut i64) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToPropVariant(pvar : *const VARIANT, ppropvar : *mut PROPVARIANT) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToUInt16(varin : *const VARIANT, puiret : *mut u16) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToUInt32(varin : *const VARIANT, pulret : *mut u32) -> HRESULT);
windows_targets::link!("propsys.dll" "system" fn VariantToUInt64(varin : *const VARIANT, pullret : *mut u64) -> HRESULT);
pub type ADVANCED_FEATURE_FLAGS = u16;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct ARRAYDESC {
pub tdescElem: TYPEDESC,
pub cDims: u16,
pub rgbounds: [SAFEARRAYBOUND; 1],
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union BINDPTR {
pub lpfuncdesc: *mut FUNCDESC,
pub lpvardesc: *mut VARDESC,
pub lptcomp: *mut core::ffi::c_void,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct BLOB {
pub cbSize: u32,
pub pBlobData: *mut u8,
}
pub type BOOL = i32;
pub type BSTR = *const u16;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct BSTRBLOB {
pub cbSize: u32,
pub pData: *mut u8,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CABOOL {
pub cElems: u32,
pub pElems: *mut VARIANT_BOOL,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CABSTR {
pub cElems: u32,
pub pElems: *mut BSTR,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CABSTRBLOB {
pub cElems: u32,
pub pElems: *mut BSTRBLOB,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAC {
pub cElems: u32,
pub pElems: PSTR,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CACLIPDATA {
pub cElems: u32,
pub pElems: *mut CLIPDATA,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CACLSID {
pub cElems: u32,
pub pElems: *mut GUID,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CACY {
pub cElems: u32,
pub pElems: *mut CY,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CADATE {
pub cElems: u32,
pub pElems: *mut f64,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CADBL {
pub cElems: u32,
pub pElems: *mut f64,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAFILETIME {
pub cElems: u32,
pub pElems: *mut FILETIME,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAFLT {
pub cElems: u32,
pub pElems: *mut f32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAH {
pub cElems: u32,
pub pElems: *mut i64,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAI {
pub cElems: u32,
pub pElems: *mut i16,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAL {
pub cElems: u32,
pub pElems: *mut i32,
}
pub type CALLCONV = i32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CALPSTR {
pub cElems: u32,
pub pElems: *mut PSTR,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CALPWSTR {
pub cElems: u32,
pub pElems: *mut PWSTR,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAPROPVARIANT {
pub cElems: u32,
pub pElems: *mut PROPVARIANT,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CASCODE {
pub cElems: u32,
pub pElems: *mut i32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAUB {
pub cElems: u32,
pub pElems: *mut u8,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAUH {
pub cElems: u32,
pub pElems: *mut u64,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAUI {
pub cElems: u32,
pub pElems: *mut u16,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CAUL {
pub cElems: u32,
pub pElems: *mut u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CLIPDATA {
pub cbSize: u32,
pub ulClipFmt: i32,
pub pClipData: *mut u8,
}
pub type CO_MTA_USAGE_COOKIE = isize;
#[repr(C)]
#[derive(Clone, Copy)]
pub union CY {
pub Anonymous: CY_0,
pub int64: i64,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CY_0 {
pub Lo: u32,
pub Hi: i32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DECIMAL {
pub wReserved: u16,
pub Anonymous1: DECIMAL_0,
pub Hi32: u32,
pub Anonymous2: DECIMAL_1,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union DECIMAL_0 {
pub Anonymous: DECIMAL_0_0,
pub signscale: u16,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DECIMAL_0_0 {
pub scale: u8,
pub sign: u8,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union DECIMAL_1 {
pub Anonymous: DECIMAL_1_0,
pub Lo64: u64,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DECIMAL_1_0 {
pub Lo32: u32,
pub Mid32: u32,
}
pub type DESCKIND = i32;
pub type DISPATCH_FLAGS = u16;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct DISPPARAMS {
pub rgvarg: *mut VARIANT,
pub rgdispidNamedArgs: *mut i32,
pub cArgs: u32,
pub cNamedArgs: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct ELEMDESC {
pub tdesc: TYPEDESC,
pub Anonymous: ELEMDESC_0,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union ELEMDESC_0 {
pub idldesc: IDLDESC,
pub paramdesc: PARAMDESC,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct EXCEPINFO {
pub wCode: u16,
pub wReserved: u16,
pub bstrSource: BSTR,
pub bstrDescription: BSTR,
pub bstrHelpFile: BSTR,
pub dwHelpContext: u32,
pub pvReserved: *mut core::ffi::c_void,
pub pfnDeferredFillIn: LPEXCEPFINO_DEFERRED_FILLIN,
pub scode: i32,
}
pub type FARPROC = Option<unsafe extern "system" fn() -> isize>;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct FILETIME {
pub dwLowDateTime: u32,
pub dwHighDateTime: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct FUNCDESC {
pub memid: i32,
pub lprgscode: *mut i32,
pub lprgelemdescParam: *mut ELEMDESC,
pub funckind: FUNCKIND,
pub invkind: INVOKEKIND,
pub callconv: CALLCONV,
pub cParams: i16,
pub cParamsOpt: i16,
pub oVft: i16,
pub cScodes: i16,
pub elemdescFunc: ELEMDESC,
pub wFuncFlags: FUNCFLAGS,
}
pub type FUNCFLAGS = u16;
pub type FUNCKIND = i32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct GUID {
pub data1: u32,
pub data2: u16,
pub data3: u16,
pub data4: [u8; 8],
}
impl GUID {
pub const fn from_u128(uuid: u128) -> Self {
Self {
data1: (uuid >> 96) as u32,
data2: (uuid >> 80 & 0xffff) as u16,
data3: (uuid >> 64 & 0xffff) as u16,
data4: (uuid as u64).to_be_bytes(),
}
}
}
pub type HANDLE = isize;
pub type HEAP_FLAGS = u32;
pub type HMODULE = isize;
pub type HRESULT = i32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct IDLDESC {
pub dwReserved: usize,
pub wIDLFlags: IDLFLAGS,
}
pub type IDLFLAGS = u16;
pub type IMPLTYPEFLAGS = i32;
pub type INVOKEKIND = i32;
pub type LOAD_LIBRARY_FLAGS = u32;
pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: LOAD_LIBRARY_FLAGS = 4096u32;
pub type LPEXCEPFINO_DEFERRED_FILLIN =
Option<unsafe extern "system" fn(pexcepinfo: *mut EXCEPINFO) -> HRESULT>;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct PARAMDESC {
pub pparamdescex: *mut PARAMDESCEX,
pub wParamFlags: PARAMFLAGS,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct PARAMDESCEX {
pub cBytes: u32,
pub varDefaultValue: VARIANT,
}
pub type PARAMFLAGS = u16;
pub type PCSTR = *const u8;
pub type PCWSTR = *const u16;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct PROPVARIANT {
pub Anonymous: PROPVARIANT_0,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union PROPVARIANT_0 {
pub Anonymous: PROPVARIANT_0_0,
pub decVal: DECIMAL,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct PROPVARIANT_0_0 {
pub vt: VARENUM,
pub wReserved1: u16,
pub wReserved2: u16,
pub wReserved3: u16,
pub Anonymous: PROPVARIANT_0_0_0,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union PROPVARIANT_0_0_0 {
pub cVal: i8,
pub bVal: u8,
pub iVal: i16,
pub uiVal: u16,
pub lVal: i32,
pub ulVal: u32,
pub intVal: i32,
pub uintVal: u32,
pub hVal: i64,
pub uhVal: u64,
pub fltVal: f32,
pub dblVal: f64,
pub boolVal: VARIANT_BOOL,
pub __OBSOLETE__VARIANT_BOOL: VARIANT_BOOL,
pub scode: i32,
pub cyVal: CY,
pub date: f64,
pub filetime: FILETIME,
pub puuid: *mut GUID,
pub pclipdata: *mut CLIPDATA,
pub bstrVal: BSTR,
pub bstrblobVal: BSTRBLOB,
pub blob: BLOB,
pub pszVal: PSTR,
pub pwszVal: PWSTR,
pub punkVal: *mut core::ffi::c_void,
pub pdispVal: *mut core::ffi::c_void,
pub pStream: *mut core::ffi::c_void,
pub pStorage: *mut core::ffi::c_void,
pub pVersionedStream: *mut VERSIONEDSTREAM,
pub parray: *mut SAFEARRAY,
pub cac: CAC,
pub caub: CAUB,
pub cai: CAI,
pub caui: CAUI,
pub cal: CAL,
pub caul: CAUL,
pub cah: CAH,
pub cauh: CAUH,
pub caflt: CAFLT,
pub cadbl: CADBL,
pub cabool: CABOOL,
pub cascode: CASCODE,
pub cacy: CACY,
pub cadate: CADATE,
pub cafiletime: CAFILETIME,
pub cauuid: CACLSID,
pub caclipdata: CACLIPDATA,
pub cabstr: CABSTR,
pub cabstrblob: CABSTRBLOB,
pub calpstr: CALPSTR,
pub calpwstr: CALPWSTR,
pub capropvar: CAPROPVARIANT,
pub pcVal: PSTR,
pub pbVal: *mut u8,
pub piVal: *mut i16,
pub puiVal: *mut u16,
pub plVal: *mut i32,
pub pulVal: *mut u32,
pub pintVal: *mut i32,
pub puintVal: *mut u32,
pub pfltVal: *mut f32,
pub pdblVal: *mut f64,
pub pboolVal: *mut VARIANT_BOOL,
pub pdecVal: *mut DECIMAL,
pub pscode: *mut i32,
pub pcyVal: *mut CY,
pub pdate: *mut f64,
pub pbstrVal: *mut BSTR,
pub ppunkVal: *mut *mut core::ffi::c_void,
pub ppdispVal: *mut *mut core::ffi::c_void,
pub pparray: *mut *mut SAFEARRAY,
pub pvarVal: *mut PROPVARIANT,
}
pub type PROPVAR_COMPARE_FLAGS = i32;
pub type PROPVAR_COMPARE_UNIT = i32;
pub type PSTR = *mut u8;
pub type PWSTR = *mut u16;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SAFEARRAY {
pub cDims: u16,
pub fFeatures: ADVANCED_FEATURE_FLAGS,
pub cbElements: u32,
pub cLocks: u32,
pub pvData: *mut core::ffi::c_void,
pub rgsabound: [SAFEARRAYBOUND; 1],
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SAFEARRAYBOUND {
pub cElements: u32,
pub lLbound: i32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SECURITY_ATTRIBUTES {
pub nLength: u32,
pub lpSecurityDescriptor: *mut core::ffi::c_void,
pub bInheritHandle: BOOL,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct STATSTG {
pub pwcsName: PWSTR,
pub r#type: u32,
pub cbSize: u64,
pub mtime: FILETIME,
pub ctime: FILETIME,
pub atime: FILETIME,
pub grfMode: STGM,
pub grfLocksSupported: u32,
pub clsid: GUID,
pub grfStateBits: u32,
pub reserved: u32,
}
pub type STGM = u32;
pub type STREAM_SEEK = u32;
pub type SYSKIND = i32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct TLIBATTR {
pub guid: GUID,
pub lcid: u32,
pub syskind: SYSKIND,
pub wMajorVerNum: u16,
pub wMinorVerNum: u16,
pub wLibFlags: u16,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct TYPEATTR {
pub guid: GUID,
pub lcid: u32,
pub dwReserved: u32,
pub memidConstructor: i32,
pub memidDestructor: i32,
pub lpstrSchema: PWSTR,
pub cbSizeInstance: u32,
pub typekind: TYPEKIND,
pub cFuncs: u16,
pub cVars: u16,
pub cImplTypes: u16,
pub cbSizeVft: u16,
pub cbAlignment: u16,
pub wTypeFlags: u16,
pub wMajorVerNum: u16,
pub wMinorVerNum: u16,
pub tdescAlias: TYPEDESC,
pub idldescType: IDLDESC,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct TYPEDESC {
pub Anonymous: TYPEDESC_0,
pub vt: VARENUM,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union TYPEDESC_0 {
pub lptdesc: *mut TYPEDESC,
pub lpadesc: *mut ARRAYDESC,
pub hreftype: u32,
}
pub type TYPEKIND = i32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct VARDESC {
pub memid: i32,
pub lpstrSchema: PWSTR,
pub Anonymous: VARDESC_0,
pub elemdescVar: ELEMDESC,
pub wVarFlags: VARFLAGS,
pub varkind: VARKIND,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union VARDESC_0 {
pub oInst: u32,
pub lpvarValue: *mut VARIANT,
}
pub type VARENUM = u16;
pub type VARFLAGS = u16;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct VARIANT {
pub Anonymous: VARIANT_0,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union VARIANT_0 {
pub Anonymous: VARIANT_0_0,
pub decVal: DECIMAL,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct VARIANT_0_0 {
pub vt: VARENUM,
pub wReserved1: u16,
pub wReserved2: u16,
pub wReserved3: u16,
pub Anonymous: VARIANT_0_0_0,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union VARIANT_0_0_0 {
pub llVal: i64,
pub lVal: i32,
pub bVal: u8,
pub iVal: i16,
pub fltVal: f32,
pub dblVal: f64,
pub boolVal: VARIANT_BOOL,
pub __OBSOLETE__VARIANT_BOOL: VARIANT_BOOL,
pub scode: i32,
pub cyVal: CY,
pub date: f64,
pub bstrVal: BSTR,
pub punkVal: *mut core::ffi::c_void,
pub pdispVal: *mut core::ffi::c_void,
pub parray: *mut SAFEARRAY,
pub pbVal: *mut u8,
pub piVal: *mut i16,
pub plVal: *mut i32,
pub pllVal: *mut i64,
pub pfltVal: *mut f32,
pub pdblVal: *mut f64,
pub pboolVal: *mut VARIANT_BOOL,
pub __OBSOLETE__VARIANT_PBOOL: *mut VARIANT_BOOL,
pub pscode: *mut i32,
pub pcyVal: *mut CY,
pub pdate: *mut f64,
pub pbstrVal: *mut BSTR,
pub ppunkVal: *mut *mut core::ffi::c_void,
pub ppdispVal: *mut *mut core::ffi::c_void,
pub pparray: *mut *mut SAFEARRAY,
pub pvarVal: *mut VARIANT,
pub byref: *mut core::ffi::c_void,
pub cVal: i8,
pub uiVal: u16,
pub ulVal: u32,
pub ullVal: u64,
pub intVal: i32,
pub uintVal: u32,
pub pdecVal: *mut DECIMAL,
pub pcVal: PSTR,
pub puiVal: *mut u16,
pub pulVal: *mut u32,
pub pullVal: *mut u64,
pub pintVal: *mut i32,
pub puintVal: *mut u32,
pub Anonymous: VARIANT_0_0_0_0,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct VARIANT_0_0_0_0 {
pub pvRecord: *mut core::ffi::c_void,
pub pRecInfo: *mut core::ffi::c_void,
}
pub type VARIANT_BOOL = i16;
pub type VARKIND = i32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct VERSIONEDSTREAM {
pub guidVersion: GUID,
pub pStream: *mut core::ffi::c_void,
}
pub const VT_BOOL: VARENUM = 11u16;
pub const VT_BSTR: VARENUM = 8u16;
pub const VT_EMPTY: VARENUM = 0u16;
pub const VT_I1: VARENUM = 16u16;
pub const VT_I2: VARENUM = 2u16;
pub const VT_I4: VARENUM = 3u16;
pub const VT_I8: VARENUM = 20u16;
pub const VT_R4: VARENUM = 4u16;
pub const VT_R8: VARENUM = 5u16;
pub const VT_UI1: VARENUM = 17u16;
pub const VT_UI2: VARENUM = 18u16;
pub const VT_UI4: VARENUM = 19u16;
pub const VT_UI8: VARENUM = 21u16;
pub const VT_UNKNOWN: VARENUM = 13u16;
pub type WAIT_EVENT = u32;

View File

@@ -0,0 +1,5 @@
pub trait CanInto<T>: Sized {
const QUERY: bool = false;
}
impl<T> CanInto<T> for T where T: Clone {}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
use super::*;
/// Attempts to load a function from a given library.
///
/// This is a small wrapper around `LoadLibrary` and `GetProcAddress`.
///
/// # Safety
///
/// * Both the library and function names must be valid null-terminated strings.
pub unsafe fn delay_load<T>(library: crate::PCSTR, function: crate::PCSTR) -> Option<T> {
let library = LoadLibraryExA(library.0, 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
if library == 0 {
return None;
}
let address = GetProcAddress(library, function.0);
if address.is_some() {
return Some(core::mem::transmute_copy(&address));
}
FreeLibrary(library);
None
}

View File

@@ -0,0 +1,190 @@
use super::*;
use crate::Interface;
use core::ffi::c_void;
use core::marker::PhantomData;
use core::mem::{forget, transmute, transmute_copy};
use core::ptr::null_mut;
use core::sync::atomic::{AtomicPtr, Ordering};
#[doc(hidden)]
pub struct FactoryCache<C, I> {
shared: AtomicPtr<c_void>,
_c: PhantomData<C>,
_i: PhantomData<I>,
}
impl<C, I> FactoryCache<C, I> {
pub const fn new() -> Self {
Self {
shared: AtomicPtr::new(null_mut()),
_c: PhantomData,
_i: PhantomData,
}
}
}
impl<C, I> Default for FactoryCache<C, I> {
fn default() -> Self {
Self::new()
}
}
impl<C: crate::RuntimeName, I: Interface> FactoryCache<C, I> {
pub fn call<R, F: FnOnce(&I) -> crate::Result<R>>(&self, callback: F) -> crate::Result<R> {
loop {
// Attempt to load a previously cached factory pointer.
let ptr = self.shared.load(Ordering::Relaxed);
// If a pointer is found, the cache is primed and we're good to go.
if !ptr.is_null() {
return callback(unsafe { transmute::<&*mut c_void, &I>(&ptr) });
}
// Otherwise, we load the factory the usual way.
let factory = factory::<C, I>()?;
// If the factory is agile, we can safely cache it.
if factory.cast::<IAgileObject>().is_ok() {
if self
.shared
.compare_exchange_weak(
null_mut(),
factory.as_raw(),
Ordering::Relaxed,
Ordering::Relaxed,
)
.is_ok()
{
forget(factory);
}
} else {
// Otherwise, for non-agile factories we simply use the factory
// and discard after use as it is not safe to cache.
return callback(&factory);
}
}
}
}
// This is safe because `FactoryCache` only holds agile factory pointers, which are safe to cache and share between threads.
unsafe impl<C, I> Sync for FactoryCache<C, I> {}
/// Attempts to load the factory object for the given WinRT class.
/// This can be used to access COM interfaces implemented on a Windows Runtime class factory.
pub fn factory<C: crate::RuntimeName, I: Interface>() -> crate::Result<I> {
let mut factory: Option<I> = None;
let name = crate::HSTRING::from(C::NAME);
let code = unsafe {
let mut get_com_factory = || {
crate::HRESULT(RoGetActivationFactory(
transmute_copy(&name),
&I::IID as *const _ as _,
&mut factory as *mut _ as *mut _,
))
};
let mut code = get_com_factory();
// If RoGetActivationFactory fails because combase hasn't been loaded yet then load combase
// automatically so that it "just works" for apartment-agnostic code.
if code == CO_E_NOTINITIALIZED {
let mut cookie = 0;
CoIncrementMTAUsage(&mut cookie);
// Now try a second time to get the activation factory via the OS.
code = get_com_factory();
}
code
};
// If this succeeded then return the resulting factory interface.
if let Some(factory) = factory {
return Ok(factory);
}
// If not, first capture the error information from the failure above so that we
// can ultimately return this error information if all else fails.
let original: crate::Error = code.into();
// Now attempt to find the factory's implementation heuristically.
if let Some(i) = search_path(C::NAME, |library| unsafe {
get_activation_factory(library, &name)
}) {
i.cast()
} else {
Err(original)
}
}
// Remove the suffix until a match is found appending `.dll\0` at the end
///
/// For example, if the class name is
/// "A.B.TypeName" then the attempted load order will be:
/// 1. A.B.dll
/// 2. A.dll
fn search_path<F, R>(mut path: &str, mut callback: F) -> Option<R>
where
F: FnMut(crate::PCSTR) -> crate::Result<R>,
{
let suffix = b".dll\0";
let mut library = vec![0; path.len() + suffix.len()];
while let Some(pos) = path.rfind('.') {
path = &path[..pos];
library.truncate(path.len() + suffix.len());
library[..path.len()].copy_from_slice(path.as_bytes());
library[path.len()..].copy_from_slice(suffix);
if let Ok(r) = callback(crate::PCSTR::from_raw(library.as_ptr())) {
return Some(r);
}
}
None
}
unsafe fn get_activation_factory(
library: crate::PCSTR,
name: &crate::HSTRING,
) -> crate::Result<IGenericFactory> {
let function =
delay_load::<DllGetActivationFactory>(library, crate::s!("DllGetActivationFactory"))
.ok_or_else(crate::Error::from_win32)?;
let mut abi = null_mut();
function(transmute_copy(name), &mut abi).and_then(|| crate::Type::from_abi(abi))
}
type DllGetActivationFactory =
extern "system" fn(name: *mut c_void, factory: *mut *mut c_void) -> crate::HRESULT;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dll_search() {
let path = "A.B.TypeName";
// Test library successfully found
let mut results = Vec::new();
let end_result = search_path(path, |library| {
results.push(unsafe { library.to_string().unwrap() });
if unsafe { library.as_bytes() } == &b"A.dll"[..] {
Ok(42)
} else {
Err(crate::Error::empty())
}
});
assert!(matches!(end_result, Some(42)));
assert_eq!(results, vec!["A.B.dll", "A.dll"]);
// Test library never successfully found
let mut results = Vec::new();
let end_result = search_path(path, |library| {
results.push(unsafe { library.to_string().unwrap() });
crate::Result::<()>::Err(crate::Error::empty())
});
assert!(end_result.is_none());
assert_eq!(results, vec!["A.B.dll", "A.dll"]);
}
}

View File

@@ -0,0 +1,33 @@
use crate::Interface;
use core::ffi::c_void;
use core::mem::{transmute_copy, zeroed};
// A streamlined version of the IActivationFactory interface used by WinRT class factories used internally by the windows crate
// to simplify code generation. Components should implement the `IActivationFactory` interface published by the windows crate.
super::define_interface!(
IGenericFactory,
IGenericFactory_Vtbl,
0x00000035_0000_0000_c000_000000000046
);
super::interface_hierarchy!(IGenericFactory, crate::IUnknown, crate::IInspectable);
impl IGenericFactory {
pub fn ActivateInstance<I: Interface>(&self) -> crate::Result<I> {
unsafe {
let mut result__ = zeroed();
(Interface::vtable(self).ActivateInstance)(
transmute_copy(self),
&mut result__ as *mut _ as *mut _,
)
.and_then(|| crate::Type::from_abi(result__))
.and_then(|interface: crate::IInspectable| interface.cast())
}
}
}
#[repr(C)]
pub struct IGenericFactory_Vtbl {
pub base__: crate::IInspectable_Vtbl,
pub ActivateInstance:
unsafe extern "system" fn(this: *mut c_void, instance: *mut *mut c_void) -> crate::HRESULT,
}

View File

@@ -0,0 +1,36 @@
use super::*;
use core::ffi::c_void;
/// Allocate memory of size `bytes` using `HeapAlloc`.
///
/// The memory allocated by this function is uninitialized.
///
/// This function will fail in OOM situations, if the heap is otherwise corrupt,
/// or if getting a handle to the process heap fails.
pub fn heap_alloc(bytes: usize) -> crate::Result<*mut c_void> {
let ptr = unsafe { HeapAlloc(GetProcessHeap(), 0, bytes) };
if ptr.is_null() {
Err(E_OUTOFMEMORY.into())
} else {
// HeapAlloc is not guaranteed to return zero memory but usually does. This just ensures that
// it predictably returns non-zero memory for testing purposes. This is similar to what MSVC's
// debug allocator does for the same reason.
#[cfg(debug_assertions)]
unsafe {
core::ptr::write_bytes(ptr, 0xCC, bytes);
}
Ok(ptr)
}
}
/// Free memory allocated by `HeapAlloc` or `HeapReAlloc`.
///
/// The pointer is allowed to be null.
///
/// # Safety
///
/// `ptr` must be a valid pointer to memory allocated by `HeapAlloc` or `HeapReAlloc`
pub unsafe fn heap_free(ptr: *mut c_void) {
HeapFree(GetProcessHeap(), 0, ptr);
}

View File

@@ -0,0 +1,115 @@
mod bindings;
mod can_into;
mod com_bindings;
mod delay_load;
mod factory_cache;
mod generic_factory;
mod heap;
mod ref_count;
mod sha1;
mod waiter;
mod weak_ref_count;
pub use bindings::*;
pub use can_into::*;
pub use com_bindings::*;
pub use delay_load::*;
pub use factory_cache::*;
pub use generic_factory::*;
pub use heap::*;
pub use ref_count::*;
pub use sha1::*;
pub use waiter::*;
pub use weak_ref_count::*;
pub fn wide_trim_end(mut wide: &[u16]) -> &[u16] {
while let Some(last) = wide.last() {
match last {
32 | 9..=13 => wide = &wide[..wide.len() - 1],
_ => break,
}
}
wide
}
#[doc(hidden)]
#[macro_export]
macro_rules! interface_hierarchy {
($child:ident, $parent:ty) => {
impl ::windows_core::imp::CanInto<$parent> for $child {}
impl ::core::convert::From<&$child> for &$parent {
fn from(value: &$child) -> Self {
unsafe { ::core::mem::transmute(value) }
}
}
impl ::core::convert::From<$child> for $parent {
fn from(value: $child) -> Self {
unsafe { ::core::mem::transmute(value) }
}
}
};
($child:ident, $first:ty, $($rest:ty),+) => {
$crate::imp::interface_hierarchy!($child, $first);
$crate::imp::interface_hierarchy!($child, $($rest),+);
};
}
#[doc(hidden)]
pub use interface_hierarchy;
#[doc(hidden)]
#[macro_export]
macro_rules! required_hierarchy {
($child:ident, $parent:ty) => {
impl ::windows_core::imp::CanInto<$parent> for $child { const QUERY: bool = true; }
};
($child:ident, $first:ty, $($rest:ty),+) => {
$crate::imp::required_hierarchy!($child, $first);
$crate::imp::required_hierarchy!($child, $($rest),+);
};
}
#[doc(hidden)]
pub use required_hierarchy;
#[doc(hidden)]
#[macro_export]
macro_rules! define_interface {
($name:ident, $vtbl:ident, $iid:literal) => {
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::clone::Clone)]
pub struct $name(::windows_core::IUnknown);
unsafe impl ::windows_core::Interface for $name {
type Vtable = $vtbl;
const IID: ::windows_core::GUID = ::windows_core::GUID::from_u128($iid);
}
impl ::core::fmt::Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple(stringify!($name))
.field(&::windows_core::Interface::as_raw(self))
.finish()
}
}
};
($name:ident, $vtbl:ident) => {
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::clone::Clone)]
pub struct $name(::std::ptr::NonNull<::std::ffi::c_void>);
unsafe impl ::windows_core::Interface for $name {
type Vtable = $vtbl;
const IID: ::windows_core::GUID = ::windows_core::GUID::zeroed();
const UNKNOWN: bool = false;
}
impl ::core::fmt::Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple(stringify!($name)).field(&self.0).finish()
}
}
};
}
#[doc(hidden)]
pub use define_interface;
#[doc(hidden)]
pub use alloc::boxed::Box;

View File

@@ -0,0 +1,34 @@
use core::sync::atomic::{fence, AtomicI32, Ordering};
#[doc(hidden)]
#[repr(transparent)]
#[derive(Default)]
pub struct RefCount(pub(crate) AtomicI32);
impl RefCount {
/// Creates a new `RefCount` with an initial value of `1`.
pub fn new(count: u32) -> Self {
Self(AtomicI32::new(count as i32))
}
/// Increments the reference count, returning the new value.
pub fn add_ref(&self) -> u32 {
(self.0.fetch_add(1, Ordering::Relaxed) + 1) as u32
}
/// Decrements the reference count, returning the new value.
///
/// This operation inserts an `Acquire` fence when the reference count reaches zero.
/// This prevents reordering before the object is destroyed.
pub fn release(&self) -> u32 {
let remaining = self.0.fetch_sub(1, Ordering::Release) - 1;
match remaining.cmp(&0) {
core::cmp::Ordering::Equal => fence(Ordering::Acquire),
core::cmp::Ordering::Less => panic!("Object has been over-released."),
core::cmp::Ordering::Greater => {}
}
remaining as u32
}
}

View File

@@ -0,0 +1,483 @@
#![allow(clippy::many_single_char_names)]
pub const fn sha1(data: &ConstBuffer) -> Digest {
let state: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
let len: u64 = 0;
let blocks = Blocks {
len: 0,
data: [0; 64],
};
let (blocks, len, state) = process_blocks(blocks, data, len, state);
digest(state, len, blocks)
}
const BUFFER_SIZE: usize = 1024;
pub struct ConstBuffer {
data: [u8; BUFFER_SIZE],
head: usize,
}
impl ConstBuffer {
pub const fn for_class<C: crate::RuntimeName, I: crate::RuntimeType>() -> Self {
Self::new()
.push_slice(b"rc(")
.push_slice(C::NAME.as_bytes())
.push(b';')
.push_other(I::SIGNATURE)
.push(b')')
}
pub const fn for_interface<T: crate::Interface>() -> Self {
Self::new().push_guid(&T::IID)
}
pub const fn from_slice(slice: &[u8]) -> Self {
let s = Self::new();
s.push_slice(slice)
}
pub const fn new() -> Self {
Self {
data: [0; BUFFER_SIZE],
head: 0,
}
}
pub const fn push_slice(self, slice: &[u8]) -> Self {
self.push_amount(slice, slice.len())
}
const fn get(&self, index: usize) -> u8 {
self.data[index]
}
const fn len(&self) -> usize {
self.head
}
pub fn as_slice(&self) -> &[u8] {
&self.data[..self.head]
}
pub const fn push_other(self, other: Self) -> Self {
self.push_amount(&other.data, other.len())
}
const fn push(mut self, value: u8) -> Self {
self.data[self.head] = value;
self.head += 1;
self
}
const fn push_hex_u8(self, value: u8) -> Self {
const fn digit(mut value: u8) -> u8 {
value &= 0xF;
if value < 10 {
b'0' + value
} else {
b'a' + (value - 10)
}
}
self.push(digit(value >> 4)).push(digit(value))
}
const fn push_hex_u16(self, value: u16) -> Self {
self.push_hex_u8((value >> 8) as u8)
.push_hex_u8((value & 0xFF) as u8)
}
const fn push_hex_u32(self, value: u32) -> Self {
self.push_hex_u16((value >> 16) as u16)
.push_hex_u16((value & 0xFFFF) as u16)
}
const fn push_amount(mut self, slice: &[u8], amount: usize) -> Self {
let mut i = 0;
while i < amount {
self.data[self.head + i] = slice[i];
i += 1;
}
self.head += i;
self
}
const fn push_guid(self, guid: &crate::GUID) -> Self {
self.push(b'{')
.push_hex_u32(guid.data1)
.push(b'-')
.push_hex_u16(guid.data2)
.push(b'-')
.push_hex_u16(guid.data3)
.push(b'-')
.push_hex_u16((guid.data4[0] as u16) << 8 | guid.data4[1] as u16)
.push(b'-')
.push_hex_u16((guid.data4[2] as u16) << 8 | guid.data4[3] as u16)
.push_hex_u16((guid.data4[4] as u16) << 8 | guid.data4[5] as u16)
.push_hex_u16((guid.data4[6] as u16) << 8 | guid.data4[7] as u16)
.push(b'}')
}
}
struct Blocks {
len: u32,
data: [u8; 64],
}
const fn process_blocks(
mut blocks: Blocks,
data: &ConstBuffer,
mut len: u64,
mut state: [u32; 5],
) -> (Blocks, u64, [u32; 5]) {
const fn as_block(input: &ConstBuffer, offset: usize) -> [u32; 16] {
let mut result = [0u32; 16];
let mut i = 0;
while i != 16 {
let off = offset + (i * 4);
result[i] = (input.get(off + 3) as u32)
| ((input.get(off + 2) as u32) << 8)
| ((input.get(off + 1) as u32) << 16)
| ((input.get(off) as u32) << 24);
i += 1;
}
result
}
const fn clone_from_slice_64(
mut data: [u8; 64],
slice: &[u8],
offset: usize,
num_elems: usize,
) -> [u8; 64] {
let mut i = 0;
while i < num_elems {
data[i] = slice[offset + i];
i += 1;
}
data
}
let mut i = 0;
while i < data.len() {
if data.len() - i >= 64 {
let chunk_block = as_block(data, i);
len += 64;
state = process_state(state, chunk_block);
i += 64;
} else {
let num_elems = data.len() - i;
blocks.data = clone_from_slice_64(blocks.data, &data.data, i, num_elems);
blocks.len = num_elems as u32;
break;
}
}
(blocks, len, state)
}
const fn process_state(mut state: [u32; 5], block: [u32; 16]) -> [u32; 5] {
let a = state[0];
let b = state[1];
let c = state[2];
let d = state[3];
let e = state[4];
let (block, b, e) = r0(block, a, b, c, d, e, 0);
let (block, a, d) = r0(block, e, a, b, c, d, 1);
let (block, e, c) = r0(block, d, e, a, b, c, 2);
let (block, d, b) = r0(block, c, d, e, a, b, 3);
let (block, c, a) = r0(block, b, c, d, e, a, 4);
let (block, b, e) = r0(block, a, b, c, d, e, 5);
let (block, a, d) = r0(block, e, a, b, c, d, 6);
let (block, e, c) = r0(block, d, e, a, b, c, 7);
let (block, d, b) = r0(block, c, d, e, a, b, 8);
let (block, c, a) = r0(block, b, c, d, e, a, 9);
let (block, b, e) = r0(block, a, b, c, d, e, 10);
let (block, a, d) = r0(block, e, a, b, c, d, 11);
let (block, e, c) = r0(block, d, e, a, b, c, 12);
let (block, d, b) = r0(block, c, d, e, a, b, 13);
let (block, c, a) = r0(block, b, c, d, e, a, 14);
let (block, b, e) = r0(block, a, b, c, d, e, 15);
let (block, a, d) = r1(block, e, a, b, c, d, 0);
let (block, e, c) = r1(block, d, e, a, b, c, 1);
let (block, d, b) = r1(block, c, d, e, a, b, 2);
let (block, c, a) = r1(block, b, c, d, e, a, 3);
let (block, b, e) = r2(block, a, b, c, d, e, 4);
let (block, a, d) = r2(block, e, a, b, c, d, 5);
let (block, e, c) = r2(block, d, e, a, b, c, 6);
let (block, d, b) = r2(block, c, d, e, a, b, 7);
let (block, c, a) = r2(block, b, c, d, e, a, 8);
let (block, b, e) = r2(block, a, b, c, d, e, 9);
let (block, a, d) = r2(block, e, a, b, c, d, 10);
let (block, e, c) = r2(block, d, e, a, b, c, 11);
let (block, d, b) = r2(block, c, d, e, a, b, 12);
let (block, c, a) = r2(block, b, c, d, e, a, 13);
let (block, b, e) = r2(block, a, b, c, d, e, 14);
let (block, a, d) = r2(block, e, a, b, c, d, 15);
let (block, e, c) = r2(block, d, e, a, b, c, 0);
let (block, d, b) = r2(block, c, d, e, a, b, 1);
let (block, c, a) = r2(block, b, c, d, e, a, 2);
let (block, b, e) = r2(block, a, b, c, d, e, 3);
let (block, a, d) = r2(block, e, a, b, c, d, 4);
let (block, e, c) = r2(block, d, e, a, b, c, 5);
let (block, d, b) = r2(block, c, d, e, a, b, 6);
let (block, c, a) = r2(block, b, c, d, e, a, 7);
let (block, b, e) = r3(block, a, b, c, d, e, 8);
let (block, a, d) = r3(block, e, a, b, c, d, 9);
let (block, e, c) = r3(block, d, e, a, b, c, 10);
let (block, d, b) = r3(block, c, d, e, a, b, 11);
let (block, c, a) = r3(block, b, c, d, e, a, 12);
let (block, b, e) = r3(block, a, b, c, d, e, 13);
let (block, a, d) = r3(block, e, a, b, c, d, 14);
let (block, e, c) = r3(block, d, e, a, b, c, 15);
let (block, d, b) = r3(block, c, d, e, a, b, 0);
let (block, c, a) = r3(block, b, c, d, e, a, 1);
let (block, b, e) = r3(block, a, b, c, d, e, 2);
let (block, a, d) = r3(block, e, a, b, c, d, 3);
let (block, e, c) = r3(block, d, e, a, b, c, 4);
let (block, d, b) = r3(block, c, d, e, a, b, 5);
let (block, c, a) = r3(block, b, c, d, e, a, 6);
let (block, b, e) = r3(block, a, b, c, d, e, 7);
let (block, a, d) = r3(block, e, a, b, c, d, 8);
let (block, e, c) = r3(block, d, e, a, b, c, 9);
let (block, d, b) = r3(block, c, d, e, a, b, 10);
let (block, c, a) = r3(block, b, c, d, e, a, 11);
let (block, b, e) = r4(block, a, b, c, d, e, 12);
let (block, a, d) = r4(block, e, a, b, c, d, 13);
let (block, e, c) = r4(block, d, e, a, b, c, 14);
let (block, d, b) = r4(block, c, d, e, a, b, 15);
let (block, c, a) = r4(block, b, c, d, e, a, 0);
let (block, b, e) = r4(block, a, b, c, d, e, 1);
let (block, a, d) = r4(block, e, a, b, c, d, 2);
let (block, e, c) = r4(block, d, e, a, b, c, 3);
let (block, d, b) = r4(block, c, d, e, a, b, 4);
let (block, c, a) = r4(block, b, c, d, e, a, 5);
let (block, b, e) = r4(block, a, b, c, d, e, 6);
let (block, a, d) = r4(block, e, a, b, c, d, 7);
let (block, e, c) = r4(block, d, e, a, b, c, 8);
let (block, d, b) = r4(block, c, d, e, a, b, 9);
let (block, c, a) = r4(block, b, c, d, e, a, 10);
let (block, b, e) = r4(block, a, b, c, d, e, 11);
let (block, a, d) = r4(block, e, a, b, c, d, 12);
let (block, e, c) = r4(block, d, e, a, b, c, 13);
let (block, d, b) = r4(block, c, d, e, a, b, 14);
let (_, c, a) = r4(block, b, c, d, e, a, 15);
state[0] = state[0].wrapping_add(a);
state[1] = state[1].wrapping_add(b);
state[2] = state[2].wrapping_add(c);
state[3] = state[3].wrapping_add(d);
state[4] = state[4].wrapping_add(e);
state
}
const fn digest(mut state: [u32; 5], len: u64, blocks: Blocks) -> Digest {
const fn clone_from_slice_128(
mut data: [u8; 128],
slice: &[u8],
offset: usize,
num_elems: usize,
) -> [u8; 128] {
let mut i = 0;
while i < num_elems {
data[i] = slice[offset + i];
i += 1;
}
data
}
const fn clone_slice_128(mut data: [u8; 128], slice: &[u8], _offset: usize) -> [u8; 128] {
let mut i = 0;
while i < slice.len() {
data[_offset + i] = slice[i];
i += 1;
}
data
}
const fn as_block(input: &[u8], offset: usize) -> [u32; 16] {
let mut result = [0u32; 16];
let mut i = 0;
while i != 16 {
let off = offset + (i * 4);
result[i] = (input[off + 3] as u32)
| ((input[off + 2] as u32) << 8)
| ((input[off + 1] as u32) << 16)
| ((input[off] as u32) << 24);
i += 1;
}
result
}
let bits = (len + (blocks.len as u64)) * 8;
let extra = [
(bits >> 56) as u8,
(bits >> 48) as u8,
(bits >> 40) as u8,
(bits >> 32) as u8,
(bits >> 24) as u8,
(bits >> 16) as u8,
(bits >> 8) as u8,
bits as u8,
];
let mut last = [0; 128];
let blocklen = blocks.len as usize;
last = clone_from_slice_128(last, &blocks.data, 0, blocklen);
last[blocklen] = 0x80;
if blocklen < 56 {
last = clone_slice_128(last, &extra, 56);
state = process_state(state, as_block(&last, 0));
} else {
last = clone_slice_128(last, &extra, 120);
state = process_state(state, as_block(&last, 0));
state = process_state(state, as_block(&last, 64));
}
Digest { data: state }
}
const fn rol(value: u32, bits: usize) -> u32 {
(value << bits) | (value >> (32 - bits))
}
const fn blk(block: &[u32], i: usize) -> u32 {
let value = block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i];
rol(value, 1)
}
const fn r0(
block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
let n = ((w & (x ^ y)) ^ y)
.wrapping_add(block[i])
.wrapping_add(0x5a82_7999)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
const fn r1(
mut block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
block[i] = blk(&block, i);
let n = ((w & (x ^ y)) ^ y)
.wrapping_add(block[i])
.wrapping_add(0x5a82_7999)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
const fn r2(
mut block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
block[i] = blk(&block, i);
let n = (w ^ x ^ y)
.wrapping_add(block[i])
.wrapping_add(0x6ed9_eba1)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
const fn r3(
mut block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
block[i] = blk(&block, i);
let n = (((w | x) & y) | (w & x))
.wrapping_add(block[i])
.wrapping_add(0x8f1b_bcdc)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
const fn r4(
mut block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
block[i] = blk(&block, i);
let n = (w ^ x ^ y)
.wrapping_add(block[i])
.wrapping_add(0xca62_c1d6)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
pub struct Digest {
data: [u32; 5],
}
impl Digest {
pub const fn bytes(&self) -> [u8; 20] {
[
(self.data[0] >> 24) as u8,
(self.data[0] >> 16) as u8,
(self.data[0] >> 8) as u8,
self.data[0] as u8,
(self.data[1] >> 24) as u8,
(self.data[1] >> 16) as u8,
(self.data[1] >> 8) as u8,
self.data[1] as u8,
(self.data[2] >> 24) as u8,
(self.data[2] >> 16) as u8,
(self.data[2] >> 8) as u8,
self.data[2] as u8,
(self.data[3] >> 24) as u8,
(self.data[3] >> 16) as u8,
(self.data[3] >> 8) as u8,
self.data[3] as u8,
(self.data[4] >> 24) as u8,
(self.data[4] >> 16) as u8,
(self.data[4] >> 8) as u8,
self.data[4] as u8,
]
}
}
impl core::fmt::Display for Digest {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
for i in self.data.iter() {
write!(f, "{:08x}", i)?;
}
Ok(())
}
}

View File

@@ -0,0 +1,39 @@
use super::*;
#[doc(hidden)]
pub struct Waiter(isize);
pub struct WaiterSignaler(isize);
impl Waiter {
pub fn new() -> crate::Result<(Waiter, WaiterSignaler)> {
unsafe {
let handle = CreateEventW(core::ptr::null(), 1, 0, core::ptr::null());
if handle == 0 {
Err(crate::Error::from_win32())
} else {
Ok((Waiter(handle), WaiterSignaler(handle)))
}
}
}
}
impl WaiterSignaler {
/// # Safety
/// Signals the `Waiter`. This is unsafe because the lifetime of `WaiterSignaler` is not tied
/// to the lifetime of the `Waiter`. This is not possible in this case because the `Waiter`
/// is used to signal a WinRT async completion and the compiler doesn't know that the lifetime
/// of the delegate is bounded by the calling function.
pub unsafe fn signal(&self) {
// https://github.com/microsoft/windows-rs/pull/374#discussion_r535313344
SetEvent(self.0);
}
}
impl Drop for Waiter {
fn drop(&mut self) {
unsafe {
WaitForSingleObject(self.0, 0xFFFFFFFF);
CloseHandle(self.0);
}
}
}

View File

@@ -0,0 +1,304 @@
use super::*;
use crate::Interface;
use core::ffi::c_void;
use core::mem::{transmute, transmute_copy};
use core::ptr::null_mut;
use core::sync::atomic::{AtomicIsize, Ordering};
#[doc(hidden)]
#[repr(transparent)]
#[derive(Default)]
pub struct WeakRefCount(AtomicIsize);
impl WeakRefCount {
pub fn new() -> Self {
Self(AtomicIsize::new(1))
}
pub fn add_ref(&self) -> u32 {
self.0
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |count_or_pointer| {
bool::then_some(!is_weak_ref(count_or_pointer), count_or_pointer + 1)
})
.map(|u| u as u32 + 1)
.unwrap_or_else(|pointer| unsafe { TearOff::decode(pointer).strong_count.add_ref() })
}
#[inline(always)]
pub fn is_one(&self) -> bool {
self.0.load(Ordering::Acquire) == 1
}
pub fn release(&self) -> u32 {
self.0
.fetch_update(Ordering::Release, Ordering::Relaxed, |count_or_pointer| {
bool::then_some(!is_weak_ref(count_or_pointer), count_or_pointer - 1)
})
.map(|u| u as u32 - 1)
.unwrap_or_else(|pointer| unsafe {
let tear_off = TearOff::decode(pointer);
let remaining = tear_off.strong_count.release();
// If this is the last strong reference, we can release the weak reference implied by the strong reference.
// There may still be weak references, so the WeakRelease is called to handle such possibilities.
if remaining == 0 {
TearOff::WeakRelease(&mut tear_off.weak_vtable as *mut _ as _);
}
remaining
})
}
/// # Safety
pub unsafe fn query(&self, iid: &crate::GUID, object: *mut c_void) -> *mut c_void {
if iid != &IWeakReferenceSource::IID {
return null_mut();
}
let mut count_or_pointer = self.0.load(Ordering::Relaxed);
if is_weak_ref(count_or_pointer) {
return TearOff::from_encoding(count_or_pointer);
}
let tear_off = TearOff::new(object, count_or_pointer as u32);
let tear_off_ptr: *mut c_void = transmute_copy(&tear_off);
let encoding: usize = ((tear_off_ptr as usize) >> 1) | (1 << (usize::BITS - 1));
loop {
match self.0.compare_exchange_weak(
count_or_pointer,
encoding as isize,
Ordering::AcqRel,
Ordering::Relaxed,
) {
Ok(_) => {
let result: *mut c_void = transmute(tear_off);
TearOff::from_strong_ptr(result).strong_count.add_ref();
return result;
}
Err(pointer) => count_or_pointer = pointer,
}
if is_weak_ref(count_or_pointer) {
return TearOff::from_encoding(count_or_pointer);
}
TearOff::from_strong_ptr(tear_off_ptr)
.strong_count
.0
.store(count_or_pointer as i32, Ordering::SeqCst);
}
}
}
fn is_weak_ref(value: isize) -> bool {
value < 0
}
#[repr(C)]
struct TearOff {
strong_vtable: *const IWeakReferenceSource_Vtbl,
weak_vtable: *const IWeakReference_Vtbl,
object: *mut c_void,
strong_count: RefCount,
weak_count: RefCount,
}
impl TearOff {
#[allow(clippy::new_ret_no_self)]
unsafe fn new(object: *mut c_void, strong_count: u32) -> IWeakReferenceSource {
transmute(Box::new(TearOff {
strong_vtable: &Self::STRONG_VTABLE,
weak_vtable: &Self::WEAK_VTABLE,
object,
strong_count: RefCount::new(strong_count),
weak_count: RefCount::new(1),
}))
}
unsafe fn from_encoding(encoding: isize) -> *mut c_void {
let tear_off = TearOff::decode(encoding);
tear_off.strong_count.add_ref();
tear_off as *mut _ as *mut _
}
const STRONG_VTABLE: IWeakReferenceSource_Vtbl = IWeakReferenceSource_Vtbl {
base__: crate::IUnknown_Vtbl {
QueryInterface: Self::StrongQueryInterface,
AddRef: Self::StrongAddRef,
Release: Self::StrongRelease,
},
GetWeakReference: Self::StrongDowngrade,
};
const WEAK_VTABLE: IWeakReference_Vtbl = IWeakReference_Vtbl {
base__: crate::IUnknown_Vtbl {
QueryInterface: Self::WeakQueryInterface,
AddRef: Self::WeakAddRef,
Release: Self::WeakRelease,
},
Resolve: Self::WeakUpgrade,
};
unsafe fn from_strong_ptr<'a>(this: *mut c_void) -> &'a mut Self {
&mut *(this as *mut *mut c_void as *mut Self)
}
unsafe fn from_weak_ptr<'a>(this: *mut c_void) -> &'a mut Self {
&mut *((this as *mut *mut c_void).sub(1) as *mut Self)
}
unsafe fn decode<'a>(value: isize) -> &'a mut Self {
transmute(value << 1)
}
unsafe fn query_interface(
&self,
iid: *const crate::GUID,
interface: *mut *mut c_void,
) -> crate::HRESULT {
((*(*(self.object as *mut *mut crate::IUnknown_Vtbl))).QueryInterface)(
self.object,
iid,
interface,
)
}
unsafe extern "system" fn StrongQueryInterface(
ptr: *mut c_void,
iid: *const crate::GUID,
interface: *mut *mut c_void,
) -> crate::HRESULT {
let this = Self::from_strong_ptr(ptr);
if iid.is_null() || interface.is_null() {
return E_POINTER;
}
// Only directly respond to queries for the the tear-off's strong interface. This is
// effectively a self-query.
if *iid == IWeakReferenceSource::IID {
*interface = ptr;
this.strong_count.add_ref();
return crate::HRESULT(0);
}
// As the tear-off is sharing the identity of the object, simply delegate any remaining
// queries to the object.
this.query_interface(iid, interface)
}
unsafe extern "system" fn WeakQueryInterface(
ptr: *mut c_void,
iid: *const crate::GUID,
interface: *mut *mut c_void,
) -> crate::HRESULT {
let this = Self::from_weak_ptr(ptr);
if iid.is_null() || interface.is_null() {
return E_POINTER;
}
// While the weak vtable is packed into the same allocation as the strong vtable and
// tear-off, it represents a distinct COM identity and thus does not share or delegate to
// the object.
*interface = if *iid == IWeakReference::IID
|| *iid == crate::IUnknown::IID
|| *iid == IAgileObject::IID
{
ptr
} else {
null_mut()
};
// TODO: implement IMarshal
if (*interface).is_null() {
E_NOINTERFACE
} else {
this.weak_count.add_ref();
crate::HRESULT(0)
}
}
unsafe extern "system" fn StrongAddRef(ptr: *mut c_void) -> u32 {
let this = Self::from_strong_ptr(ptr);
// Implement `AddRef` directly as we own the strong reference.
this.strong_count.add_ref()
}
unsafe extern "system" fn WeakAddRef(ptr: *mut c_void) -> u32 {
let this = Self::from_weak_ptr(ptr);
// Implement `AddRef` directly as we own the weak reference.
this.weak_count.add_ref()
}
unsafe extern "system" fn StrongRelease(ptr: *mut c_void) -> u32 {
let this = Self::from_strong_ptr(ptr);
// Forward strong `Release` to the object so that it can destroy itself. It will then
// decrement its weak reference and allow the tear-off to be released as needed.
((*(*(this.object as *mut *mut crate::IUnknown_Vtbl))).Release)(this.object)
}
unsafe extern "system" fn WeakRelease(ptr: *mut c_void) -> u32 {
let this = Self::from_weak_ptr(ptr);
// Implement `Release` directly as we own the weak reference.
let remaining = this.weak_count.release();
// If there are no remaining references, it means that the object has already been
// destroyed. Go ahead and destroy the tear-off.
if remaining == 0 {
let _ = Box::from_raw(this);
}
remaining
}
unsafe extern "system" fn StrongDowngrade(
ptr: *mut c_void,
interface: *mut *mut c_void,
) -> crate::HRESULT {
let this = Self::from_strong_ptr(ptr);
// The strong vtable hands out a reference to the weak vtable. This is always safe and
// straightforward since a strong reference guarantees there is at least one weak
// reference.
*interface = &mut this.weak_vtable as *mut _ as _;
this.weak_count.add_ref();
crate::HRESULT(0)
}
unsafe extern "system" fn WeakUpgrade(
ptr: *mut c_void,
iid: *const crate::GUID,
interface: *mut *mut c_void,
) -> crate::HRESULT {
let this = Self::from_weak_ptr(ptr);
this.strong_count
.0
.fetch_update(Ordering::Acquire, Ordering::Relaxed, |count| {
// Attempt to acquire a strong reference count to stabilize the object for the duration
// of the `QueryInterface` call.
bool::then_some(count != 0, count + 1)
})
.map(|_| {
// Let the object respond to the upgrade query.
let result = this.query_interface(iid, interface);
// Decrement the temporary reference account used to stabilize the object.
this.strong_count.0.fetch_sub(1, Ordering::Relaxed);
// Return the result of the query.
result
})
.unwrap_or_else(|_| {
*interface = null_mut();
crate::HRESULT(0)
})
}
}

View File

@@ -0,0 +1,185 @@
use super::*;
use core::ffi::c_void;
use core::mem::{transmute, transmute_copy};
use core::ptr::null_mut;
/// A WinRT object that may be used as a polymorphic stand-in for any WinRT class, interface, or boxed value.
/// [`IInspectable`] represents the
/// [IInspectable](https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nn-inspectable-iinspectable)
/// interface.
#[repr(transparent)]
#[derive(Clone, PartialEq, Eq)]
pub struct IInspectable(pub IUnknown);
interface_hierarchy!(IInspectable, IUnknown);
impl IInspectable {
/// Returns the canonical type name for the underlying object.
pub fn GetRuntimeClassName(&self) -> Result<HSTRING> {
unsafe {
let mut abi = null_mut();
(self.vtable().GetRuntimeClassName)(transmute_copy(self), &mut abi).ok()?;
Ok(transmute::<*mut c_void, HSTRING>(abi))
}
}
/// Gets the trust level of the current object.
pub fn GetTrustLevel(&self) -> Result<i32> {
unsafe {
let mut value = 0;
(self.vtable().GetTrustLevel)(transmute_copy(self), &mut value).ok()?;
Ok(value)
}
}
}
#[doc(hidden)]
#[repr(C)]
pub struct IInspectable_Vtbl {
pub base: IUnknown_Vtbl,
pub GetIids: unsafe extern "system" fn(
this: *mut c_void,
count: *mut u32,
values: *mut *mut GUID,
) -> HRESULT,
pub GetRuntimeClassName:
unsafe extern "system" fn(this: *mut c_void, value: *mut *mut c_void) -> HRESULT,
pub GetTrustLevel: unsafe extern "system" fn(this: *mut c_void, value: *mut i32) -> HRESULT,
}
unsafe impl Interface for IInspectable {
type Vtable = IInspectable_Vtbl;
const IID: GUID = GUID::from_u128(0xaf86e2e0_b12d_4c6a_9c5a_d7aa65101e90);
}
impl RuntimeType for IInspectable {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice(b"cinterface(IInspectable)");
}
impl RuntimeName for IInspectable {}
impl IInspectable_Vtbl {
pub const fn new<Identity: IUnknownImpl, Name: RuntimeName, const OFFSET: isize>() -> Self {
unsafe extern "system" fn GetIids(
_: *mut c_void,
count: *mut u32,
values: *mut *mut GUID,
) -> HRESULT {
if count.is_null() || values.is_null() {
return imp::E_POINTER;
}
// Note: even if we end up implementing this in future, it still doesn't need a this pointer
// since the data to be returned is type- not instance-specific so can be shared for all
// interfaces.
*count = 0;
*values = null_mut();
HRESULT(0)
}
unsafe extern "system" fn GetRuntimeClassName<T: RuntimeName>(
_: *mut c_void,
value: *mut *mut c_void,
) -> HRESULT {
if value.is_null() {
return imp::E_POINTER;
}
let h: HSTRING = T::NAME.into(); // TODO: should be try_into
*value = transmute::<HSTRING, *mut c_void>(h);
HRESULT(0)
}
unsafe extern "system" fn GetTrustLevel<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
value: *mut i32,
) -> HRESULT {
if value.is_null() {
return imp::E_POINTER;
}
let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T;
(*this).GetTrustLevel(value)
}
Self {
base: IUnknown_Vtbl::new::<Identity, OFFSET>(),
GetIids,
GetRuntimeClassName: GetRuntimeClassName::<Name>,
GetTrustLevel: GetTrustLevel::<Identity, OFFSET>,
}
}
}
impl core::fmt::Debug for IInspectable {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
// Attempts to retrieve the string representation of the object via the
// IStringable interface. If that fails, it will use the canonical type
// name to give some idea of what the object represents.
let name = <Self as Interface>::cast::<imp::IStringable>(self)
.and_then(|s| s.ToString())
.or_else(|_| self.GetRuntimeClassName())
.unwrap_or_default();
write!(f, "\"{}\"", name)
}
}
macro_rules! primitive_boxed_type {
($(($t:ty, $m:ident)),+) => {
$(impl TryFrom<$t> for IInspectable {
type Error = Error;
fn try_from(value: $t) -> Result<Self> {
imp::PropertyValue::$m(value)
}
}
impl TryFrom<IInspectable> for $t {
type Error = Error;
fn try_from(value: IInspectable) -> Result<Self> {
<IInspectable as Interface>::cast::<imp::IReference<$t>>(&value)?.Value()
}
}
impl TryFrom<&IInspectable> for $t {
type Error = Error;
fn try_from(value: &IInspectable) -> Result<Self> {
<IInspectable as Interface>::cast::<imp::IReference<$t>>(value)?.Value()
}
})*
};
}
primitive_boxed_type! {
(bool, CreateBoolean),
(u8, CreateUInt8),
(i16, CreateInt16),
(u16, CreateUInt16),
(i32, CreateInt32),
(u32, CreateUInt32),
(i64, CreateInt64),
(u64, CreateUInt64),
(f32, CreateSingle),
(f64, CreateDouble)
}
impl TryFrom<&str> for IInspectable {
type Error = Error;
fn try_from(value: &str) -> Result<Self> {
let value: HSTRING = value.into();
imp::PropertyValue::CreateString(&value)
}
}
impl TryFrom<HSTRING> for IInspectable {
type Error = Error;
fn try_from(value: HSTRING) -> Result<Self> {
imp::PropertyValue::CreateString(&value)
}
}
impl TryFrom<&HSTRING> for IInspectable {
type Error = Error;
fn try_from(value: &HSTRING) -> Result<Self> {
imp::PropertyValue::CreateString(value)
}
}
impl TryFrom<IInspectable> for HSTRING {
type Error = Error;
fn try_from(value: IInspectable) -> Result<Self> {
<IInspectable as Interface>::cast::<imp::IReference<HSTRING>>(&value)?.Value()
}
}
impl TryFrom<&IInspectable> for HSTRING {
type Error = Error;
fn try_from(value: &IInspectable) -> Result<Self> {
<IInspectable as Interface>::cast::<imp::IReference<HSTRING>>(value)?.Value()
}
}

View File

@@ -0,0 +1,341 @@
use super::*;
use core::any::Any;
use core::ffi::c_void;
use core::marker::PhantomData;
use core::mem::{forget, transmute_copy, MaybeUninit};
use core::ptr::NonNull;
/// Provides low-level access to an interface vtable.
///
/// This trait is automatically implemented by the generated bindings and should not be
/// implemented manually.
///
/// # Safety
pub unsafe trait Interface: Sized + Clone {
#[doc(hidden)]
type Vtable;
/// The `GUID` associated with the interface.
const IID: GUID;
#[doc(hidden)]
const UNKNOWN: bool = true;
/// A reference to the interface's vtable
#[doc(hidden)]
#[inline(always)]
fn vtable(&self) -> &Self::Vtable {
// SAFETY: the implementor of the trait guarantees that `Self` is castable to its vtable
unsafe { self.assume_vtable::<Self>() }
}
/// Cast this interface as a reference to the supplied interfaces `Vtable`
///
/// # Safety
///
/// This is safe if `T` is an equivalent interface to `Self` or a super interface.
/// In other words, `T::Vtable` must be equivalent to the beginning of `Self::Vtable`.
#[doc(hidden)]
#[inline(always)]
unsafe fn assume_vtable<T: Interface>(&self) -> &T::Vtable {
&**(self.as_raw() as *mut *mut T::Vtable)
}
/// Returns the raw COM interface pointer. The resulting pointer continues to be owned by the `Interface` implementation.
#[inline(always)]
fn as_raw(&self) -> *mut c_void {
// SAFETY: implementors of this trait must guarantee that the implementing type has a pointer in-memory representation
unsafe { transmute_copy(self) }
}
/// Returns the raw COM interface pointer and releases ownership. It the caller's responsibility to release the COM interface pointer.
#[inline(always)]
fn into_raw(self) -> *mut c_void {
// SAFETY: implementors of this trait must guarantee that the implementing type has a pointer in-memory representation
let raw = self.as_raw();
forget(self);
raw
}
/// Creates an `Interface` by taking ownership of the `raw` COM interface pointer.
///
/// # Safety
///
/// The `raw` pointer must be owned by the caller and represent a valid COM interface pointer. In other words,
/// it must point to a vtable beginning with the `IUnknown` function pointers and match the vtable of `Interface`.
unsafe fn from_raw(raw: *mut c_void) -> Self {
transmute_copy(&raw)
}
/// Creates an `Interface` that is valid so long as the `raw` COM interface pointer is valid.
///
/// # Safety
///
/// The `raw` pointer must be a valid COM interface pointer. In other words, it must point to a vtable
/// beginning with the `IUnknown` function pointers and match the vtable of `Interface`.
#[inline(always)]
unsafe fn from_raw_borrowed(raw: &*mut c_void) -> Option<&Self> {
if raw.is_null() {
None
} else {
Some(transmute_copy(&raw))
}
}
/// Attempts to cast the current interface to another interface using `QueryInterface`.
///
/// The name `cast` is preferred to `query` because there is a WinRT method named query but not one
/// named cast.
#[inline(always)]
fn cast<T: Interface>(&self) -> Result<T> {
// SAFETY: `result` is valid for writing an interface pointer and it is safe
// to cast the `result` pointer as `T` on success because we are using the `IID` tied
// to `T` which the implementor of `Interface` has guaranteed is correct
unsafe {
// If query() returns a failure code then we propagate that failure code to the caller.
// In that case, we ignore the contents of 'result' (which will _not_ be dropped,
// because MaybeUninit intentionally does not drop its contents).
//
// This guards against implementations of COM interfaces which may store non-null values
// in 'result' but still return E_NOINTERFACE.
let mut result = MaybeUninit::<Option<T>>::zeroed();
self.query(&T::IID, result.as_mut_ptr() as _).ok()?;
// If we get here, then query() has succeeded, but we still need to double-check
// that the output pointer is non-null.
if let Some(obj) = result.assume_init() {
Ok(obj)
} else {
Err(imp::E_POINTER.into())
}
}
}
/// This casts the given COM interface to [`&dyn Any`].
///
/// Applications should generally _not_ call this method directly. Instead, use the
/// [`Interface::cast_object_ref`] or [`Interface::cast_object`] methods.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method. However, note that the
/// returned `&dyn Any` refers to the _outer_ implementation object that was generated by
/// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`.
///
/// # Safety
///
/// **IMPORTANT!!** This uses a non-standard protocol for QueryInterface! The `DYNAMIC_CAST_IID`
/// IID identifies this protocol, but there is no `IDynamicCast` interface. Instead, objects
/// that recognize `DYNAMIC_CAST_IID` simply store their `&dyn Any` directly at the interface
/// pointer that was passed to `QueryInterface. This means that the returned value has a
/// size that is twice as large (`size_of::<&dyn Any>() == 2 * size_of::<*const c_void>()`).
///
/// This means that callers that use this protocol cannot simply pass `&mut ptr` for
/// an ordinary single-pointer-sized pointer. Only this method understands this protocol.
///
/// Another part of this protocol is that the implementation of `QueryInterface` _does not_
/// AddRef the object. The caller must guarantee the liveness of the COM object. In Rust,
/// this means tying the lifetime of the IUnknown* that we used for the QueryInterface
/// call to the lifetime of the returned `&dyn Any` value.
///
/// This method preserves type safety and relies on these invariants:
///
/// * All `QueryInterface` implementations that recognize `DYNAMIC_CAST_IID` are generated by
/// the `#[implement]` macro and respect the rules described here.
#[inline(always)]
fn cast_to_any<T>(&self) -> Result<&dyn Any>
where
T: ComObjectInner,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
unsafe {
let mut any_ref_arg: MaybeUninit<&dyn Any> = MaybeUninit::zeroed();
self.query(
&DYNAMIC_CAST_IID,
any_ref_arg.as_mut_ptr() as *mut *mut c_void,
)
.ok()?;
Ok(any_ref_arg.assume_init())
}
}
/// Returns `true` if the given COM interface refers to an implementation of `T`.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `false`.
#[inline(always)]
fn is_object<T>(&self) -> bool
where
T: ComObjectInner,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
if let Ok(any) = self.cast_to_any::<T>() {
any.is::<T::Outer>()
} else {
false
}
}
/// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer"
/// object, e.g. `&MyApp_Impl`, not the inner `&MyApp` object.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method. However, note that the
/// returned `&dyn Any` refers to the _outer_ implementation object that was generated by
/// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`.
///
/// The returned value is borrowed. If you need an owned (counted) reference, then use
/// [`Interface::cast_object`].
#[inline(always)]
fn cast_object_ref<T>(&self) -> Result<&T::Outer>
where
T: ComObjectInner,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
let any: &dyn Any = self.cast_to_any::<T>()?;
if let Some(outer) = any.downcast_ref::<T::Outer>() {
Ok(outer)
} else {
Err(imp::E_NOINTERFACE.into())
}
}
/// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer"
/// object, e.g. `MyApp_Impl`, not the inner `MyApp` object.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method. However, note that the
/// returned `&dyn Any` refers to the _outer_ implementation object that was generated by
/// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`.
///
/// The returned value is an owned (counted) reference; this function calls `AddRef` on the
/// underlying COM object. If you do not need an owned reference, then you can use the
/// [`Interface::cast_object_ref`] method instead, and avoid the cost of `AddRef` / `Release`.
#[inline(always)]
fn cast_object<T>(&self) -> Result<ComObject<T>>
where
T: ComObjectInner,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
let object_ref = self.cast_object_ref::<T>()?;
Ok(object_ref.to_object())
}
/// Attempts to create a [`Weak`] reference to this object.
fn downgrade(&self) -> Result<Weak<Self>> {
self.cast::<imp::IWeakReferenceSource>()
.and_then(|source| Weak::downgrade(&source))
}
/// Call `QueryInterface` on this interface
///
/// # Safety
///
/// `interface` must be a non-null, valid pointer for writing an interface pointer.
#[inline(always)]
unsafe fn query(&self, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT {
if Self::UNKNOWN {
(self.assume_vtable::<IUnknown>().QueryInterface)(self.as_raw(), iid, interface)
} else {
panic!("Non-COM interfaces cannot be queried.")
}
}
/// Creates an `InterfaceRef` for this reference. The `InterfaceRef` tracks lifetimes statically,
/// and eliminates the need for dynamic reference count adjustments (AddRef/Release).
fn to_ref(&self) -> InterfaceRef<'_, Self> {
InterfaceRef::from_interface(self)
}
}
/// # Safety
#[doc(hidden)]
pub unsafe fn from_raw_borrowed<T: Interface>(raw: &*mut c_void) -> Option<&T> {
T::from_raw_borrowed(raw)
}
/// This has the same memory representation as `IFoo`, but represents a borrowed interface pointer.
///
/// This type has no `Drop` impl; it does not AddRef/Release the given interface. However, because
/// it has a lifetime parameter, it always represents a non-null pointer to an interface.
#[repr(transparent)]
pub struct InterfaceRef<'a, I>(NonNull<c_void>, PhantomData<&'a I>);
impl<'a, I> Copy for InterfaceRef<'a, I> {}
impl<'a, I> Clone for InterfaceRef<'a, I> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, I: core::fmt::Debug + Interface> core::fmt::Debug for InterfaceRef<'a, I> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
<I as core::fmt::Debug>::fmt(&**self, f)
}
}
impl<'a, I: Interface> InterfaceRef<'a, I> {
/// Creates an `InterfaceRef` from a raw pointer. _This is extremely dangerous, since there
/// is no lifetime tracking at all!_
///
/// # Safety
/// The caller must guarantee that the `'a` lifetime parameter is bound by context to a correct
/// lifetime.
#[inline(always)]
pub unsafe fn from_raw(ptr: NonNull<c_void>) -> Self {
Self(ptr, PhantomData)
}
/// Creates an `InterfaceRef` from an interface reference. This safely associates the lifetime
/// of the interface reference with the `'a` parameter of `InterfaceRef`. This allows for
/// lifetime checking _without_ calling AddRef/Release on the underlying lifetime, which can
/// improve efficiency.
#[inline(always)]
pub fn from_interface(interface: &I) -> Self {
unsafe {
// SAFETY: new_unchecked() should be valid because Interface::as_raw should always
// return a non-null pointer.
Self(NonNull::new_unchecked(interface.as_raw()), PhantomData)
}
}
/// Calls AddRef on the underlying COM interface and returns an "owned" (counted) reference.
#[inline(always)]
pub fn to_owned(self) -> I {
(*self).clone()
}
}
impl<'a, 'i: 'a, I: Interface> From<&'i I> for InterfaceRef<'a, I> {
#[inline(always)]
fn from(interface: &'a I) -> InterfaceRef<'a, I> {
InterfaceRef::from_interface(interface)
}
}
impl<'a, I: Interface> core::ops::Deref for InterfaceRef<'a, I> {
type Target = I;
#[inline(always)]
fn deref(&self) -> &I {
unsafe { core::mem::transmute(self) }
}
}
/// This IID identifies a special protocol, used by [`Interface::cast_to_any`]. This is _not_
/// an ordinary COM interface; it uses special lifetime rules and a larger interface pointer.
/// See the comments on [`Interface::cast_to_any`].
#[doc(hidden)]
pub const DYNAMIC_CAST_IID: GUID = GUID::from_u128(0xae49d5cb_143f_431c_874c_2729336e4eca);

78
vendor/windows-core-0.57.0/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,78 @@
/*!
Learn more about Rust for Windows here: <https://github.com/microsoft/windows-rs>
*/
#![doc(html_no_source)]
#![allow(non_snake_case)]
#![cfg_attr(
windows_debugger_visualizer,
debugger_visualizer(natvis_file = "../.natvis")
)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
extern crate self as windows_core;
#[macro_use]
extern crate alloc;
use alloc::{boxed::Box, string::String, vec::Vec};
#[doc(hidden)]
pub mod imp;
mod agile_reference;
mod array;
mod as_impl;
mod com_object;
#[cfg(feature = "std")]
mod event;
mod guid;
mod handles;
mod inspectable;
mod interface;
mod out_param;
mod out_ref;
mod param;
mod param_value;
mod r#ref;
mod runtime_name;
mod runtime_type;
mod scoped_interface;
mod strings;
mod r#type;
mod unknown;
mod variant;
mod weak;
pub use agile_reference::*;
pub use array::*;
pub use as_impl::*;
pub use com_object::*;
#[cfg(feature = "std")]
pub use event::*;
pub use guid::*;
pub use handles::*;
pub use inspectable::*;
pub use interface::*;
pub use out_param::*;
pub use out_ref::*;
pub use param::*;
pub use param_value::*;
pub use r#ref::*;
pub use r#type::*;
pub use runtime_name::*;
pub use runtime_type::*;
pub use scoped_interface::*;
pub use strings::*;
pub use unknown::*;
pub use variant::*;
pub use weak::*;
pub use windows_implement::implement;
pub use windows_interface::interface;
pub use windows_result::*;
/// Attempts to load the factory object for the given WinRT class.
/// This can be used to access COM interfaces implemented on a Windows Runtime class factory.
pub fn factory<C: RuntimeName, I: Interface>() -> Result<I> {
imp::factory::<C, I>()
}

View File

@@ -0,0 +1,57 @@
use super::*;
use core::mem::{take, transmute_copy, zeroed};
/// Provides automatic parameter conversion in cases where the Windows API expects implicit conversion support.
///
/// This is a mutable version of [Param] meant to support out parameters.
/// There is no need to implement this trait. Blanket implementations are provided for all applicable Windows types.
pub trait OutParam<T: TypeKind, C = <T as TypeKind>::TypeKind>: Sized
where
T: Type<T>,
{
#[doc(hidden)]
unsafe fn borrow_mut(&self) -> OutRef<'_, T>;
}
impl<T> OutParam<T, CloneType> for &mut T
where
T: TypeKind<TypeKind = CloneType> + Clone + Default,
{
unsafe fn borrow_mut(&self) -> OutRef<'_, T> {
let this: &mut T = transmute_copy(self);
take(this);
transmute_copy(self)
}
}
impl<T> OutParam<T, CopyType> for &mut T
where
T: TypeKind<TypeKind = CopyType> + Clone + Default,
{
unsafe fn borrow_mut(&self) -> OutRef<'_, T> {
transmute_copy(self)
}
}
impl<T> OutParam<T, InterfaceType> for &mut Option<T>
where
T: TypeKind<TypeKind = InterfaceType> + Clone,
{
unsafe fn borrow_mut(&self) -> OutRef<'_, T> {
let this: &mut Option<T> = transmute_copy(self);
take(this);
transmute_copy(self)
}
}
impl<T> OutParam<T> for Option<&mut T>
where
T: Type<T>,
{
unsafe fn borrow_mut(&self) -> OutRef<'_, T> {
match self {
Some(this) => transmute_copy(this),
None => zeroed(),
}
}
}

View File

@@ -0,0 +1,25 @@
use super::*;
/// A borrowed type with the same memory layout as the type itself that can be used to construct ABI-compatible function signatures.
///
/// This is a mutable version of [Ref] meant to support out parameters.
#[repr(transparent)]
pub struct OutRef<'a, T: Type<T>>(*mut T::Abi, core::marker::PhantomData<&'a T>);
impl<'a, T: Type<T>> OutRef<'a, T> {
/// Returns `true` if the argument is null.
pub fn is_null(&self) -> bool {
self.0.is_null()
}
/// Overwrites a memory location with the given value without reading or dropping the old value.
pub fn write(self, value: T::Default) -> Result<()> {
if self.0.is_null() {
Err(Error::from_hresult(imp::E_POINTER))
} else {
unsafe { *self.0 = core::mem::transmute_copy(&value) }
core::mem::forget(value);
Ok(())
}
}
}

87
vendor/windows-core-0.57.0/src/param.rs vendored Normal file
View File

@@ -0,0 +1,87 @@
use super::*;
use core::mem::transmute_copy;
use core::mem::zeroed;
/// Provides automatic parameter conversion in cases where the Windows API expects implicit conversion support.
///
/// There is no need to implement this trait. Blanket implementations are provided for all applicable Windows types.
pub trait Param<T: TypeKind, C = <T as TypeKind>::TypeKind>: Sized
where
T: Type<T>,
{
#[doc(hidden)]
unsafe fn param(self) -> ParamValue<T>;
}
impl<T> Param<T> for Option<&T>
where
T: Type<T>,
{
unsafe fn param(self) -> ParamValue<T> {
ParamValue::Borrowed(match self {
Some(item) => transmute_copy(item),
None => zeroed(),
})
}
}
impl<T, U> Param<T, InterfaceType> for &U
where
T: TypeKind<TypeKind = InterfaceType> + Clone,
T: Interface,
U: Interface,
U: imp::CanInto<T>,
{
unsafe fn param(self) -> ParamValue<T> {
if U::QUERY {
self.cast()
.map_or(ParamValue::Borrowed(zeroed()), |ok| ParamValue::Owned(ok))
} else {
ParamValue::Borrowed(transmute_copy(self))
}
}
}
impl<T> Param<T, CloneType> for &T
where
T: TypeKind<TypeKind = CloneType> + Clone,
{
unsafe fn param(self) -> ParamValue<T> {
ParamValue::Borrowed(transmute_copy(self))
}
}
impl<T, U> Param<T, CopyType> for U
where
T: TypeKind<TypeKind = CopyType> + Clone,
U: TypeKind<TypeKind = CopyType> + Clone,
U: imp::CanInto<T>,
{
unsafe fn param(self) -> ParamValue<T> {
ParamValue::Owned(transmute_copy(&self))
}
}
impl Param<PCWSTR> for &BSTR {
unsafe fn param(self) -> ParamValue<PCWSTR> {
ParamValue::Owned(PCWSTR(self.as_ptr()))
}
}
impl Param<PCWSTR> for &HSTRING {
unsafe fn param(self) -> ParamValue<PCWSTR> {
ParamValue::Owned(PCWSTR(self.as_ptr()))
}
}
impl Param<PCWSTR> for PWSTR {
unsafe fn param(self) -> ParamValue<PCWSTR> {
ParamValue::Owned(PCWSTR(self.0))
}
}
impl Param<PCSTR> for PSTR {
unsafe fn param(self) -> ParamValue<PCSTR> {
ParamValue::Owned(PCSTR(self.0))
}
}

View File

@@ -0,0 +1,24 @@
use super::*;
use core::mem::transmute_copy;
#[doc(hidden)]
pub enum ParamValue<T: Type<T>> {
Owned(T),
Borrowed(T::Abi),
}
impl<T: Type<T>> ParamValue<T> {
// TODO: replace with `borrow` in windows-bindgen
pub fn abi(&self) -> T::Abi {
unsafe {
match self {
Self::Owned(item) => transmute_copy(item),
Self::Borrowed(borrowed) => transmute_copy(borrowed),
}
}
}
pub fn borrow(&self) -> Ref<'_, T> {
unsafe { transmute_copy(&self.abi()) }
}
}

26
vendor/windows-core-0.57.0/src/ref.rs vendored Normal file
View File

@@ -0,0 +1,26 @@
use super::*;
use core::ffi::c_void;
use core::marker::PhantomData;
use core::mem::transmute;
/// A borrowed type with the same memory layout as the type itself that can be used to construct ABI-compatible function signatures.
#[repr(transparent)]
pub struct Ref<'a, T: Type<T>>(T::Abi, PhantomData<&'a T>);
impl<'a, T: Type<T, Default = Option<T>, Abi = *mut c_void>> Ref<'a, T> {
/// Converts the argument to a [Result<&T>] reference.
pub fn ok(&self) -> Result<&T> {
if self.0.is_null() {
Err(Error::from_hresult(imp::E_POINTER))
} else {
unsafe { Ok(transmute::<&*mut c_void, &T>(&self.0)) }
}
}
}
impl<'a, T: Type<T>> core::ops::Deref for Ref<'a, T> {
type Target = T::Default;
fn deref(&self) -> &Self::Target {
unsafe { transmute(&self.0) }
}
}

View File

@@ -0,0 +1,5 @@
#[doc(hidden)]
pub trait RuntimeName {
// TODO: needs to use ConstBuffer like RuntimeType to allow generic interfaces to have names for GetRuntimeClassName
const NAME: &'static str = "";
}

View File

@@ -0,0 +1,34 @@
use super::*;
#[doc(hidden)]
pub trait RuntimeType: Type<Self> {
const SIGNATURE: imp::ConstBuffer;
}
macro_rules! primitives {
($(($t:ty, $s:literal)),+) => {
$(
impl RuntimeType for $t {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice($s);
}
)*
};
}
primitives! {
(bool, b"b1"),
(i8, b"i1"),
(u8, b"u1"),
(i16, b"i2"),
(u16, b"u2"),
(i32, b"i4"),
(u32, b"u4"),
(i64, b"i8"),
(u64, b"u8"),
(f32, b"f4"),
(f64, b"f8")
}
impl RuntimeType for HSTRING {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice(b"string");
}

View File

@@ -0,0 +1,41 @@
use super::*;
use core::ffi::c_void;
use core::marker::PhantomData;
#[doc(hidden)]
#[repr(C)]
pub struct ScopedHeap {
pub vtable: *const c_void,
pub this: *const c_void,
}
#[doc(hidden)]
pub struct ScopedInterface<'a, T: Interface> {
interface: T,
lifetime: PhantomData<&'a T>,
}
impl<'a, T: Interface> ScopedInterface<'a, T> {
pub fn new(interface: T) -> Self {
Self {
interface,
lifetime: PhantomData,
}
}
}
impl<'a, T: Interface> core::ops::Deref for ScopedInterface<'a, T> {
type Target = T;
fn deref(&self) -> &T {
&self.interface
}
}
impl<'a, T: Interface> Drop for ScopedInterface<'a, T> {
fn drop(&mut self) {
unsafe {
let _ = Box::from_raw(self.interface.as_raw() as *const _ as *mut ScopedHeap);
}
}
}

View File

@@ -0,0 +1,176 @@
use super::*;
/// A BSTR string ([BSTR](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/automat/string-manipulation-functions))
/// is a length-prefixed wide string.
#[repr(transparent)]
pub struct BSTR(*const u16);
impl BSTR {
/// Create an empty `BSTR`.
///
/// This function does not allocate memory.
pub const fn new() -> Self {
Self(core::ptr::null_mut())
}
/// Returns `true` if the string is empty.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Returns the length of the string.
pub fn len(&self) -> usize {
if self.0.is_null() {
0
} else {
unsafe { imp::SysStringLen(self.0) as usize }
}
}
/// Get the string as 16-bit wide characters (wchars).
pub fn as_wide(&self) -> &[u16] {
unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len()) }
}
/// Returns a raw pointer to the `BSTR` buffer.
pub fn as_ptr(&self) -> *const u16 {
if !self.is_empty() {
self.0
} else {
const EMPTY: [u16; 1] = [0];
EMPTY.as_ptr()
}
}
/// Create a `BSTR` from a slice of 16 bit characters (wchars).
pub fn from_wide(value: &[u16]) -> Result<Self> {
if value.is_empty() {
return Ok(Self::new());
}
let result = unsafe {
Self(imp::SysAllocStringLen(
value.as_ptr(),
value.len().try_into()?,
))
};
if result.is_empty() {
Err(imp::E_OUTOFMEMORY.into())
} else {
Ok(result)
}
}
/// # Safety
#[doc(hidden)]
pub unsafe fn from_raw(raw: *const u16) -> Self {
Self(raw)
}
/// # Safety
#[doc(hidden)]
pub fn into_raw(self) -> *const u16 {
unsafe { core::mem::transmute(self) }
}
}
impl Clone for BSTR {
fn clone(&self) -> Self {
Self::from_wide(self.as_wide()).unwrap()
}
}
impl From<&str> for BSTR {
fn from(value: &str) -> Self {
let value: Vec<u16> = value.encode_utf16().collect();
Self::from_wide(&value).unwrap()
}
}
impl From<String> for BSTR {
fn from(value: String) -> Self {
value.as_str().into()
}
}
impl From<&String> for BSTR {
fn from(value: &String) -> Self {
value.as_str().into()
}
}
impl<'a> TryFrom<&'a BSTR> for String {
type Error = alloc::string::FromUtf16Error;
fn try_from(value: &BSTR) -> core::result::Result<Self, Self::Error> {
String::from_utf16(value.as_wide())
}
}
impl TryFrom<BSTR> for String {
type Error = alloc::string::FromUtf16Error;
fn try_from(value: BSTR) -> core::result::Result<Self, Self::Error> {
String::try_from(&value)
}
}
impl Default for BSTR {
fn default() -> Self {
Self(core::ptr::null_mut())
}
}
impl core::fmt::Display for BSTR {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::write!(
f,
"{}",
Decode(|| core::char::decode_utf16(self.as_wide().iter().cloned()))
)
}
}
impl core::fmt::Debug for BSTR {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::write!(f, "{}", self)
}
}
impl PartialEq for BSTR {
fn eq(&self, other: &Self) -> bool {
self.as_wide() == other.as_wide()
}
}
impl Eq for BSTR {}
impl PartialEq<BSTR> for &str {
fn eq(&self, other: &BSTR) -> bool {
other == self
}
}
impl PartialEq<BSTR> for String {
fn eq(&self, other: &BSTR) -> bool {
other == self
}
}
impl<T: AsRef<str> + ?Sized> PartialEq<T> for BSTR {
fn eq(&self, other: &T) -> bool {
self.as_wide()
.iter()
.copied()
.eq(other.as_ref().encode_utf16())
}
}
impl Drop for BSTR {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { imp::SysFreeString(self.0) }
}
}
}

View File

@@ -0,0 +1,459 @@
use super::*;
/// A WinRT string ([HSTRING](https://docs.microsoft.com/en-us/windows/win32/winrt/hstring))
/// is reference-counted and immutable.
#[repr(transparent)]
pub struct HSTRING(Option<core::ptr::NonNull<Header>>);
impl HSTRING {
/// Create an empty `HSTRING`.
///
/// This function does not allocate memory.
pub const fn new() -> Self {
Self(None)
}
/// Returns `true` if the string is empty.
pub const fn is_empty(&self) -> bool {
// An empty HSTRING is represented by a null pointer.
self.0.is_none()
}
/// Returns the length of the string. The length is measured in `u16`s (UTF-16 code units), not including the terminating null character.
pub fn len(&self) -> usize {
if let Some(header) = self.get_header() {
header.len as usize
} else {
0
}
}
/// Get the string as 16-bit wide characters (wchars).
pub fn as_wide(&self) -> &[u16] {
unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len()) }
}
/// Returns a raw pointer to the `HSTRING` buffer.
pub fn as_ptr(&self) -> *const u16 {
if let Some(header) = self.get_header() {
header.data
} else {
const EMPTY: [u16; 1] = [0];
EMPTY.as_ptr()
}
}
/// Create a `HSTRING` from a slice of 16 bit characters (wchars).
pub fn from_wide(value: &[u16]) -> Result<Self> {
unsafe { Self::from_wide_iter(value.iter().copied(), value.len()) }
}
/// Get the contents of this `HSTRING` as a String lossily.
pub fn to_string_lossy(&self) -> String {
String::from_utf16_lossy(self.as_wide())
}
/// Get the contents of this `HSTRING` as a OsString.
#[cfg(all(feature = "std", windows))]
pub fn to_os_string(&self) -> std::ffi::OsString {
std::os::windows::ffi::OsStringExt::from_wide(self.as_wide())
}
/// # Safety
/// len must not be less than the number of items in the iterator.
unsafe fn from_wide_iter<I: Iterator<Item = u16>>(iter: I, len: usize) -> Result<Self> {
if len == 0 {
return Ok(Self::new());
}
let ptr = Header::alloc(len.try_into()?)?;
// Place each utf-16 character into the buffer and
// increase len as we go along.
for (index, wide) in iter.enumerate() {
debug_assert!(index < len);
core::ptr::write((*ptr).data.add(index), wide);
(*ptr).len = index as u32 + 1;
}
// Write a 0 byte to the end of the buffer.
core::ptr::write((*ptr).data.offset((*ptr).len as isize), 0);
Ok(Self(core::ptr::NonNull::new(ptr)))
}
fn get_header(&self) -> Option<&Header> {
self.0.map(|header| unsafe { header.as_ref() })
}
}
impl Default for HSTRING {
fn default() -> Self {
Self::new()
}
}
impl Clone for HSTRING {
fn clone(&self) -> Self {
if let Some(header) = self.get_header() {
Self(core::ptr::NonNull::new(header.duplicate().unwrap()))
} else {
Self::new()
}
}
}
impl Drop for HSTRING {
fn drop(&mut self) {
if self.is_empty() {
return;
}
if let Some(header) = self.0.take() {
// REFERENCE_FLAG indicates a string backed by static or stack memory that is
// thus not reference-counted and does not need to be freed.
unsafe {
let header = header.as_ref();
if header.flags & REFERENCE_FLAG == 0 && header.count.release() == 0 {
imp::heap_free(header as *const _ as *mut _);
}
}
}
}
}
unsafe impl Send for HSTRING {}
unsafe impl Sync for HSTRING {}
impl core::fmt::Display for HSTRING {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"{}",
Decode(|| core::char::decode_utf16(self.as_wide().iter().cloned()))
)
}
}
impl core::fmt::Debug for HSTRING {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "\"{}\"", self)
}
}
impl From<&str> for HSTRING {
fn from(value: &str) -> Self {
unsafe { Self::from_wide_iter(value.encode_utf16(), value.len()).unwrap() }
}
}
impl From<String> for HSTRING {
fn from(value: String) -> Self {
value.as_str().into()
}
}
impl From<&String> for HSTRING {
fn from(value: &String) -> Self {
value.as_str().into()
}
}
#[cfg(all(feature = "std", windows))]
impl From<&std::path::Path> for HSTRING {
fn from(value: &std::path::Path) -> Self {
value.as_os_str().into()
}
}
#[cfg(all(feature = "std", windows))]
impl From<&std::ffi::OsStr> for HSTRING {
fn from(value: &std::ffi::OsStr) -> Self {
unsafe {
Self::from_wide_iter(
std::os::windows::ffi::OsStrExt::encode_wide(value),
value.len(),
)
.unwrap()
}
}
}
#[cfg(all(feature = "std", windows))]
impl From<std::ffi::OsString> for HSTRING {
fn from(value: std::ffi::OsString) -> Self {
value.as_os_str().into()
}
}
#[cfg(all(feature = "std", windows))]
impl From<&std::ffi::OsString> for HSTRING {
fn from(value: &std::ffi::OsString) -> Self {
value.as_os_str().into()
}
}
impl Eq for HSTRING {}
impl Ord for HSTRING {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.as_wide().cmp(other.as_wide())
}
}
impl core::hash::Hash for HSTRING {
fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
self.as_wide().hash(hasher)
}
}
impl PartialOrd for HSTRING {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for HSTRING {
fn eq(&self, other: &Self) -> bool {
*self.as_wide() == *other.as_wide()
}
}
impl PartialEq<String> for HSTRING {
fn eq(&self, other: &String) -> bool {
*self == **other
}
}
impl PartialEq<String> for &HSTRING {
fn eq(&self, other: &String) -> bool {
**self == **other
}
}
impl PartialEq<&String> for HSTRING {
fn eq(&self, other: &&String) -> bool {
*self == ***other
}
}
impl PartialEq<str> for HSTRING {
fn eq(&self, other: &str) -> bool {
self.as_wide().iter().copied().eq(other.encode_utf16())
}
}
impl PartialEq<str> for &HSTRING {
fn eq(&self, other: &str) -> bool {
**self == *other
}
}
impl PartialEq<&str> for HSTRING {
fn eq(&self, other: &&str) -> bool {
*self == **other
}
}
impl PartialEq<HSTRING> for str {
fn eq(&self, other: &HSTRING) -> bool {
*other == *self
}
}
impl PartialEq<HSTRING> for &str {
fn eq(&self, other: &HSTRING) -> bool {
*other == **self
}
}
impl PartialEq<&HSTRING> for str {
fn eq(&self, other: &&HSTRING) -> bool {
**other == *self
}
}
impl PartialEq<HSTRING> for String {
fn eq(&self, other: &HSTRING) -> bool {
*other == **self
}
}
impl PartialEq<HSTRING> for &String {
fn eq(&self, other: &HSTRING) -> bool {
*other == ***self
}
}
impl PartialEq<&HSTRING> for String {
fn eq(&self, other: &&HSTRING) -> bool {
**other == **self
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<std::ffi::OsString> for HSTRING {
fn eq(&self, other: &std::ffi::OsString) -> bool {
*self == **other
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<std::ffi::OsString> for &HSTRING {
fn eq(&self, other: &std::ffi::OsString) -> bool {
**self == **other
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<&std::ffi::OsString> for HSTRING {
fn eq(&self, other: &&std::ffi::OsString) -> bool {
*self == ***other
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<std::ffi::OsStr> for HSTRING {
fn eq(&self, other: &std::ffi::OsStr) -> bool {
self.as_wide()
.iter()
.copied()
.eq(std::os::windows::ffi::OsStrExt::encode_wide(other))
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<std::ffi::OsStr> for &HSTRING {
fn eq(&self, other: &std::ffi::OsStr) -> bool {
**self == *other
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<&std::ffi::OsStr> for HSTRING {
fn eq(&self, other: &&std::ffi::OsStr) -> bool {
*self == **other
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<HSTRING> for std::ffi::OsStr {
fn eq(&self, other: &HSTRING) -> bool {
*other == *self
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<HSTRING> for &std::ffi::OsStr {
fn eq(&self, other: &HSTRING) -> bool {
*other == **self
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<&HSTRING> for std::ffi::OsStr {
fn eq(&self, other: &&HSTRING) -> bool {
**other == *self
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<HSTRING> for std::ffi::OsString {
fn eq(&self, other: &HSTRING) -> bool {
*other == **self
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<HSTRING> for &std::ffi::OsString {
fn eq(&self, other: &HSTRING) -> bool {
*other == ***self
}
}
#[cfg(all(feature = "std", windows))]
impl PartialEq<&HSTRING> for std::ffi::OsString {
fn eq(&self, other: &&HSTRING) -> bool {
**other == **self
}
}
impl<'a> TryFrom<&'a HSTRING> for String {
type Error = alloc::string::FromUtf16Error;
fn try_from(hstring: &HSTRING) -> core::result::Result<Self, Self::Error> {
String::from_utf16(hstring.as_wide())
}
}
impl TryFrom<HSTRING> for String {
type Error = alloc::string::FromUtf16Error;
fn try_from(hstring: HSTRING) -> core::result::Result<Self, Self::Error> {
String::try_from(&hstring)
}
}
#[cfg(all(feature = "std", windows))]
impl<'a> From<&'a HSTRING> for std::ffi::OsString {
fn from(hstring: &HSTRING) -> Self {
hstring.to_os_string()
}
}
#[cfg(all(feature = "std", windows))]
impl From<HSTRING> for std::ffi::OsString {
fn from(hstring: HSTRING) -> Self {
Self::from(&hstring)
}
}
const REFERENCE_FLAG: u32 = 1;
#[repr(C)]
struct Header {
flags: u32,
len: u32,
_0: u32,
_1: u32,
data: *mut u16,
count: imp::RefCount,
buffer_start: u16,
}
impl Header {
fn alloc(len: u32) -> Result<*mut Header> {
debug_assert!(len != 0);
// Allocate enough space for header and two bytes per character.
// The space for the terminating null character is already accounted for inside of `Header`.
let alloc_size = core::mem::size_of::<Header>() + 2 * len as usize;
let header = imp::heap_alloc(alloc_size)? as *mut Header;
// SAFETY: uses `core::ptr::write` (since `header` is unintialized). `Header` is safe to be all zeros.
unsafe {
header.write(core::mem::MaybeUninit::<Header>::zeroed().assume_init());
(*header).len = len;
(*header).count = imp::RefCount::new(1);
(*header).data = &mut (*header).buffer_start;
}
Ok(header)
}
fn duplicate(&self) -> Result<*mut Header> {
if self.flags & REFERENCE_FLAG == 0 {
// If this is not a "fast pass" string then simply increment the reference count.
self.count.add_ref();
Ok(self as *const Header as *mut Header)
} else {
// Otherwise, allocate a new string and copy the value into the new string.
let copy = Header::alloc(self.len)?;
// SAFETY: since we are duplicating the string it is safe to copy all data from self to the initialized `copy`.
// We copy `len + 1` characters since `len` does not account for the terminating null character.
unsafe {
core::ptr::copy_nonoverlapping(self.data, (*copy).data, self.len as usize + 1);
}
Ok(copy)
}
}
}

View File

@@ -0,0 +1,167 @@
/// A literal UTF-8 string with a trailing null terminator.
#[macro_export]
macro_rules! s {
($s:literal) => {
$crate::PCSTR::from_raw(::core::concat!($s, '\0').as_ptr())
};
}
/// A literal UTF-16 wide string with a trailing null terminator.
#[macro_export]
macro_rules! w {
($s:literal) => {{
const INPUT: &[u8] = $s.as_bytes();
const OUTPUT_LEN: usize = $crate::utf16_len(INPUT) + 1;
const OUTPUT: &[u16; OUTPUT_LEN] = {
let mut buffer = [0; OUTPUT_LEN];
let mut input_pos = 0;
let mut output_pos = 0;
while let Some((mut code_point, new_pos)) = $crate::decode_utf8_char(INPUT, input_pos) {
input_pos = new_pos;
if code_point <= 0xffff {
buffer[output_pos] = code_point as u16;
output_pos += 1;
} else {
code_point -= 0x10000;
buffer[output_pos] = 0xd800 + (code_point >> 10) as u16;
output_pos += 1;
buffer[output_pos] = 0xdc00 + (code_point & 0x3ff) as u16;
output_pos += 1;
}
}
&{ buffer }
};
$crate::PCWSTR::from_raw(OUTPUT.as_ptr())
}};
}
/// A literal HSTRING, length-prefixed wide string with a trailing null terminator.
#[macro_export]
macro_rules! h {
($s:literal) => {{
const INPUT: &[u8] = $s.as_bytes();
const OUTPUT_LEN: usize = $crate::utf16_len(INPUT) + 1;
#[allow(clippy::declare_interior_mutable_const)]
const RESULT: $crate::HSTRING = {
if OUTPUT_LEN == 1 {
unsafe { ::std::mem::transmute(::std::ptr::null::<u16>()) }
} else {
const OUTPUT: $crate::PCWSTR = $crate::w!($s);
const HEADER: $crate::HSTRING_HEADER = $crate::HSTRING_HEADER {
flags: 0x11,
len: (OUTPUT_LEN - 1) as u32,
padding1: 0,
padding2: 0,
ptr: OUTPUT.as_ptr(),
};
// SAFETY: an `HSTRING` is exactly equivalent to a pointer to an `HSTRING_HEADER`
unsafe {
::std::mem::transmute::<&$crate::HSTRING_HEADER, $crate::HSTRING>(&HEADER)
}
}
};
#[allow(clippy::borrow_interior_mutable_const)]
&RESULT
}};
}
#[doc(hidden)]
pub const fn decode_utf8_char(bytes: &[u8], mut pos: usize) -> Option<(u32, usize)> {
if bytes.len() == pos {
return None;
}
let ch = bytes[pos] as u32;
pos += 1;
if ch <= 0x7f {
return Some((ch, pos));
}
if (ch & 0xe0) == 0xc0 {
if bytes.len() - pos < 1 {
return None;
}
let ch2 = bytes[pos] as u32;
pos += 1;
if (ch2 & 0xc0) != 0x80 {
return None;
}
let result: u32 = ((ch & 0x1f) << 6) | (ch2 & 0x3f);
if result <= 0x7f {
return None;
}
return Some((result, pos));
}
if (ch & 0xf0) == 0xe0 {
if bytes.len() - pos < 2 {
return None;
}
let ch2 = bytes[pos] as u32;
pos += 1;
let ch3 = bytes[pos] as u32;
pos += 1;
if (ch2 & 0xc0) != 0x80 || (ch3 & 0xc0) != 0x80 {
return None;
}
let result = ((ch & 0x0f) << 12) | ((ch2 & 0x3f) << 6) | (ch3 & 0x3f);
if result <= 0x7ff || (0xd800 <= result && result <= 0xdfff) {
return None;
}
return Some((result, pos));
}
if (ch & 0xf8) == 0xf0 {
if bytes.len() - pos < 3 {
return None;
}
let ch2 = bytes[pos] as u32;
pos += 1;
let ch3 = bytes[pos] as u32;
pos += 1;
let ch4 = bytes[pos] as u32;
pos += 1;
if (ch2 & 0xc0) != 0x80 || (ch3 & 0xc0) != 0x80 || (ch4 & 0xc0) != 0x80 {
return None;
}
let result =
((ch & 0x07) << 18) | ((ch2 & 0x3f) << 12) | ((ch3 & 0x3f) << 6) | (ch4 & 0x3f);
if result <= 0xffff || 0x10ffff < result {
return None;
}
return Some((result, pos));
}
None
}
#[doc(hidden)]
#[repr(C)]
pub struct HSTRING_HEADER {
pub flags: u32,
pub len: u32,
pub padding1: u32,
pub padding2: u32,
pub ptr: *const u16,
}
#[doc(hidden)]
pub const fn utf16_len(bytes: &[u8]) -> usize {
let mut pos = 0;
let mut len = 0;
while let Some((code_point, new_pos)) = decode_utf8_char(bytes, pos) {
pos = new_pos;
len += if code_point <= 0xffff { 1 } else { 2 };
}
len
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(decode_utf8_char(b"123", 0), Some((0x31, 1)));
assert_eq!(decode_utf8_char(b"123", 1), Some((0x32, 2)));
assert_eq!(decode_utf8_char(b"123", 2), Some((0x33, 3)));
assert_eq!(decode_utf8_char(b"123", 3), None);
assert_eq!(utf16_len(b"123"), 3);
assert_eq!(utf16_len("α & ω".as_bytes()), 5);
}
}

View File

@@ -0,0 +1,82 @@
mod bstr;
mod hstring;
mod literals;
mod pcstr;
mod pcwstr;
mod pstr;
mod pwstr;
pub use bstr::*;
pub use hstring::*;
#[doc(hidden)]
pub use literals::*;
pub use pcstr::*;
pub use pcwstr::*;
pub use pstr::*;
pub use pwstr::*;
use super::*;
extern "C" {
#[doc(hidden)]
pub fn strlen(s: PCSTR) -> usize;
}
/// An internal helper for decoding an iterator of chars and displaying them
struct Decode<F>(pub F);
impl<F, R, E> core::fmt::Display for Decode<F>
where
F: Clone + FnOnce() -> R,
R: IntoIterator<Item = core::result::Result<char, E>>,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use core::fmt::Write;
let iter = self.0.clone();
for c in iter().into_iter() {
f.write_char(c.unwrap_or(core::char::REPLACEMENT_CHARACTER))?
}
Ok(())
}
}
/// Mirror of `std::char::decode_utf16` for utf-8.
fn decode_utf8(
mut buffer: &[u8],
) -> impl Iterator<Item = core::result::Result<char, core::str::Utf8Error>> + '_ {
let mut current = "".chars();
let mut previous_error = None;
core::iter::from_fn(move || {
loop {
match (current.next(), previous_error) {
(Some(c), _) => return Some(Ok(c)),
// Return the previous error
(None, Some(e)) => {
previous_error = None;
return Some(Err(e));
}
// We're completely done
(None, None) if buffer.is_empty() => return None,
(None, None) => {
match core::str::from_utf8(buffer) {
Ok(s) => {
current = s.chars();
buffer = &[];
}
Err(e) => {
let (valid, rest) = buffer.split_at(e.valid_up_to());
// Skip the invalid sequence and stop completely if we ended early
let invalid_sequence_length = e.error_len()?;
buffer = &rest[invalid_sequence_length..];
// Set the current iterator to the valid section and indicate previous error
// SAFETY: `valid` is known to be valid utf-8 from error
current = unsafe { core::str::from_utf8_unchecked(valid) }.chars();
previous_error = Some(e);
}
}
}
}
}
})
}

View File

@@ -0,0 +1,56 @@
use super::*;
/// A pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PCSTR(pub *const u8);
impl PCSTR {
/// Construct a new `PCSTR` from a raw pointer
pub const fn from_raw(ptr: *const u8) -> Self {
Self(ptr)
}
/// Construct a null `PCSTR`
pub const fn null() -> Self {
Self(core::ptr::null())
}
/// Returns a raw pointer to the `PCSTR`
pub const fn as_ptr(&self) -> *const u8 {
self.0
}
/// Checks whether the `PCSTR` is null
pub fn is_null(&self) -> bool {
self.0.is_null()
}
/// String data without the trailing 0
///
/// # Safety
///
/// The `PCSTR`'s pointer needs to be valid for reads up until and including the next `\0`.
pub unsafe fn as_bytes(&self) -> &[u8] {
let len = strlen(*self);
core::slice::from_raw_parts(self.0, len)
}
/// Copy the `PCSTR` into a Rust `String`.
///
/// # Safety
///
/// See the safety information for `PCSTR::as_bytes`.
pub unsafe fn to_string(&self) -> core::result::Result<String, alloc::string::FromUtf8Error> {
String::from_utf8(self.as_bytes().into())
}
/// Allow this string to be displayed.
///
/// # Safety
///
/// See the safety information for `PCSTR::as_bytes`.
pub unsafe fn display(&self) -> impl core::fmt::Display + '_ {
Decode(move || decode_utf8(self.as_bytes()))
}
}

View File

@@ -0,0 +1,101 @@
use super::*;
/// A pointer to a constant null-terminated string of 16-bit Unicode characters.
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PCWSTR(pub *const u16);
impl PCWSTR {
/// Construct a new `PCWSTR` from a raw pointer
pub const fn from_raw(ptr: *const u16) -> Self {
Self(ptr)
}
/// Construct a null `PCWSTR`
pub const fn null() -> Self {
Self(core::ptr::null())
}
/// Returns a raw pointer to the `PCWSTR`
pub const fn as_ptr(&self) -> *const u16 {
self.0
}
/// Checks whether the `PCWSTR` is null
pub fn is_null(&self) -> bool {
self.0.is_null()
}
/// String length without the trailing 0
///
/// # Safety
///
/// The `PCWSTR`'s pointer needs to be valid for reads up until and including the next `\0`.
pub unsafe fn len(&self) -> usize {
#[cfg(windows)]
let len = {
extern "C" {
fn wcslen(s: *const u16) -> usize;
}
wcslen(self.0)
};
#[cfg(not(windows))]
let len = {
let mut len = 0;
let mut ptr = self.0;
while ptr.read() != 0 {
len += 1;
ptr = ptr.add(1);
}
len
};
len
}
/// Returns `true` if the string length is zero, and `false` otherwise.
///
/// # Safety
///
/// The `PCWSTR`'s pointer needs to be valid for reads up until and including the next `\0`.
pub unsafe fn is_empty(&self) -> bool {
self.len() == 0
}
/// String data without the trailing 0
///
/// # Safety
///
/// The `PCWSTR`'s pointer needs to be valid for reads up until and including the next `\0`.
pub unsafe fn as_wide(&self) -> &[u16] {
core::slice::from_raw_parts(self.0, self.len())
}
/// Copy the `PCWSTR` into a Rust `String`.
///
/// # Safety
///
/// See the safety information for `PCWSTR::as_wide`.
pub unsafe fn to_string(&self) -> core::result::Result<String, alloc::string::FromUtf16Error> {
String::from_utf16(self.as_wide())
}
/// Copy the `PCWSTR` into an `HSTRING`.
///
/// # Safety
///
/// See the safety information for `PCWSTR::as_wide`.
pub unsafe fn to_hstring(&self) -> Result<HSTRING> {
HSTRING::from_wide(self.as_wide())
}
/// Allow this string to be displayed.
///
/// # Safety
///
/// See the safety information for `PCWSTR::as_wide`.
pub unsafe fn display(&self) -> impl core::fmt::Display + '_ {
Decode(move || core::char::decode_utf16(self.as_wide().iter().cloned()))
}
}

View File

@@ -0,0 +1,56 @@
use super::*;
/// A pointer to a null-terminated string of 8-bit Windows (ANSI) characters.
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PSTR(pub *mut u8);
impl PSTR {
/// Construct a new `PSTR` from a raw pointer
pub const fn from_raw(ptr: *mut u8) -> Self {
Self(ptr)
}
/// Construct a null `PSTR`
pub const fn null() -> Self {
Self(core::ptr::null_mut())
}
/// Returns a raw pointer to the `PSTR`
pub const fn as_ptr(&self) -> *mut u8 {
self.0
}
/// Checks whether the `PSTR` is null
pub fn is_null(&self) -> bool {
self.0.is_null()
}
/// String data without the trailing 0
///
/// # Safety
///
/// The `PSTR`'s pointer needs to be valid for reads up until and including the next `\0`.
pub unsafe fn as_bytes(&self) -> &[u8] {
let len = strlen(PCSTR::from_raw(self.0));
core::slice::from_raw_parts(self.0, len)
}
/// Copy the `PSTR` into a Rust `String`.
///
/// # Safety
///
/// See the safety information for `PSTR::as_bytes`.
pub unsafe fn to_string(&self) -> core::result::Result<String, alloc::string::FromUtf8Error> {
String::from_utf8(self.as_bytes().into())
}
/// Allow this string to be displayed.
///
/// # Safety
///
/// See the safety information for `PSTR::as_bytes`.
pub unsafe fn display(&self) -> impl core::fmt::Display + '_ {
Decode(move || decode_utf8(self.as_bytes()))
}
}

View File

@@ -0,0 +1,82 @@
use super::*;
/// A pointer to a null-terminated string of 16-bit Unicode characters.
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PWSTR(pub *mut u16);
impl PWSTR {
/// Construct a new `PWSTR` from a raw pointer.
pub const fn from_raw(ptr: *mut u16) -> Self {
Self(ptr)
}
/// Construct a null `PWSTR`.
pub const fn null() -> Self {
Self(core::ptr::null_mut())
}
/// Returns a raw pointer to the `PWSTR`.
pub const fn as_ptr(&self) -> *mut u16 {
self.0
}
/// Checks whether the `PWSTR` is null.
pub fn is_null(&self) -> bool {
self.0.is_null()
}
/// String length without the trailing 0
///
/// # Safety
///
/// The `PWSTR`'s pointer needs to be valid for reads up until and including the next `\0`.
pub unsafe fn len(&self) -> usize {
PCWSTR(self.0).len()
}
/// Returns `true` if the string length is zero, and `false` otherwise.
///
/// # Safety
///
/// The `PWSTR`'s pointer needs to be valid for reads up until and including the next `\0`.
pub unsafe fn is_empty(&self) -> bool {
self.len() == 0
}
/// String data without the trailing 0.
///
/// # Safety
///
/// The `PWSTR`'s pointer needs to be valid for reads up until and including the next `\0`.
pub unsafe fn as_wide(&self) -> &[u16] {
core::slice::from_raw_parts(self.0, self.len())
}
/// Copy the `PWSTR` into a Rust `String`.
///
/// # Safety
///
/// See the safety information for `PWSTR::as_wide`.
pub unsafe fn to_string(&self) -> core::result::Result<String, alloc::string::FromUtf16Error> {
String::from_utf16(self.as_wide())
}
/// Copy the `PWSTR` into an `HSTRING`.
///
/// # Safety
///
/// See the safety information for `PWSTR::as_wide`.
pub unsafe fn to_hstring(&self) -> Result<HSTRING> {
HSTRING::from_wide(self.as_wide())
}
/// Allow this string to be displayed.
///
/// # Safety
///
/// See the safety information for `PWSTR::as_wide`.
pub unsafe fn display(&self) -> impl core::fmt::Display + '_ {
Decode(move || core::char::decode_utf16(self.as_wide().iter().cloned()))
}
}

124
vendor/windows-core-0.57.0/src/type.rs vendored Normal file
View File

@@ -0,0 +1,124 @@
use super::*;
#[doc(hidden)]
pub trait TypeKind {
type TypeKind;
}
#[doc(hidden)]
pub struct InterfaceType;
#[doc(hidden)]
pub struct CloneType;
#[doc(hidden)]
pub struct CopyType;
#[doc(hidden)]
pub trait Type<T: TypeKind, C = <T as TypeKind>::TypeKind>: TypeKind + Sized + Clone {
type Abi;
type Default;
/// # Safety
unsafe fn from_abi(abi: Self::Abi) -> Result<Self>;
fn from_default(default: &Self::Default) -> Result<Self>;
}
impl<T> Type<T, InterfaceType> for T
where
T: TypeKind<TypeKind = InterfaceType> + Clone,
{
type Abi = *mut core::ffi::c_void;
type Default = Option<Self>;
unsafe fn from_abi(abi: Self::Abi) -> Result<Self> {
if !abi.is_null() {
Ok(core::mem::transmute_copy(&abi))
} else {
Err(Error::empty())
}
}
fn from_default(default: &Self::Default) -> Result<Self> {
default.as_ref().cloned().ok_or(Error::empty())
}
}
impl<T> Type<T, CloneType> for T
where
T: TypeKind<TypeKind = CloneType> + Clone,
{
type Abi = core::mem::MaybeUninit<Self>;
type Default = Self;
unsafe fn from_abi(abi: Self::Abi) -> Result<Self> {
Ok(abi.assume_init())
}
fn from_default(default: &Self::Default) -> Result<Self> {
Ok(default.clone())
}
}
impl<T> Type<T, CopyType> for T
where
T: TypeKind<TypeKind = CopyType> + Clone,
{
type Abi = Self;
type Default = Self;
unsafe fn from_abi(abi: Self::Abi) -> Result<Self> {
Ok(abi)
}
fn from_default(default: &Self) -> Result<Self> {
Ok(default.clone())
}
}
impl<T: Interface> TypeKind for T {
type TypeKind = InterfaceType;
}
impl<T> TypeKind for *mut T {
type TypeKind = CopyType;
}
macro_rules! primitives {
($($t:ty),+) => {
$(
impl TypeKind for $t {
type TypeKind = CopyType;
}
)*
};
}
primitives!(bool, i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, usize, isize);
#[doc(hidden)]
pub type AbiType<T> = <T as Type<T>>::Abi;
impl TypeKind for PWSTR {
type TypeKind = CopyType;
}
impl TypeKind for PSTR {
type TypeKind = CopyType;
}
impl TypeKind for PCWSTR {
type TypeKind = CopyType;
}
impl TypeKind for PCSTR {
type TypeKind = CopyType;
}
impl TypeKind for HSTRING {
type TypeKind = CloneType;
}
impl TypeKind for BSTR {
type TypeKind = CloneType;
}

View File

@@ -0,0 +1,193 @@
use super::*;
use core::ffi::c_void;
use core::ptr::NonNull;
/// All COM interfaces (and thus WinRT classes and interfaces) implement
/// [IUnknown](https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown)
/// under the hood to provide reference-counted lifetime management as well as the ability
/// to query for additional interfaces that the object may implement.
#[repr(transparent)]
pub struct IUnknown(NonNull<c_void>);
#[doc(hidden)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub struct IUnknown_Vtbl {
pub QueryInterface: unsafe extern "system" fn(
this: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT,
pub AddRef: unsafe extern "system" fn(this: *mut c_void) -> u32,
pub Release: unsafe extern "system" fn(this: *mut c_void) -> u32,
}
unsafe impl Interface for IUnknown {
type Vtable = IUnknown_Vtbl;
const IID: GUID = GUID::from_u128(0x00000000_0000_0000_c000_000000000046);
}
impl Clone for IUnknown {
fn clone(&self) -> Self {
unsafe {
(self.vtable().AddRef)(core::mem::transmute_copy(self));
}
Self(self.0)
}
}
impl Drop for IUnknown {
fn drop(&mut self) {
unsafe {
(self.vtable().Release)(core::mem::transmute_copy(self));
}
}
}
impl PartialEq for IUnknown {
fn eq(&self, other: &Self) -> bool {
// First we test for ordinary pointer equality. If two COM interface pointers have the
// same pointer value, then they are the same object. This can save us a lot of time,
// since calling QueryInterface is much more expensive than a single pointer comparison.
//
// However, interface pointers may have different values and yet point to the same object.
// Since COM objects may implement multiple interfaces, COM identity can only
// be determined by querying for `IUnknown` explicitly and then comparing the
// pointer values. This works since `QueryInterface` is required to return
// the same pointer value for queries for `IUnknown`.
self.as_raw() == other.as_raw()
|| self.cast::<IUnknown>().unwrap().0 == other.cast::<IUnknown>().unwrap().0
}
}
impl Eq for IUnknown {}
impl core::fmt::Debug for IUnknown {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("IUnknown").field(&self.as_raw()).finish()
}
}
/// The `#[implement]` macro generates implementations of this trait for the types
/// that it generates, e.g. `MyApp_Impl`,
///
/// `ComObject` uses this trait to interact with boxed COM objects.
#[doc(hidden)]
pub trait IUnknownImpl {
/// The contained user type, e.g. `MyApp`. Also known as the "inner" type.
type Impl;
/// Get a reference to the backing implementation.
fn get_impl(&self) -> &Self::Impl;
/// Get a mutable reference to the contained (inner) object.
fn get_impl_mut(&mut self) -> &mut Self::Impl;
/// Consumes the box and returns the contained (inner) object. This is the opposite of `new_box`.
fn into_inner(self) -> Self::Impl;
/// The classic `QueryInterface` method from COM.
///
/// # Safety
///
/// This function is safe to call as long as the interface pointer is non-null and valid for writes
/// of an interface pointer.
unsafe fn QueryInterface(&self, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT;
/// Increments the reference count of the interface
fn AddRef(&self) -> u32;
/// Decrements the reference count causing the interface's memory to be freed when the count is 0
///
/// # Safety
///
/// This function should only be called when the interface pointer is no longer used as calling `Release`
/// on a non-aliased interface pointer and then using that interface pointer may result in use after free.
///
/// This function takes `*mut Self` because the object may be freed by the time this method returns.
/// Taking `&self` would violate Rust's rules on reference lifetime.
unsafe fn Release(self_: *mut Self) -> u32;
/// Returns `true` if the reference count of the box is equal to 1.
fn is_reference_count_one(&self) -> bool;
/// Gets the trust level of the current object.
unsafe fn GetTrustLevel(&self, value: *mut i32) -> HRESULT;
/// Given a reference to an inner type, returns a reference to the outer shared type.
///
/// # Safety
///
/// This function should only be called from methods that implement COM interfaces, i.e.
/// implementations of methods on `IFoo_Impl` traits.
// TODO: This can be made safe, if IFoo_Impl are moved to the Object_Impl types.
// That requires some substantial redesign, though.
unsafe fn from_inner_ref(inner: &Self::Impl) -> &Self;
/// Gets a borrowed reference to an interface that is implemented by this ComObject.
///
/// The returned reference does not have an additional reference count.
/// You can AddRef it by calling to_owned().
#[inline(always)]
fn as_interface<I: Interface>(&self) -> InterfaceRef<'_, I>
where
Self: ComObjectInterface<I>,
{
<Self as ComObjectInterface<I>>::as_interface_ref(self)
}
/// Gets an owned (counted) reference to an interface that is implemented by this ComObject.
#[inline(always)]
fn to_interface<I: Interface>(&self) -> I
where
Self: ComObjectInterface<I>,
{
<Self as ComObjectInterface<I>>::as_interface_ref(self).to_owned()
}
/// Creates a new owned reference to this object.
///
/// # Safety
///
/// This function can only be safely called by `<Foo>_Impl` objects that are embedded in a
/// `ComObject`. Since we only allow safe Rust code to access these objects using a `ComObject`
/// or a `&<Foo>_Impl` that points within a `ComObject`, this is safe.
fn to_object(&self) -> ComObject<Self::Impl>
where
Self::Impl: ComObjectInner<Outer = Self>;
/// The distance from the start of `<Foo>_Impl` to the `this` field within it, measured in
/// pointer-sized elements. The `this` field contains the `MyApp` instance.
const INNER_OFFSET_IN_POINTERS: usize;
}
impl IUnknown_Vtbl {
pub const fn new<T: IUnknownImpl, const OFFSET: isize>() -> Self {
unsafe extern "system" fn QueryInterface<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T;
(*this).QueryInterface(iid, interface)
}
unsafe extern "system" fn AddRef<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
) -> u32 {
let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T;
(*this).AddRef()
}
unsafe extern "system" fn Release<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
) -> u32 {
let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T;
T::Release(this)
}
Self {
QueryInterface: QueryInterface::<T, OFFSET>,
AddRef: AddRef::<T, OFFSET>,
Release: Release::<T, OFFSET>,
}
}
}

View File

@@ -0,0 +1,852 @@
use super::*;
use core::mem::transmute;
/// A VARIANT ([VARIANT](https://learn.microsoft.com/en-us/windows/win32/api/oaidl/ns-oaidl-variant)) is a container that can store different types of values.
#[repr(transparent)]
pub struct VARIANT(imp::VARIANT);
/// A PROPVARIANT ([PROPVARIANT](https://learn.microsoft.com/en-us/windows/win32/api/propidlbase/ns-propidlbase-propvariant)) is a container that can store different types of values.
#[repr(transparent)]
pub struct PROPVARIANT(imp::PROPVARIANT);
impl Default for VARIANT {
fn default() -> Self {
Self::new()
}
}
impl Default for PROPVARIANT {
fn default() -> Self {
Self::new()
}
}
impl Clone for VARIANT {
fn clone(&self) -> Self {
unsafe {
let mut value = Self::new();
imp::VariantCopy(&mut value.0, &self.0);
value
}
}
}
impl Clone for PROPVARIANT {
fn clone(&self) -> Self {
unsafe {
let mut value = Self::new();
imp::PropVariantCopy(&mut value.0, &self.0);
value
}
}
}
impl Drop for VARIANT {
fn drop(&mut self) {
unsafe { imp::VariantClear(&mut self.0) };
}
}
impl Drop for PROPVARIANT {
fn drop(&mut self) {
unsafe { imp::PropVariantClear(&mut self.0) };
}
}
impl TypeKind for VARIANT {
type TypeKind = CloneType;
}
impl TypeKind for PROPVARIANT {
type TypeKind = CloneType;
}
impl core::fmt::Debug for VARIANT {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut debug = f.debug_struct("VARIANT");
debug.field("type", &unsafe { self.0.Anonymous.Anonymous.vt });
if let Ok(value) = BSTR::try_from(self) {
debug.field("value", &value);
}
debug.finish()
}
}
impl core::fmt::Debug for PROPVARIANT {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut debug = f.debug_struct("PROPVARIANT");
debug.field("type", &unsafe { self.0.Anonymous.Anonymous.vt });
if let Ok(value) = BSTR::try_from(self) {
debug.field("value", &value);
}
debug.finish()
}
}
impl core::fmt::Display for VARIANT {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::write!(f, "{}", BSTR::try_from(self).unwrap_or_default())
}
}
impl core::fmt::Display for PROPVARIANT {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::write!(f, "{}", BSTR::try_from(self).unwrap_or_default())
}
}
impl PartialEq for VARIANT {
fn eq(&self, other: &Self) -> bool {
unsafe {
if self.0.Anonymous.Anonymous.vt != other.0.Anonymous.Anonymous.vt {
return false;
}
let this = PROPVARIANT::try_from(self);
let other = PROPVARIANT::try_from(other);
if let (Ok(this), Ok(other)) = (this, other) {
this.eq(&other)
} else {
false
}
}
}
}
impl PartialEq for PROPVARIANT {
fn eq(&self, other: &Self) -> bool {
unsafe {
if self.0.Anonymous.Anonymous.vt != other.0.Anonymous.Anonymous.vt {
return false;
}
imp::PropVariantCompareEx(&self.0, &other.0, 0, 0) == 0
}
}
}
impl Eq for VARIANT {}
impl Eq for PROPVARIANT {}
impl VARIANT {
/// Create an empty `VARIANT`.
///
/// This function does not allocate memory.
pub fn new() -> Self {
unsafe { core::mem::zeroed() }
}
/// Returns true if the `VARIANT` is empty.
pub const fn is_empty(&self) -> bool {
unsafe { self.0.Anonymous.Anonymous.vt == imp::VT_EMPTY }
}
/// Creates a `VARIANT` by taking ownership of the raw data.
///
/// # Safety
///
/// The raw data must be owned by the caller and represent a valid `VARIANT` data structure.
pub unsafe fn from_raw(raw: imp::VARIANT) -> Self {
Self(raw)
}
/// Returns the underlying raw data for the `VARIANT`.
pub fn as_raw(&self) -> &imp::VARIANT {
&self.0
}
}
impl PROPVARIANT {
/// Create an empty `PROPVARIANT`.
///
/// This function does not allocate memory.
pub fn new() -> Self {
unsafe { core::mem::zeroed() }
}
/// Returns true if the `PROPVARIANT` is empty.
pub const fn is_empty(&self) -> bool {
unsafe { self.0.Anonymous.Anonymous.vt == imp::VT_EMPTY }
}
/// Creates a `PROPVARIANT` by taking ownership of the raw data.
///
/// # Safety
///
/// The raw data must be owned by the caller and represent a valid `PROPVARIANT` data structure.
pub unsafe fn from_raw(raw: imp::PROPVARIANT) -> Self {
Self(raw)
}
/// Returns the underlying raw data for the `PROPVARIANT`.
pub fn as_raw(&self) -> &imp::PROPVARIANT {
&self.0
}
}
impl TryFrom<&VARIANT> for PROPVARIANT {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
unsafe {
let mut value = Self::new();
HRESULT(imp::VariantToPropVariant(&from.0, &mut value.0)).map(|| value)
}
}
}
impl TryFrom<&PROPVARIANT> for VARIANT {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
unsafe {
let mut value = Self::new();
HRESULT(imp::PropVariantToVariant(&from.0, &mut value.0)).map(|| value)
}
}
}
// VT_UNKNOWN
impl From<IUnknown> for VARIANT {
fn from(value: IUnknown) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_UNKNOWN,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 {
punkVal: value.into_raw(),
},
},
},
})
}
}
impl From<IUnknown> for PROPVARIANT {
fn from(value: IUnknown) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_UNKNOWN,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 {
punkVal: value.into_raw(),
},
},
},
})
}
}
impl TryFrom<&VARIANT> for IUnknown {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
unsafe {
if from.0.Anonymous.Anonymous.vt == imp::VT_UNKNOWN
&& !from.0.Anonymous.Anonymous.Anonymous.punkVal.is_null()
{
let unknown: &IUnknown = transmute(&from.0.Anonymous.Anonymous.Anonymous.punkVal);
Ok(unknown.clone())
} else {
Err(Error::from_hresult(imp::TYPE_E_TYPEMISMATCH))
}
}
}
}
impl TryFrom<&PROPVARIANT> for IUnknown {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
unsafe {
if from.0.Anonymous.Anonymous.vt == imp::VT_UNKNOWN
&& !from.0.Anonymous.Anonymous.Anonymous.punkVal.is_null()
{
let unknown: &IUnknown = transmute(&from.0.Anonymous.Anonymous.Anonymous.punkVal);
Ok(unknown.clone())
} else {
Err(Error::from_hresult(imp::TYPE_E_TYPEMISMATCH))
}
}
}
}
// VT_BSTR
impl From<BSTR> for VARIANT {
fn from(value: BSTR) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_BSTR,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 {
bstrVal: value.into_raw(),
},
},
},
})
}
}
impl From<BSTR> for PROPVARIANT {
fn from(value: BSTR) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_BSTR,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 {
bstrVal: value.into_raw(),
},
},
},
})
}
}
impl From<&str> for VARIANT {
fn from(value: &str) -> Self {
BSTR::from(value).into()
}
}
impl From<&str> for PROPVARIANT {
fn from(value: &str) -> Self {
BSTR::from(value).into()
}
}
impl TryFrom<&VARIANT> for BSTR {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let pv = PROPVARIANT::try_from(from)?;
BSTR::try_from(&pv)
}
}
impl TryFrom<&PROPVARIANT> for BSTR {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = Self::new();
HRESULT(unsafe { imp::PropVariantToBSTR(&from.0, &mut value as *mut _ as *mut _) })
.map(|| value)
}
}
// VT_BOOL
impl From<bool> for VARIANT {
fn from(value: bool) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_BOOL,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 {
boolVal: if value { -1 } else { 0 },
},
},
},
})
}
}
impl From<bool> for PROPVARIANT {
fn from(value: bool) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_BOOL,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 {
boolVal: if value { -1 } else { 0 },
},
},
},
})
}
}
impl TryFrom<&VARIANT> for bool {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::VariantToBoolean(&from.0, &mut value) }).map(|| value != 0)
}
}
impl TryFrom<&PROPVARIANT> for bool {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::PropVariantToBoolean(&from.0, &mut value) }).map(|| value != 0)
}
}
// VT_UI1
impl From<u8> for VARIANT {
fn from(value: u8) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_UI1,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { bVal: value },
},
},
})
}
}
impl From<u8> for PROPVARIANT {
fn from(value: u8) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_UI1,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { bVal: value },
},
},
})
}
}
// VT_I1
impl From<i8> for VARIANT {
fn from(value: i8) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_I1,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { cVal: value },
},
},
})
}
}
impl From<i8> for PROPVARIANT {
fn from(value: i8) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_I1,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { cVal: value },
},
},
})
}
}
// VT_UI2
impl From<u16> for VARIANT {
fn from(value: u16) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_UI2,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { uiVal: value },
},
},
})
}
}
impl From<u16> for PROPVARIANT {
fn from(value: u16) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_UI2,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { uiVal: value },
},
},
})
}
}
impl TryFrom<&VARIANT> for u16 {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::VariantToUInt16(&from.0, &mut value) }).map(|| value)
}
}
impl TryFrom<&PROPVARIANT> for u16 {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::PropVariantToUInt16(&from.0, &mut value) }).map(|| value)
}
}
// VT_I2
impl From<i16> for VARIANT {
fn from(value: i16) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_I2,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { iVal: value },
},
},
})
}
}
impl From<i16> for PROPVARIANT {
fn from(value: i16) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_I2,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { iVal: value },
},
},
})
}
}
impl TryFrom<&VARIANT> for i16 {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::VariantToInt16(&from.0, &mut value) }).map(|| value)
}
}
impl TryFrom<&PROPVARIANT> for i16 {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::PropVariantToInt16(&from.0, &mut value) }).map(|| value)
}
}
// VT_UI4
impl From<u32> for VARIANT {
fn from(value: u32) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_UI4,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { ulVal: value },
},
},
})
}
}
impl From<u32> for PROPVARIANT {
fn from(value: u32) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_UI4,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { ulVal: value },
},
},
})
}
}
impl TryFrom<&VARIANT> for u32 {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::VariantToUInt32(&from.0, &mut value) }).map(|| value)
}
}
impl TryFrom<&PROPVARIANT> for u32 {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::PropVariantToUInt32(&from.0, &mut value) }).map(|| value)
}
}
// VT_I4
impl From<i32> for VARIANT {
fn from(value: i32) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_I4,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { lVal: value },
},
},
})
}
}
impl From<i32> for PROPVARIANT {
fn from(value: i32) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_I4,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { lVal: value },
},
},
})
}
}
impl TryFrom<&VARIANT> for i32 {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::VariantToInt32(&from.0, &mut value) }).map(|| value)
}
}
impl TryFrom<&PROPVARIANT> for i32 {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::PropVariantToInt32(&from.0, &mut value) }).map(|| value)
}
}
// VT_UI8
impl From<u64> for VARIANT {
fn from(value: u64) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_UI8,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { ullVal: value },
},
},
})
}
}
impl From<u64> for PROPVARIANT {
fn from(value: u64) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_UI8,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { uhVal: value },
},
},
})
}
}
impl TryFrom<&VARIANT> for u64 {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::VariantToUInt64(&from.0, &mut value) }).map(|| value)
}
}
impl TryFrom<&PROPVARIANT> for u64 {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::PropVariantToUInt64(&from.0, &mut value) }).map(|| value)
}
}
// VT_I8
impl From<i64> for VARIANT {
fn from(value: i64) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_I8,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { llVal: value },
},
},
})
}
}
impl From<i64> for PROPVARIANT {
fn from(value: i64) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_I8,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { hVal: value },
},
},
})
}
}
impl TryFrom<&VARIANT> for i64 {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::VariantToInt64(&from.0, &mut value) }).map(|| value)
}
}
impl TryFrom<&PROPVARIANT> for i64 {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = 0;
HRESULT(unsafe { imp::PropVariantToInt64(&from.0, &mut value) }).map(|| value)
}
}
// VT_R4
impl From<f32> for VARIANT {
fn from(value: f32) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_R4,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { fltVal: value },
},
},
})
}
}
impl From<f32> for PROPVARIANT {
fn from(value: f32) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_R4,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { fltVal: value },
},
},
})
}
}
// VT_R8
impl From<f64> for VARIANT {
fn from(value: f64) -> Self {
Self(imp::VARIANT {
Anonymous: imp::VARIANT_0 {
Anonymous: imp::VARIANT_0_0 {
vt: imp::VT_R8,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::VARIANT_0_0_0 { dblVal: value },
},
},
})
}
}
impl From<f64> for PROPVARIANT {
fn from(value: f64) -> Self {
Self(imp::PROPVARIANT {
Anonymous: imp::PROPVARIANT_0 {
Anonymous: imp::PROPVARIANT_0_0 {
vt: imp::VT_R8,
wReserved1: 0,
wReserved2: 0,
wReserved3: 0,
Anonymous: imp::PROPVARIANT_0_0_0 { dblVal: value },
},
},
})
}
}
impl TryFrom<&VARIANT> for f64 {
type Error = Error;
fn try_from(from: &VARIANT) -> Result<Self> {
let mut value = 0.0;
HRESULT(unsafe { imp::VariantToDouble(&from.0, &mut value) }).map(|| value)
}
}
impl TryFrom<&PROPVARIANT> for f64 {
type Error = Error;
fn try_from(from: &PROPVARIANT) -> Result<Self> {
let mut value = 0.0;
HRESULT(unsafe { imp::PropVariantToDouble(&from.0, &mut value) }).map(|| value)
}
}

25
vendor/windows-core-0.57.0/src/weak.rs vendored Normal file
View File

@@ -0,0 +1,25 @@
use super::*;
use core::marker::PhantomData;
/// `Weak` holds a non-owning reference to an object.
#[derive(Clone, PartialEq, Eq, Default)]
pub struct Weak<I: Interface>(Option<imp::IWeakReference>, PhantomData<I>);
impl<I: Interface> Weak<I> {
/// Creates a new `Weak` object without any backing object.
pub fn new() -> Self {
Self(None, PhantomData)
}
/// Attempts to upgrade the weak reference to a strong reference.
pub fn upgrade(&self) -> Option<I> {
self.0
.as_ref()
.and_then(|inner| unsafe { inner.Resolve().ok() })
}
pub(crate) fn downgrade(source: &imp::IWeakReferenceSource) -> Result<Self> {
let reference = unsafe { source.GetWeakReference().ok() };
Ok(Self(reference, PhantomData))
}
}

View File

@@ -0,0 +1,8 @@
use windows_bindgen::*;
#[test]
fn bindings() -> Result<()> {
bindgen(["--etc", "tests/bindings.txt"])?;
bindgen(["--etc", "tests/com_bindings.txt"])?;
Ok(())
}

View File

@@ -0,0 +1,65 @@
// These will use `windows-sys` style bindings.
--out src/imp/bindings.rs
--config flatten sys minimal no-bindgen-comment
--filter
Windows.Win32.Foundation.CloseHandle
Windows.Win32.Foundation.FreeLibrary
Windows.Win32.Foundation.SysAllocStringLen
Windows.Win32.Foundation.SysFreeString
Windows.Win32.Foundation.SysStringLen
Windows.Win32.System.Com.CoIncrementMTAUsage
Windows.Win32.System.Com.CoTaskMemAlloc
Windows.Win32.System.Com.CoTaskMemFree
Windows.Win32.System.Com.StructuredStorage.PROPVARIANT
Windows.Win32.System.Com.StructuredStorage.PropVariantClear
Windows.Win32.System.Com.StructuredStorage.PropVariantCompareEx
Windows.Win32.System.Com.StructuredStorage.PropVariantCopy
Windows.Win32.System.Com.StructuredStorage.PropVariantToBoolean
Windows.Win32.System.Com.StructuredStorage.PropVariantToBSTR
Windows.Win32.System.Com.StructuredStorage.PropVariantToDouble
Windows.Win32.System.Com.StructuredStorage.PropVariantToInt16
Windows.Win32.System.Com.StructuredStorage.PropVariantToInt32
Windows.Win32.System.Com.StructuredStorage.PropVariantToInt64
Windows.Win32.System.Com.StructuredStorage.PropVariantToUInt16
Windows.Win32.System.Com.StructuredStorage.PropVariantToUInt32
Windows.Win32.System.Com.StructuredStorage.PropVariantToUInt64
Windows.Win32.System.Com.StructuredStorage.PropVariantToVariant
Windows.Win32.System.Com.StructuredStorage.VariantToPropVariant
Windows.Win32.System.Diagnostics.Debug.EncodePointer
Windows.Win32.System.LibraryLoader.GetProcAddress
Windows.Win32.System.LibraryLoader.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
Windows.Win32.System.LibraryLoader.LoadLibraryExA
Windows.Win32.System.Memory.GetProcessHeap
Windows.Win32.System.Memory.HeapAlloc
Windows.Win32.System.Memory.HeapFree
Windows.Win32.System.Threading.CreateEventW
Windows.Win32.System.Threading.SetEvent
Windows.Win32.System.Threading.WaitForSingleObject
Windows.Win32.System.Variant.VARIANT
Windows.Win32.System.Variant.VariantClear
Windows.Win32.System.Variant.VariantCopy
Windows.Win32.System.Variant.VariantToBoolean
Windows.Win32.System.Variant.VariantToDouble
Windows.Win32.System.Variant.VariantToInt16
Windows.Win32.System.Variant.VariantToInt32
Windows.Win32.System.Variant.VariantToInt64
Windows.Win32.System.Variant.VariantToUInt16
Windows.Win32.System.Variant.VariantToUInt32
Windows.Win32.System.Variant.VariantToUInt64
Windows.Win32.System.Variant.VT_BOOL
Windows.Win32.System.Variant.VT_BSTR
Windows.Win32.System.Variant.VT_EMPTY
Windows.Win32.System.Variant.VT_I1
Windows.Win32.System.Variant.VT_I2
Windows.Win32.System.Variant.VT_I4
Windows.Win32.System.Variant.VT_I8
Windows.Win32.System.Variant.VT_R4
Windows.Win32.System.Variant.VT_R8
Windows.Win32.System.Variant.VT_UI1
Windows.Win32.System.Variant.VT_UI2
Windows.Win32.System.Variant.VT_UI4
Windows.Win32.System.Variant.VT_UI8
Windows.Win32.System.Variant.VT_UNKNOWN
Windows.Win32.System.WinRT.RoGetActivationFactory

View File

@@ -0,0 +1,23 @@
// These will use `windows` style bindings and include COM APIs.
--out src/imp/com_bindings.rs
--config flatten minimal no-bindgen-comment
--filter
Windows.Foundation.IReference
Windows.Foundation.IStringable
Windows.Foundation.PropertyValue
Windows.Win32.Foundation.CO_E_NOTINITIALIZED
Windows.Win32.Foundation.E_BOUNDS
Windows.Win32.Foundation.E_NOINTERFACE
Windows.Win32.Foundation.E_OUTOFMEMORY
Windows.Win32.Foundation.E_POINTER
Windows.Win32.Foundation.JSCRIPT_E_CANTEXECUTE
Windows.Win32.Foundation.RPC_E_DISCONNECTED
Windows.Win32.Foundation.TYPE_E_TYPEMISMATCH
Windows.Win32.System.Com.CoCreateGuid
Windows.Win32.System.Com.IAgileObject
Windows.Win32.System.WinRT.AGILEREFERENCE_DEFAULT
Windows.Win32.System.WinRT.IAgileReference
Windows.Win32.System.WinRT.IWeakReferenceSource
Windows.Win32.System.WinRT.RoGetAgileReference