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.lock":"353fb5452d5decff175fd41fa3284ecdc2de55a3b867b63e82341a2adab392cc","Cargo.toml":"2c521ca48502be5f6dcbc644bd268bae694cd175d5616c540a454840e97ad5ca","README.md":"0f426dba1cf9f879c1a47a26706c4ca86a7f20809bef92d1dd132a2f2e5e39d1","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"0f426dba1cf9f879c1a47a26706c4ca86a7f20809bef92d1dd132a2f2e5e39d1","src/agile_reference.rs":"3f88c6db85e1fefac15352e8b6bf63c8075b2d3c2f5f0a55e5ac2625239f7bb2","src/array.rs":"a991330fdb48bbceedbe33eb3d438e44f77bd257081e9e2409d304e7bf805a66","src/as_impl.rs":"2d4d1239869c3333141e5ebaa1fa102fd43ce48a7a9a32fe246859c0d5d4866c","src/com_object.rs":"64e1481969fcf61cdc22a935c7f1e71a8486832a13dfea7e09afbc6f06fdeb58","src/event.rs":"abf575d7af25bd6a892139a659a1ce270fb807ad94f6c2be2701f70b63d148bf","src/guid.rs":"9b276cecdccb40481ac4c39d69b0c9195913414659e46bab71b854b5491fa262","src/handles.rs":"c5f53785605cc14059c4ad0272e310b435ed2f48405e8e4052fb1d5e40ee4d78","src/imp/array_proxy.rs":"1081f11dec6250e946ce1c9a74fe848b6c43cf1c20bf74b42ee93e95edcb2ca6","src/imp/bindings.rs":"7e54bcd14f10e690320e91caecc5cd4cbbf0eab5278c72df2913c7ca5d7323ba","src/imp/can_into.rs":"d06228653f20c07dcfd8a4004cd6be7a19a8da0a79226d42653ab2f3bf290816","src/imp/com_bindings.rs":"3d3375e213d7f54f4b6e07bbac036e04eceee02376db443da8d64c284a0464f0","src/imp/factory_cache.rs":"a681c5024722e87873c9153758a4913b9e4aa4182a6d57fa878b7c14a38943f0","src/imp/generic_factory.rs":"340e2a75a5c4ec36bc7ea442c7211b3be4f8d3a537fda99316f9ce15bde02555","src/imp/marshaler.rs":"563e4965ee8db90106174caeb8ee800eb3a11f24ca6607a53606bb98fbafa8f9","src/imp/mod.rs":"21aca5aa46b4dbb827805cb22d9439e2ea07b43761ea87f35989bf566197d7c6","src/imp/ref_count.rs":"a9f4b5a3f2cc59580321cc65151510dafa699b7b308360f7023ea0f0c9f52a55","src/imp/sha1.rs":"0d06e4256c2dcd30259a97e3a16afe7d1a38a6fa87bda992faac7f98d8ae9c63","src/imp/weak_ref_count.rs":"769fca4c53f3146d2559530ab878a33ddc1fa0f584e3cdd02354efd32bdac247","src/imp/windows.rs":"7c05c90441107563fe6aee53b26bb6a78f6ff73f3e29f41a813c8559b97de36f","src/inspectable.rs":"0aaa0cf86d8ab0252d65610e38522e75ef5512202b8243d1610f2ef4ae979cab","src/interface.rs":"c8ca6c7ea20a27495412081c0827151758e601ba9887fa75e7a222a94c36297b","src/lib.rs":"1c147a297b8bbcbbdb38a6ae1abb000a1eeb9592303ff1eb475baf2f3218932e","src/out_param.rs":"cfd82569b669ed3f094d8076442c92a86bda1445e1b286a55cf5b95ff8eb80f7","src/out_ref.rs":"f19bf8900b08510f7b2d5c16e31d7712ea8a4183db8eed2de608c6e5e5b30321","src/param.rs":"7b660a0e50deb0890c849538a967e0cd5942ce122d9cf819cc0c69feb33a5ba6","src/param_value.rs":"b1d29ec7589cc7eebba1faf01aaae39f9d401dff13d2a6a5ec382f94b1becce0","src/ref.rs":"c176d20f78cedd498e1c273abe71cf7199ba811b7985e6f2074306811801ef27","src/runtime_name.rs":"b330db95b0ce32c963d6b43a0b152cd96e136e5b38b92c02223fb53b30f83ecf","src/runtime_type.rs":"4f504a1ee3525003d4376d259c5e195a08617bd5aff1789fd9027d51b354eb63","src/scoped_interface.rs":"1fb8526939d682f957ae7baee3ff1435880d6da358ce6662c68382678ecd6616","src/type.rs":"71f5028b70182b2486a3ab5b9db2626babf455285594b940210cf9d5fdb33998","src/unknown.rs":"4103ab719eafd93a2f4c756a6eb48af7e7722e034c37d649fbaf40929c8d0dbf","src/weak.rs":"e84056d21b205cd90997fbcb10b3fd11367beb4305baf039a1efdfd5a10d2005","src/windows.rs":"29d05450d084aba755c51af37f36176a73b4702756b5bee280f87c398d476460","windows-core.natvis":"4edd10bdfc6827212e412e57e24f184182035d871c8bb859c6eaccc2ad8d258e"},"package":"6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9"}

95
vendor/windows-core/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,95 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]]
name = "windows-core"
version = "0.62.1"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.59.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-link"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]]
name = "windows-result"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
dependencies = [
"windows-link",
]

70
vendor/windows-core/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.82"
name = "windows-core"
version = "0.62.1"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Core type support for COM and 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 = []
[features]
default = ["std"]
std = [
"windows-result/std",
"windows-strings/std",
]
[lib]
name = "windows_core"
path = "src/lib.rs"
[dependencies.windows-implement]
version = "0.60.1"
default-features = false
[dependencies.windows-interface]
version = "0.59.2"
default-features = false
[dependencies.windows-link]
version = "0.2.0"
default-features = false
[dependencies.windows-result]
version = "0.4.0"
default-features = false
[dependencies.windows-strings]
version = "0.5.0"
default-features = false
[lints.rust]
missing_unsafe_on_extern = "warn"
[lints.rust.unexpected_cfgs]
level = "warn"
priority = 0
check-cfg = ["cfg(windows_raw_dylib, windows_slim_errors)"]

7
vendor/windows-core/README.md vendored Normal file
View File

@@ -0,0 +1,7 @@
## Core type support for COM and Windows
The [windows-core](https://crates.io/crates/windows-core) crate provides core type support for the windows-* family of crates.
* [Getting started](https://kennykerr.ca/rust-getting-started/)
* [Samples](https://github.com/microsoft/windows-rs/tree/master/crates/samples)
* [Releases](https://github.com/microsoft/windows-rs/releases)

201
vendor/windows-core/license-apache-2.0 vendored Normal file
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/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

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

@@ -0,0 +1,7 @@
## Core type support for COM and Windows
The [windows-core](https://crates.io/crates/windows-core) crate provides core type support for the windows-* family of crates.
* [Getting started](https://kennykerr.ca/rust-getting-started/)
* [Samples](https://github.com/microsoft/windows-rs/tree/master/crates/samples)
* [Releases](https://github.com/microsoft/windows-rs/releases)

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)
}
}

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

@@ -0,0 +1,165 @@
use super::*;
/// A WinRT array stores elements contiguously in a heap-allocated buffer.
pub struct Array<T: Type<T>> {
pub(crate) data: *mut T::Default,
pub(crate) len: u32,
}
impl<T: Type<T>> Default for Array<T> {
fn default() -> Self {
Self {
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::ptr::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();
}
}
impl<T: Type<T>> core::fmt::Debug for Array<T>
where
T::Default: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::ops::Deref::deref(self).fmt(f)
}
}

20
vendor/windows-core/src/as_impl.rs vendored Normal file
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 {
unsafe { 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>;
}

394
vendor/windows-core/src/com_object.rs vendored Normal file
View File

@@ -0,0 +1,394 @@
use crate::imp::Box;
use crate::{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 [`InterfaceRef::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> {
#[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) -> Self {
Self::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: &Self) -> 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()
}
}
/// Enables applications to define COM objects using static storage. This is useful for factory
/// objects, stateless objects, or objects which use need to contain or use mutable global state.
///
/// COM objects that are defined using `StaticComObject` have their storage placed directly in
/// static storage; they are not stored in the heap.
///
/// COM objects defined using `StaticComObject` do have a reference count and this reference
/// count is adjusted when owned COM interface references (e.g. `IFoo` and `IUnknown`) are created
/// for the object. The reference count is initialized to 1.
///
/// # Example
///
/// ```rust,ignore
/// #[implement(IFoo)]
/// struct MyApp {
/// // ...
/// }
///
/// static MY_STATIC_APP: StaticComObject<MyApp> = MyApp { ... }.into_static();
///
/// fn get_my_static_ifoo() -> IFoo {
/// MY_STATIC_APP.to_interface()
/// }
/// ```
pub struct StaticComObject<T>
where
T: ComObjectInner,
{
outer: T::Outer,
}
// IMPORTANT: Do not expose any methods that return mutable access to the contents of StaticComObject.
// Doing so would violate our safety invariants. For example, we provide a Deref impl but it would
// be unsound to provide a DerefMut impl.
impl<T> StaticComObject<T>
where
T: ComObjectInner,
{
/// Wraps `outer` in a `StaticComObject`.
pub const fn from_outer(outer: T::Outer) -> Self {
Self { outer }
}
}
impl<T> StaticComObject<T>
where
T: ComObjectInner,
{
/// Gets access to the contained value.
pub const fn get(&'static self) -> &'static T::Outer {
&self.outer
}
}
impl<T> core::ops::Deref for StaticComObject<T>
where
T: ComObjectInner,
{
type Target = T::Outer;
fn deref(&self) -> &Self::Target {
&self.outer
}
}

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

@@ -0,0 +1,144 @@
use super::*;
use core::{iter::once, mem::transmute_copy};
use std::sync::{Arc, RwLock};
/// 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> {
delegates: RwLock<Option<Arc<[Delegate<T>]>>>,
}
unsafe impl<T: Interface> Send for Event<T> {}
unsafe impl<T: Interface> Sync for Event<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 const fn new() -> Self {
Self {
delegates: RwLock::new(None),
}
}
/// Registers a delegate with the event object.
pub fn add(&self, delegate: &T) -> Result<i64> {
let new_delegate = Delegate::new(delegate)?;
let token = new_delegate.to_token();
let new_iter = once(new_delegate);
let mut guard = self.delegates.write().unwrap();
let new_list = if let Some(old_delegates) = guard.as_ref() {
Arc::from_iter(old_delegates.iter().cloned().chain(new_iter))
} else {
Arc::from_iter(new_iter)
};
let old_list = guard.replace(new_list);
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
Ok(token)
}
/// Revokes a delegate's registration from the event object.
pub fn remove(&self, token: i64) {
let mut guard = self.delegates.write().unwrap();
let mut old_list = None;
if let Some(old_delegates) = guard.as_ref() {
// `self.delegates` is only modified if the token is found.
if let Some(i) = old_delegates
.iter()
.position(|old_delegate| old_delegate.to_token() == token)
{
let new_list = Arc::from_iter(
old_delegates[..i]
.iter()
.chain(old_delegates[i + 1..].iter())
.cloned(),
);
old_list = guard.replace(new_list);
}
}
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
}
/// Clears the event, removing all delegates.
pub fn clear(&self) {
let mut guard = self.delegates.write().unwrap();
let old_list = guard.take();
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
}
/// Invokes all of the event object's registered delegates with the provided callback.
pub fn call<F: FnMut(&T) -> Result<()>>(&self, mut callback: F) {
let delegates = {
let guard = self.delegates.read().unwrap();
if let Some(delegates) = guard.as_ref() {
delegates.clone()
} else {
// No delegates to call.
return;
}
// <-- lock is released here
};
for delegate in delegates.iter() {
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());
}
}
}
}
}
/// 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()?),
}
}
}

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

@@ -0,0 +1,206 @@
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> {
let mut guid = Self::zeroed();
let result = unsafe { imp::UuidCreate(&mut guid as *mut _ as _) };
if matches!(result, 0 | imp::RPC_S_UUID_LOCAL_ONLY) {
Ok(guid)
} else {
Err(Error::from_hresult(HRESULT::from_win32(result as u32)))
}
}
/// 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 TryFrom<&str> for GUID {
type Error = Error;
fn try_from(from: &str) -> Result<Self> {
if from.len() != 36 {
return Err(invalid_guid());
}
let bytes = &mut from.bytes();
let mut guid = Self::zeroed();
guid.data1 = try_u32(bytes, true)?;
guid.data2 = try_u16(bytes, true)?;
guid.data3 = try_u16(bytes, true)?;
guid.data4[0] = try_u8(bytes, false)?;
guid.data4[1] = try_u8(bytes, true)?;
guid.data4[2] = try_u8(bytes, false)?;
guid.data4[3] = try_u8(bytes, false)?;
guid.data4[4] = try_u8(bytes, false)?;
guid.data4[5] = try_u8(bytes, false)?;
guid.data4[6] = try_u8(bytes, false)?;
guid.data4[7] = try_u8(bytes, false)?;
Ok(guid)
}
}
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()
}
}
fn invalid_guid() -> Error {
Error::from_hresult(imp::E_INVALIDARG)
}
fn try_u32(bytes: &mut core::str::Bytes, delimiter: bool) -> Result<u32> {
next(bytes, 8, delimiter).ok_or_else(invalid_guid)
}
fn try_u16(bytes: &mut core::str::Bytes, delimiter: bool) -> Result<u16> {
next(bytes, 4, delimiter)
.map(|value| value as u16)
.ok_or_else(invalid_guid)
}
fn try_u8(bytes: &mut core::str::Bytes, delimiter: bool) -> Result<u8> {
next(bytes, 2, delimiter)
.map(|value| value as u8)
.ok_or_else(invalid_guid)
}
fn next(bytes: &mut core::str::Bytes, len: usize, delimiter: bool) -> Option<u32> {
let mut value: u32 = 0;
for _ in 0..len {
let digit = bytes.next()?;
match digit {
b'0'..=b'9' => value = (value << 4) + (digit - b'0') as u32,
b'A'..=b'F' => value = (value << 4) + (digit - b'A' + 10) as u32,
b'a'..=b'f' => value = (value << 4) + (digit - b'a' + 10) as u32,
_ => return None,
}
}
if delimiter && bytes.next() != Some(b'-') {
None
} else {
Some(value)
}
}

46
vendor/windows-core/src/handles.rs vendored Normal file
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,38 @@
use crate::{Array, Type};
pub struct ArrayProxy<T: Type<T>> {
data: *mut *mut T::Default,
len: *mut u32,
temp: core::mem::ManuallyDrop<Array<T>>,
}
pub unsafe fn array_proxy<T: Type<T>>(data: *mut *mut T::Default, len: *mut u32) -> ArrayProxy<T> {
ArrayProxy {
data,
len,
temp: core::mem::ManuallyDrop::new(Array::new()),
}
}
impl<T: Type<T>> Drop for ArrayProxy<T> {
fn drop(&mut self) {
unsafe {
*self.data = self.temp.data;
*self.len = self.temp.len;
}
}
}
impl<T: Type<T>> core::ops::Deref for ArrayProxy<T> {
type Target = Array<T>;
fn deref(&self) -> &Array<T> {
&self.temp
}
}
impl<T: Type<T>> core::ops::DerefMut for ArrayProxy<T> {
fn deref_mut(&mut self) -> &mut Array<T> {
&mut self.temp
}
}

40
vendor/windows-core/src/imp/bindings.rs vendored Normal file
View File

@@ -0,0 +1,40 @@
windows_link::link!("combase.dll" "system" fn CoIncrementMTAUsage(pcookie : *mut CO_MTA_USAGE_COOKIE) -> HRESULT);
windows_link::link!("combase.dll" "system" fn CoTaskMemAlloc(cb : usize) -> *mut core::ffi::c_void);
windows_link::link!("combase.dll" "system" fn CoTaskMemFree(pv : *const core::ffi::c_void));
windows_link::link!("kernel32.dll" "system" fn EncodePointer(ptr : *const core::ffi::c_void) -> *mut core::ffi::c_void);
windows_link::link!("kernel32.dll" "system" fn FreeLibrary(hlibmodule : HMODULE) -> BOOL);
windows_link::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : HMODULE, lpprocname : PCSTR) -> FARPROC);
windows_link::link!("kernel32.dll" "system" fn LoadLibraryExA(lplibfilename : PCSTR, hfile : HANDLE, dwflags : LOAD_LIBRARY_FLAGS) -> HMODULE);
windows_link::link!("api-ms-win-core-winrt-l1-1-0.dll" "system" fn RoGetActivationFactory(activatableclassid : HSTRING, iid : *const GUID, factory : *mut *mut core::ffi::c_void) -> HRESULT);
windows_link::link!("rpcrt4.dll" "system" fn UuidCreate(uuid : *mut GUID) -> RPC_STATUS);
pub type BOOL = i32;
pub type CO_MTA_USAGE_COOKIE = *mut core::ffi::c_void;
pub type FARPROC = Option<unsafe extern "system" fn() -> isize>;
#[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 = *mut core::ffi::c_void;
pub type HINSTANCE = *mut core::ffi::c_void;
pub type HMODULE = *mut core::ffi::c_void;
pub type HRESULT = i32;
pub type LOAD_LIBRARY_FLAGS = u32;
pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: LOAD_LIBRARY_FLAGS = 4096u32;
pub type PCSTR = *const u8;
pub type RPC_STATUS = i32;
pub const RPC_S_UUID_LOCAL_ONLY: RPC_STATUS = 1824i32;
pub type HSTRING = *mut core::ffi::c_void;

View File

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

View File

@@ -0,0 +1,246 @@
#[inline]
pub unsafe fn RoGetAgileReference<P2>(
options: AgileReferenceOptions,
riid: *const windows_core::GUID,
punk: P2,
) -> windows_core::Result<IAgileReference>
where
P2: windows_core::Param<windows_core::IUnknown>,
{
windows_core::link!("combase.dll" "system" fn RoGetAgileReference(options : AgileReferenceOptions, riid : *const windows_core::GUID, punk : * mut core::ffi::c_void, ppagilereference : *mut * mut core::ffi::c_void) -> windows_core::HRESULT);
unsafe {
let mut result__ = core::mem::zeroed();
RoGetAgileReference(options, riid, punk.param().abi(), &mut result__)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
pub const AGILEREFERENCE_DEFAULT: AgileReferenceOptions = AgileReferenceOptions(0i32);
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct AgileReferenceOptions(pub i32);
pub const CO_E_NOTINITIALIZED: windows_core::HRESULT = windows_core::HRESULT(0x800401F0_u32 as _);
pub const E_INVALIDARG: windows_core::HRESULT = windows_core::HRESULT(0x80070057_u32 as _);
pub const E_NOINTERFACE: windows_core::HRESULT = windows_core::HRESULT(0x80004002_u32 as _);
pub const E_POINTER: windows_core::HRESULT = windows_core::HRESULT(0x80004003_u32 as _);
windows_core::imp::define_interface!(
IAgileObject,
IAgileObject_Vtbl,
0x94ea2b94_e9cc_49e0_c0ff_ee64ca8f5b90
);
windows_core::imp::interface_hierarchy!(IAgileObject, windows_core::IUnknown);
#[repr(C)]
#[doc(hidden)]
pub struct IAgileObject_Vtbl {
pub base__: windows_core::IUnknown_Vtbl,
}
pub trait IAgileObject_Impl: windows_core::IUnknownImpl {}
impl IAgileObject_Vtbl {
pub const fn new<Identity: IAgileObject_Impl, const OFFSET: isize>() -> Self {
Self {
base__: windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(),
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<IAgileObject as windows_core::Interface>::IID
}
}
impl windows_core::RuntimeName for IAgileObject {}
windows_core::imp::define_interface!(
IAgileReference,
IAgileReference_Vtbl,
0xc03f6a43_65a4_9818_987e_e0b810d2a6f2
);
windows_core::imp::interface_hierarchy!(IAgileReference, windows_core::IUnknown);
impl IAgileReference {
pub unsafe fn Resolve<T>(&self) -> windows_core::Result<T>
where
T: windows_core::Interface,
{
let mut result__ = core::ptr::null_mut();
unsafe {
(windows_core::Interface::vtable(self).Resolve)(
windows_core::Interface::as_raw(self),
&T::IID,
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
}
#[repr(C)]
#[doc(hidden)]
pub struct IAgileReference_Vtbl {
pub base__: windows_core::IUnknown_Vtbl,
pub Resolve: unsafe extern "system" fn(
*mut core::ffi::c_void,
*const windows_core::GUID,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
pub trait IAgileReference_Impl: windows_core::IUnknownImpl {
fn Resolve(
&self,
riid: *const windows_core::GUID,
ppvobjectreference: *mut *mut core::ffi::c_void,
) -> windows_core::Result<()>;
}
impl IAgileReference_Vtbl {
pub const fn new<Identity: IAgileReference_Impl, const OFFSET: isize>() -> Self {
unsafe extern "system" fn Resolve<Identity: IAgileReference_Impl, const OFFSET: isize>(
this: *mut core::ffi::c_void,
riid: *const windows_core::GUID,
ppvobjectreference: *mut *mut core::ffi::c_void,
) -> windows_core::HRESULT {
unsafe {
let this: &Identity =
&*((this as *const *const ()).offset(OFFSET) as *const Identity);
IAgileReference_Impl::Resolve(
this,
core::mem::transmute_copy(&riid),
core::mem::transmute_copy(&ppvobjectreference),
)
.into()
}
}
Self {
base__: windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(),
Resolve: Resolve::<Identity, OFFSET>,
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<IAgileReference as windows_core::Interface>::IID
}
}
impl windows_core::RuntimeName for IAgileReference {}
windows_core::imp::define_interface!(
IWeakReference,
IWeakReference_Vtbl,
0x00000037_0000_0000_c000_000000000046
);
windows_core::imp::interface_hierarchy!(IWeakReference, windows_core::IUnknown);
impl IWeakReference {
pub unsafe fn Resolve<T>(&self) -> windows_core::Result<T>
where
T: windows_core::Interface,
{
let mut result__ = core::ptr::null_mut();
unsafe {
(windows_core::Interface::vtable(self).Resolve)(
windows_core::Interface::as_raw(self),
&T::IID,
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
}
#[repr(C)]
#[doc(hidden)]
pub struct IWeakReference_Vtbl {
pub base__: windows_core::IUnknown_Vtbl,
pub Resolve: unsafe extern "system" fn(
*mut core::ffi::c_void,
*const windows_core::GUID,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
pub trait IWeakReference_Impl: windows_core::IUnknownImpl {
fn Resolve(
&self,
riid: *const windows_core::GUID,
objectreference: *mut *mut core::ffi::c_void,
) -> windows_core::Result<()>;
}
impl IWeakReference_Vtbl {
pub const fn new<Identity: IWeakReference_Impl, const OFFSET: isize>() -> Self {
unsafe extern "system" fn Resolve<Identity: IWeakReference_Impl, const OFFSET: isize>(
this: *mut core::ffi::c_void,
riid: *const windows_core::GUID,
objectreference: *mut *mut core::ffi::c_void,
) -> windows_core::HRESULT {
unsafe {
let this: &Identity =
&*((this as *const *const ()).offset(OFFSET) as *const Identity);
IWeakReference_Impl::Resolve(
this,
core::mem::transmute_copy(&riid),
core::mem::transmute_copy(&objectreference),
)
.into()
}
}
Self {
base__: windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(),
Resolve: Resolve::<Identity, OFFSET>,
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<IWeakReference as windows_core::Interface>::IID
}
}
impl windows_core::RuntimeName for IWeakReference {}
windows_core::imp::define_interface!(
IWeakReferenceSource,
IWeakReferenceSource_Vtbl,
0x00000038_0000_0000_c000_000000000046
);
windows_core::imp::interface_hierarchy!(IWeakReferenceSource, windows_core::IUnknown);
impl IWeakReferenceSource {
pub unsafe fn GetWeakReference(&self) -> windows_core::Result<IWeakReference> {
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(self).GetWeakReference)(
windows_core::Interface::as_raw(self),
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
}
#[repr(C)]
#[doc(hidden)]
pub struct IWeakReferenceSource_Vtbl {
pub base__: windows_core::IUnknown_Vtbl,
pub GetWeakReference: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
pub trait IWeakReferenceSource_Impl: windows_core::IUnknownImpl {
fn GetWeakReference(&self) -> windows_core::Result<IWeakReference>;
}
impl IWeakReferenceSource_Vtbl {
pub const fn new<Identity: IWeakReferenceSource_Impl, const OFFSET: isize>() -> Self {
unsafe extern "system" fn GetWeakReference<
Identity: IWeakReferenceSource_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
weakreference: *mut *mut core::ffi::c_void,
) -> windows_core::HRESULT {
unsafe {
let this: &Identity =
&*((this as *const *const ()).offset(OFFSET) as *const Identity);
match IWeakReferenceSource_Impl::GetWeakReference(this) {
Ok(ok__) => {
weakreference.write(core::mem::transmute(ok__));
windows_core::HRESULT(0)
}
Err(err) => err.into(),
}
}
}
Self {
base__: windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(),
GetWeakReference: GetWeakReference::<Identity, OFFSET>,
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<IWeakReferenceSource as windows_core::Interface>::IID
}
}
impl windows_core::RuntimeName for IWeakReferenceSource {}
pub const JSCRIPT_E_CANTEXECUTE: windows_core::HRESULT = windows_core::HRESULT(0x89020001_u32 as _);
pub const REGDB_E_CLASSNOTREG: windows_core::HRESULT = windows_core::HRESULT(0x80040154_u32 as _);
pub const RPC_E_DISCONNECTED: windows_core::HRESULT = windows_core::HRESULT(0x80010108_u32 as _);
pub const S_OK: windows_core::HRESULT = windows_core::HRESULT(0x0_u32 as _);

View File

@@ -0,0 +1,214 @@
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};
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 = load_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 load_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 = core::ptr::null_mut();
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);
}
// Reg-free activation should only be attempted if the class is not registered.
// It should not be attempted if the class is registered but fails to activate.
if code == REGDB_E_CLASSNOTREG {
// Now attempt to find the factory's implementation heuristically.
if let Some(i) = search_path(C::NAME, |library| unsafe {
get_activation_factory(library, &name)
}) {
return i.cast();
}
}
Err(crate::Error::from_hresult(code))
}
// 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 = alloc::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> {
unsafe {
let function =
delay_load::<DllGetActivationFactory>(library, crate::s!("DllGetActivationFactory"))
.ok_or_else(crate::Error::from_thread)?;
let mut abi = null_mut();
function(transmute_copy(name), &mut abi).and_then(|| crate::Type::from_abi(abi))
}
}
unsafe fn delay_load<T>(library: crate::PCSTR, function: crate::PCSTR) -> Option<T> {
unsafe {
let library = LoadLibraryExA(
library.0,
core::ptr::null_mut(),
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
);
if library.is_null() {
return None;
}
let address = GetProcAddress(library, function.0);
if address.is_some() {
return Some(core::mem::transmute_copy(&address));
}
FreeLibrary(library);
None
}
}
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,
}

268
vendor/windows-core/src/imp/marshaler.rs vendored Normal file
View File

@@ -0,0 +1,268 @@
use super::*;
use crate::{IUnknown, IUnknown_Vtbl, Interface, GUID, HRESULT};
use core::ffi::c_void;
use core::mem::{transmute, transmute_copy};
use core::ptr::null_mut;
windows_link::link!("combase.dll" "system" fn CoCreateFreeThreadedMarshaler(punkouter: *mut c_void, ppunkmarshal: *mut *mut c_void) -> HRESULT);
pub unsafe fn marshaler(outer: IUnknown, result: *mut *mut c_void) -> HRESULT {
unsafe {
let mut marshaler_raw = null_mut();
_ = CoCreateFreeThreadedMarshaler(null_mut(), &mut marshaler_raw);
assert!(!marshaler_raw.is_null(), "allocation failed");
let marshaler: IUnknown = transmute(marshaler_raw);
_ = (marshaler.vtable().QueryInterface)(
transmute_copy(&marshaler),
&IMarshal::IID,
&mut marshaler_raw,
);
debug_assert!(!marshaler_raw.is_null());
let marshaler: IMarshal = transmute(marshaler_raw);
let marshaler = Marshaler {
vtable: &Marshaler::VTABLE,
outer,
marshaler,
count: RefCount::new(1),
};
debug_assert!(!result.is_null());
*result = transmute::<Box<_>, *mut c_void>(Box::new(marshaler));
S_OK
}
}
#[repr(C)]
struct Marshaler {
vtable: *const IMarshal_Vtbl,
outer: IUnknown,
marshaler: IMarshal,
count: RefCount,
}
impl Marshaler {
const VTABLE: IMarshal_Vtbl = IMarshal_Vtbl {
base__: IUnknown_Vtbl {
QueryInterface: Self::QueryInterface,
AddRef: Self::AddRef,
Release: Self::Release,
},
GetUnmarshalClass: Self::GetUnmarshalClass,
GetMarshalSizeMax: Self::GetMarshalSizeMax,
MarshalInterface: Self::MarshalInterface,
UnmarshalInterface: Self::UnmarshalInterface,
ReleaseMarshalData: Self::ReleaseMarshalData,
DisconnectObject: Self::DisconnectObject,
};
unsafe extern "system" fn QueryInterface(
this: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
if iid.is_null() || interface.is_null() {
return E_POINTER;
}
if *iid == IMarshal::IID {
*interface = &mut (*this).vtable as *mut _ as _;
(*this).count.add_ref();
return S_OK;
}
((*this).outer.vtable().QueryInterface)(transmute_copy(&(*this).outer), iid, interface)
}
}
unsafe extern "system" fn AddRef(this: *mut c_void) -> u32 {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
(*this).count.add_ref()
}
}
unsafe extern "system" fn Release(this: *mut c_void) -> u32 {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
let remaining = (*this).count.release();
if remaining == 0 {
let _ = Box::from_raw(this);
}
remaining
}
}
unsafe extern "system" fn GetUnmarshalClass(
this: *mut c_void,
riid: *const GUID,
pv: *const c_void,
dwdestcontext: u32,
pvdestcontext: *const c_void,
mshlflags: u32,
pcid: *mut GUID,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().GetUnmarshalClass)(
transmute_copy(&(*this).marshaler),
riid,
pv,
dwdestcontext,
pvdestcontext,
mshlflags,
pcid,
)
}
}
unsafe extern "system" fn GetMarshalSizeMax(
this: *mut c_void,
riid: *const GUID,
pv: *const c_void,
dwdestcontext: u32,
pvdestcontext: *const c_void,
mshlflags: u32,
psize: *mut u32,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().GetMarshalSizeMax)(
transmute_copy(&(*this).marshaler),
riid,
pv,
dwdestcontext,
pvdestcontext,
mshlflags,
psize,
)
}
}
unsafe extern "system" fn MarshalInterface(
this: *mut c_void,
pstm: *mut c_void,
riid: *const GUID,
pv: *const c_void,
dwdestcontext: u32,
pvdestcontext: *const c_void,
mshlflags: u32,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().MarshalInterface)(
transmute_copy(&(*this).marshaler),
pstm,
riid,
pv,
dwdestcontext,
pvdestcontext,
mshlflags,
)
}
}
unsafe extern "system" fn UnmarshalInterface(
this: *mut c_void,
pstm: *mut c_void,
riid: *const GUID,
ppv: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().UnmarshalInterface)(
transmute_copy(&(*this).marshaler),
pstm,
riid,
ppv,
)
}
}
unsafe extern "system" fn ReleaseMarshalData(this: *mut c_void, pstm: *mut c_void) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().ReleaseMarshalData)(
transmute_copy(&(*this).marshaler),
pstm,
)
}
}
unsafe extern "system" fn DisconnectObject(this: *mut c_void, dwreserved: u32) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().DisconnectObject)(
transmute_copy(&(*this).marshaler),
dwreserved,
)
}
}
}
#[repr(transparent)]
#[derive(Clone)]
pub struct IMarshal(IUnknown);
unsafe impl Interface for IMarshal {
type Vtable = IMarshal_Vtbl;
const IID: GUID = GUID::from_u128(0x00000003_0000_0000_c000_000000000046);
}
#[repr(C)]
pub struct IMarshal_Vtbl {
base__: IUnknown_Vtbl,
GetUnmarshalClass: unsafe extern "system" fn(
*mut c_void,
*const GUID,
*const c_void,
u32,
*const c_void,
u32,
*mut GUID,
) -> HRESULT,
GetMarshalSizeMax: unsafe extern "system" fn(
*mut c_void,
*const GUID,
*const c_void,
u32,
*const c_void,
u32,
*mut u32,
) -> HRESULT,
MarshalInterface: unsafe extern "system" fn(
*mut c_void,
*mut c_void,
*const GUID,
*const c_void,
u32,
*const c_void,
u32,
) -> HRESULT,
UnmarshalInterface: unsafe extern "system" fn(
*mut c_void,
*mut c_void,
*const GUID,
*mut *mut c_void,
) -> HRESULT,
ReleaseMarshalData: unsafe extern "system" fn(*mut c_void, *mut c_void) -> HRESULT,
DisconnectObject: unsafe extern "system" fn(*mut c_void, u32) -> HRESULT,
}

98
vendor/windows-core/src/imp/mod.rs vendored Normal file
View File

@@ -0,0 +1,98 @@
#[cfg(windows)]
include!("windows.rs");
mod bindings;
mod can_into;
mod com_bindings;
mod ref_count;
mod sha1;
mod weak_ref_count;
pub(crate) use bindings::*;
pub use can_into::*;
pub use com_bindings::*;
pub use ref_count::*;
pub use sha1::*;
pub use weak_ref_count::*;
#[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(::core::ptr::NonNull<::core::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,33 @@
use core::sync::atomic::{fence, AtomicI32, Ordering};
#[repr(transparent)]
#[derive(Default)]
pub struct RefCount(pub(crate) AtomicI32);
impl RefCount {
/// Creates a new `RefCount` with an initial value of `1`.
pub const 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
}
}

487
vendor/windows-core/src/imp/sha1.rs vendored Normal file
View File

@@ -0,0 +1,487 @@
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 Default for ConstBuffer {
fn default() -> Self {
Self::new()
}
}
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, "{i:08x}")?;
}
Ok(())
}
}

View File

@@ -0,0 +1,327 @@
use super::*;
use crate::{IUnknown, IUnknown_Vtbl, Interface, GUID, HRESULT};
use core::ffi::c_void;
use core::mem::{transmute, transmute_copy};
use core::ptr::null_mut;
use core::sync::atomic::{AtomicIsize, Ordering};
#[repr(transparent)]
#[derive(Default)]
pub struct WeakRefCount(AtomicIsize);
impl WeakRefCount {
pub const 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: &GUID, object: *mut c_void) -> *mut c_void {
unsafe {
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 {
#[expect(clippy::new_ret_no_self)]
unsafe fn new(object: *mut c_void, strong_count: u32) -> IWeakReferenceSource {
unsafe {
transmute(Box::new(Self {
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 {
unsafe {
let tear_off = Self::decode(encoding);
tear_off.strong_count.add_ref();
tear_off as *mut _ as *mut _
}
}
const STRONG_VTABLE: IWeakReferenceSource_Vtbl = IWeakReferenceSource_Vtbl {
base__: IUnknown_Vtbl {
QueryInterface: Self::StrongQueryInterface,
AddRef: Self::StrongAddRef,
Release: Self::StrongRelease,
},
GetWeakReference: Self::StrongDowngrade,
};
const WEAK_VTABLE: IWeakReference_Vtbl = IWeakReference_Vtbl {
base__: 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 {
unsafe { &mut *(this as *mut *mut c_void as *mut Self) }
}
unsafe fn from_weak_ptr<'a>(this: *mut c_void) -> &'a mut Self {
unsafe { &mut *((this as *mut *mut c_void).sub(1) as *mut Self) }
}
unsafe fn decode<'a>(value: isize) -> &'a mut Self {
unsafe { &mut *((value << 1) as *mut Self) as &mut Self }
}
unsafe fn query_interface(&self, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT {
unsafe {
((*(*(self.object as *mut *mut IUnknown_Vtbl))).QueryInterface)(
self.object,
iid,
interface,
)
}
}
unsafe extern "system" fn StrongQueryInterface(
ptr: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
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 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 GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
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 == IUnknown::IID
|| *iid == IAgileObject::IID
{
ptr
} else {
#[cfg(windows)]
if *iid == IMarshal::IID {
this.weak_count.add_ref();
return marshaler(transmute::<*mut c_void, IUnknown>(ptr), interface);
}
null_mut()
};
if (*interface).is_null() {
E_NOINTERFACE
} else {
this.weak_count.add_ref();
HRESULT(0)
}
}
}
unsafe extern "system" fn StrongAddRef(ptr: *mut c_void) -> u32 {
unsafe {
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 {
unsafe {
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 {
unsafe {
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 IUnknown_Vtbl))).Release)(this.object)
}
}
unsafe extern "system" fn WeakRelease(ptr: *mut c_void) -> u32 {
unsafe {
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,
) -> HRESULT {
unsafe {
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();
HRESULT(0)
}
}
unsafe extern "system" fn WeakUpgrade(
ptr: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
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();
HRESULT(0)
})
}
}
}

11
vendor/windows-core/src/imp/windows.rs vendored Normal file
View File

@@ -0,0 +1,11 @@
mod factory_cache;
pub use factory_cache::*;
mod generic_factory;
pub use generic_factory::*;
mod marshaler;
pub use marshaler::*;
mod array_proxy;
pub use array_proxy::*;

123
vendor/windows-core/src/inspectable.rs vendored Normal file
View File

@@ -0,0 +1,123 @@
use super::*;
use core::ffi::c_void;
use core::ptr::null_mut;
/// Parent interface for all WinRT interfaces.
///
/// 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, Debug)]
pub struct IInspectable(pub IUnknown);
interface_hierarchy!(IInspectable, IUnknown);
impl IInspectable {
/// Returns the canonical type name for the underlying object.
#[cfg(windows)]
pub fn GetRuntimeClassName(&self) -> Result<HSTRING> {
unsafe {
let mut abi = null_mut();
(self.vtable().GetRuntimeClassName)(core::mem::transmute_copy(self), &mut abi).ok()?;
Ok(core::mem::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)(core::mem::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 {
unsafe {
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 {
unsafe {
if value.is_null() {
return imp::E_POINTER;
}
#[cfg(windows)]
{
*value = core::mem::transmute::<HSTRING, *mut c_void>(T::NAME.into());
}
#[cfg(not(windows))]
{
*value = core::ptr::null_mut();
}
HRESULT(0)
}
}
unsafe extern "system" fn GetTrustLevel<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
value: *mut i32,
) -> HRESULT {
unsafe {
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>,
}
}
}

339
vendor/windows-core/src/interface.rs vendored Normal file
View File

@@ -0,0 +1,339 @@
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 {
unsafe { &**(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 {
unsafe { 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> {
unsafe {
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>()
.map(|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 {
unsafe {
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)
}
}
/// 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<I> Copy for InterfaceRef<'_, I> {}
impl<I> Clone for InterfaceRef<'_, I> {
fn clone(&self) -> Self {
*self
}
}
impl<I: core::fmt::Debug + Interface> core::fmt::Debug for InterfaceRef<'_, I> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
<I as core::fmt::Debug>::fmt(&**self, f)
}
}
impl<I: Interface> InterfaceRef<'_, 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) -> Self {
InterfaceRef::from_interface(interface)
}
}
impl<I: Interface> core::ops::Deref for InterfaceRef<'_, 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);

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

@@ -0,0 +1,61 @@
#![doc = include_str!("../readme.md")]
#![doc(html_no_source)]
#![debugger_visualizer(natvis_file = "../windows-core.natvis")]
#![cfg_attr(all(not(feature = "std")), no_std)]
#![expect(
non_snake_case,
non_camel_case_types,
dead_code,
clippy::missing_transmute_annotations,
clippy::upper_case_acronyms
)]
#[cfg(windows)]
include!("windows.rs");
extern crate self as windows_core;
extern crate alloc;
use alloc::boxed::Box;
#[doc(hidden)]
pub mod imp;
mod as_impl;
mod com_object;
mod guid;
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 r#type;
mod unknown;
mod weak;
pub use as_impl::*;
pub use com_object::*;
pub use guid::*;
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 unknown::*;
pub use weak::*;
pub use windows_implement::implement;
pub use windows_interface::interface;
pub use windows_link::link;
pub use windows_result::*;

63
vendor/windows-core/src/out_param.rs vendored Normal file
View File

@@ -0,0 +1,63 @@
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> {
unsafe {
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> {
unsafe { 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> {
unsafe {
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> {
unsafe {
match self {
Some(this) => transmute_copy(this),
None => zeroed(),
}
}
}
}

37
vendor/windows-core/src/out_ref.rs vendored Normal file
View File

@@ -0,0 +1,37 @@
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<T: Type<T>> OutRef<'_, 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(())
}
}
}
impl<'a, T: Type<T>> From<&'a mut T::Default> for OutRef<'a, T> {
fn from(from: &'a mut T::Default) -> Self {
unsafe { core::mem::transmute(from) }
}
}
impl<T: Type<T>> Default for OutRef<'_, T> {
fn default() -> Self {
unsafe { core::mem::zeroed() }
}
}

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

@@ -0,0 +1,76 @@
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> {
unsafe {
ParamValue::Borrowed(match self {
Some(item) => transmute_copy(item),
None => zeroed(),
})
}
}
}
impl<T> Param<T> for InterfaceRef<'_, T>
where
T: Type<T>,
{
unsafe fn param(self) -> ParamValue<T> {
unsafe { ParamValue::Borrowed(transmute_copy(&self)) }
}
}
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> {
unsafe {
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> {
unsafe { 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> {
unsafe { ParamValue::Owned(transmute_copy(&self)) }
}
}

24
vendor/windows-core/src/param_value.rs vendored Normal file
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()) }
}
}

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

@@ -0,0 +1,88 @@
use super::*;
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, core::marker::PhantomData<&'a T>);
impl<T: Type<T>> Ref<'_, T> {
/// Returns `true` if the argument is null.
pub fn is_null(&self) -> bool {
T::is_null(&self.0)
}
/// Converts the argument to a [`Result<&T>`] reference.
pub fn ok(&self) -> Result<&T> {
self.as_ref()
.ok_or_else(|| Error::from_hresult(imp::E_POINTER))
}
/// Converts the argument to a [`Option<&T>`] reference.
pub fn as_ref(&self) -> Option<&T> {
if self.is_null() {
None
} else {
unsafe { Some(self.assume_init_ref()) }
}
}
/// Converts the argument to a `&T` reference.
///
/// # Panics
///
/// Panics if the argument is null.
#[track_caller]
pub fn unwrap(&self) -> &T {
self.as_ref().expect("called `Ref::unwrap` on a null value")
}
/// Converts the argument to an [`Option<T>`] by cloning the reference.
pub fn cloned(&self) -> Option<T> {
self.as_ref().cloned()
}
unsafe fn assume_init_ref(&self) -> &T {
unsafe { T::assume_init_ref(&self.0) }
}
}
impl<T: Type<T>> Default for Ref<'_, T> {
fn default() -> Self {
unsafe { core::mem::zeroed() }
}
}
impl<T: Type<T>> core::ops::Deref for Ref<'_, T> {
type Target = T::Default;
fn deref(&self) -> &Self::Target {
unsafe { transmute(&self.0) }
}
}
impl<'a, T: Type<T, InterfaceType>> From<&'a Option<T>> for Ref<'a, T>
where
T: TypeKind<TypeKind = InterfaceType>,
{
fn from(from: &'a Option<T>) -> Self {
unsafe { core::mem::transmute_copy(from) }
}
}
impl<'a, T: Type<T, InterfaceType>> From<Option<&'a T>> for Ref<'a, T>
where
T: TypeKind<TypeKind = InterfaceType>,
{
fn from(from: Option<&'a T>) -> Self {
if let Some(from) = from {
unsafe { core::mem::transmute_copy(from) }
} else {
unsafe { core::mem::zeroed() }
}
}
}
impl<'a, T: Type<T>> From<&'a T> for Ref<'a, T> {
fn from(from: &'a T) -> Self {
unsafe { core::mem::transmute_copy(from) }
}
}

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 = "";
}

30
vendor/windows-core/src/runtime_type.rs vendored Normal file
View File

@@ -0,0 +1,30 @@
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")
}

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<T: Interface> ScopedInterface<'_, T> {
pub fn new(interface: T) -> Self {
Self {
interface,
lifetime: PhantomData,
}
}
}
impl<T: Interface> core::ops::Deref for ScopedInterface<'_, T> {
type Target = T;
fn deref(&self) -> &T {
&self.interface
}
}
impl<T: Interface> Drop for ScopedInterface<'_, T> {
fn drop(&mut self) {
unsafe {
let _ = Box::from_raw(self.interface.as_raw() as *const _ as *mut ScopedHeap);
}
}
}

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

@@ -0,0 +1,127 @@
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;
fn is_null(abi: &Self::Abi) -> bool;
unsafe fn assume_init_ref(abi: &Self::Abi) -> &Self;
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>;
fn is_null(abi: &Self::Abi) -> bool {
abi.is_null()
}
unsafe fn assume_init_ref(abi: &Self::Abi) -> &Self {
unsafe { core::mem::transmute::<&*mut core::ffi::c_void, &T>(abi) }
}
unsafe fn from_abi(abi: Self::Abi) -> Result<Self> {
unsafe {
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;
fn is_null(_: &Self::Abi) -> bool {
false
}
unsafe fn assume_init_ref(abi: &Self::Abi) -> &Self {
unsafe { abi.assume_init_ref() }
}
unsafe fn from_abi(abi: Self::Abi) -> Result<Self> {
unsafe { 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;
fn is_null(_: &Self::Abi) -> bool {
false
}
unsafe fn assume_init_ref(abi: &Self::Abi) -> &Self {
abi
}
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;

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

@@ -0,0 +1,186 @@
use super::*;
use core::ffi::c_void;
use core::ptr::NonNull;
/// Base interface for all COM interfaces.
///
/// 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)]
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`.
core::ptr::eq(self.as_raw(), other.as_raw())
|| self.cast::<Self>().unwrap().0 == other.cast::<Self>().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;
/// 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>;
}
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 {
unsafe {
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 {
unsafe {
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 {
unsafe {
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>,
}
}
}

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

@@ -0,0 +1,28 @@
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 const 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) -> Self {
let reference = unsafe { source.GetWeakReference().ok() };
Self(reference, PhantomData)
}
}
unsafe impl<I: Interface> Send for Weak<I> {}
unsafe impl<I: Interface> Sync for Weak<I> {}

73
vendor/windows-core/src/windows.rs vendored Normal file
View File

@@ -0,0 +1,73 @@
mod agile_reference;
pub use agile_reference::*;
mod array;
pub use array::*;
#[cfg(feature = "std")]
mod event;
#[cfg(feature = "std")]
pub use event::*;
mod handles;
pub use handles::*;
pub use windows_strings::*;
/// 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::load_factory::<C, I>()
}
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))
}
}
impl RuntimeType for HSTRING {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice(b"string");
}
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;
}

18
vendor/windows-core/windows-core.natvis vendored Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="windows_core::array::Array&lt;*&gt;">
<DisplayString>{{ len={len} }}</DisplayString>
<Expand>
<Item Name="[len]">len</Item>
<ArrayItems>
<Size>len</Size>
<ValuePointer>data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="windows_core::imp::ref_count::RefCount">
<DisplayString>{__0}</DisplayString>
</Type>
</AutoVisualizer>