Vendor dependencies for 0.3.0 release

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

View File

@@ -0,0 +1 @@
{"files":{"Cargo.toml":"7c5e1458d2fa129080022a13acd45527a25e39beb2e422585ebe48a39ce2ab34","license-apache-2.0":"c16f8dcf1a368b83be78d826ea23de4079fe1b4469a0ab9ee20563f37ff3d44b","license-mit":"c2cfccb812fe482101a8f04597dfc5a9991a6b2748266c47ac91b6a5aae15383","readme.md":"75fb78f065320771362c3a74a2e285ac336b657887b0c7f41cafe57d9b1f7e1a","src/agile_reference.rs":"2de43273e6e7dcf63e1460581012ebacea9d2a7a2f566ccda7019f4191b79a7d","src/array.rs":"c9975db941876ce329ed851b5e6ad989a660f9da0f91e8dece7333fda2274e01","src/as_impl.rs":"018954b44fe4c16d62a959f5578c5a26b968d0f9a3f156f1bac10492b934d949","src/event.rs":"fbd5ef786eebde877160af0dd56edea4c357114061d19fc90e161c34d54f03a6","src/guid.rs":"e0f407b6e06f35530fc15f9592dc547361094932ccc3bc15622763322dc34458","src/imp/bindings.rs":"dd414b50ab080ce8aef8c48bd23b40bceee2aaaf3bfaa0adde6275b5bf5fabf1","src/imp/com_bindings.rs":"f5b1a3690e092783f71b39178cbd178f12291c772ccbc24eedbe95ad8bc45a90","src/imp/delay_load.rs":"26492b2ef34f4a3ac35f41050a9088ee15603caf0a59c6e74fdf423bfcb96829","src/imp/factory_cache.rs":"5e3540d7e2fcf872d0dadbec66a09f81a4f38a6567a796e571921c177996ee56","src/imp/generic_factory.rs":"89f50e4e686d93a212e1f7d260bc6491867c84c732d3ad3fdedd9562aa73346c","src/imp/heap.rs":"646e31462f37f96a9d6928997c2bbacc333eabb3989e9999e89ff95e9565e4ba","src/imp/mod.rs":"3f8f1ff647463896096c79cdcfe05492f45753bd25387e0e755fa2fd804cab44","src/imp/ref_count.rs":"ded51b50923eb1d542432d216b56604b6cef564f664740a3ad8290ad8d88b8e6","src/imp/sha1.rs":"f2272c9ea729d1a752fb52ea1ccee6cbcb2bb5deb3436052381f9dba9a1a0cc4","src/imp/waiter.rs":"575cfdbe9befc22b1e8fa91e15f303d830b23673d07a5361992229e0440081b2","src/imp/weak_ref_count.rs":"1b3c631a9d33160478e4a33a6b0611ad7157a9c497b25aaf730733aadad1d6ac","src/inspectable.rs":"293ab8b19a7f88547bb837222d4d439c93dd029d248634c3750293661ddd3f3f","src/interface.rs":"230500f0d5bcbb0ed216f5ed16815a08d0bc03bb0435aaa55c76aac63d4ddb2e","src/lib.rs":"a0dd2ca9195e2aa2e04df2f7823cfa09b6c5b34d4af313961e7b86b03924cbad","src/param.rs":"605d8bd965d1d57e299442544482703f8e1e3d207e655d6a9155b1b89bc980fe","src/runtime_name.rs":"b330db95b0ce32c963d6b43a0b152cd96e136e5b38b92c02223fb53b30f83ecf","src/runtime_type.rs":"12af114889b61b12ceabd8192caa0fcdf9df18a8cfbb294728a5737bbf8ea6c1","src/scoped_interface.rs":"c11be14a0c95c3c9b055741e4b9c353d6bb6efe88075ceb05fd606b6ac34a2a6","src/strings/bstr.rs":"d82800786fb1b24a120390ba9edd343d34e78cd1b29a0cd6e70a2823bb5484c4","src/strings/hstring.rs":"a5f7f8ee2cbc293ed9ac32f55d32efdbfd71ea9d2785480ef76b0dec0633ec76","src/strings/literals.rs":"5b998ebd3a750a7f42c2013b354a58f6c289f5f433f154a9ac34b47e23ec9429","src/strings/mod.rs":"758276670ab6d01a5c9c78965cc4bace48b27dcbc30abc9b2a3cea2e9d96fe0b","src/strings/pcstr.rs":"540f01b2e28fa5b819b582071774e0c954a2bb026b953ce4e505de6c4291015a","src/strings/pcwstr.rs":"7783525994ec458bcad5c500aea617916ed3128ee799feb1264e4423bfc46bf0","src/strings/pstr.rs":"5bc3fadafb48df1b009e11ba9ccde5eb619c1df30d1675e6e0658fa7333e9673","src/strings/pwstr.rs":"0f59aa476fe4326e297cd6d7798cdc2307ab2795fdf5448dd0c1937a550f34f8","src/type.rs":"334fa825868794dbc0bac06a271631c142baee506e5a9caf1fac6ca2fb3cfff2","src/unknown.rs":"77981d78642c921b5479a30d6807ea931a9acbeb6c55399d4dc6243fad4ec4fb","src/variant.rs":"91e154533d4349cced8a6ebf2b6d33023afbee9cf0697414c2dc35ad0ef675b3","src/weak.rs":"9ec739389870aad73b674aaf20cae9e3cd67d2ad479f47d8e01bd9fe174a372e"},"package":"12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65"}

41
vendor/windows-core-0.54.0/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,41 @@
# 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.62"
name = "windows-core"
version = "0.54.0"
authors = ["Microsoft"]
description = "Rust for Windows"
readme = "readme.md"
categories = ["os::windows-apis"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/microsoft/windows-rs"
[package.metadata.docs.rs]
default-target = "x86_64-pc-windows-msvc"
targets = []
[dependencies.windows-result]
version = "0.1.0"
[dependencies.windows-targets]
version = "0.52.3"
[features]
default = []
implement = []
[lints.rust]
missing_docs = "warn"
rust_2018_idioms = "warn"
unused_qualifications = "warn"

View File

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

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

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

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

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

View File

@@ -0,0 +1,28 @@
use super::*;
use std::marker::PhantomData;
/// A type representing an agile reference to a COM/WinRT object.
#[repr(transparent)]
#[derive(Clone, PartialEq, Eq)]
pub struct AgileReference<T>(crate::imp::IAgileReference, PhantomData<T>);
impl<T: Interface> AgileReference<T> {
/// Creates an agile reference to the object.
pub fn new(object: &T) -> Result<Self> {
unsafe { crate::imp::RoGetAgileReference(crate::imp::AGILEREFERENCE_DEFAULT, &T::IID, std::mem::transmute::<_, &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> std::fmt::Debug for AgileReference<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "AgileReference({:?})", &self.0)
}
}

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

@@ -0,0 +1,177 @@
use super::*;
/// A WinRT array stores elements contiguously in a heap-allocated buffer.
pub struct Array<T: Type<T>> {
data: *mut T::Default,
len: u32,
}
impl<T: Type<T>> Default for Array<T> {
fn default() -> Self {
Array { data: std::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 < std::u32::MAX as usize);
let bytes_amount = len.checked_mul(std::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 { crate::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 {
std::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 = std::ptr::null_mut();
let mut len = 0;
std::mem::swap(&mut data, &mut self.data);
std::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`
std::ptr::drop_in_place(std::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
crate::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);
std::mem::forget(self);
abi
}
}
impl<T: Type<T>> std::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 { std::slice::from_raw_parts(self.data, self.len as usize) }
}
}
impl<T: Type<T>> std::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 { std::slice::from_raw_parts_mut(self.data, self.len as usize) }
}
}
impl<T: Type<T>> Drop for Array<T> {
fn drop(&mut self) {
self.clear();
}
}
#[doc(hidden)]
pub struct ArrayProxy<T: Type<T>> {
data: *mut *mut T::Default,
len: *mut u32,
temp: std::mem::ManuallyDrop<Array<T>>,
}
impl<T: Type<T>> ArrayProxy<T> {
pub fn from_raw_parts(data: *mut *mut T::Default, len: *mut u32) -> Self {
Self { data, len, temp: std::mem::ManuallyDrop::new(Array::new()) }
}
pub fn as_array(&mut self) -> &mut Array<T> {
&mut self.temp
}
}
impl<T: Type<T>> Drop for ArrayProxy<T> {
fn drop(&mut self) {
unsafe {
*self.data = self.temp.data;
*self.len = self.temp.len;
}
}
}

View File

@@ -0,0 +1,10 @@
/// 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;
}

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

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

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

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,108 @@
mod bindings;
mod com_bindings;
mod delay_load;
mod factory_cache;
mod generic_factory;
mod heap;
mod ref_count;
mod sha1;
mod waiter;
mod weak_ref_count;
pub use bindings::*;
pub use com_bindings::*;
pub use delay_load::*;
pub use factory_cache::*;
pub use generic_factory::*;
pub use heap::*;
pub use ref_count::*;
pub use sha1::*;
pub use waiter::*;
pub use weak_ref_count::*;
pub fn wide_trim_end(mut wide: &[u16]) -> &[u16] {
while let Some(last) = wide.last() {
match last {
32 | 9..=13 => wide = &wide[..wide.len() - 1],
_ => break,
}
}
wide
}
#[doc(hidden)]
#[macro_export]
macro_rules! interface_hierarchy {
($child:ident, $parent:ty) => {
impl ::windows_core::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::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! interface {
($(#[$doc:meta])? $name:ident, $vtbl:ident) => {
$(#[$doc])?
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct $name(::std::ptr::NonNull<::std::ffi::c_void>);
unsafe impl ::windows_core::Interface for $name {
type Vtable = $vtbl;
const IID: ::windows_core::GUID = ::windows_core::GUID::zeroed();
const UNKNOWN: bool = false;
}
};
}
#[doc(hidden)]
pub use interface;
#[doc(hidden)]
#[macro_export]
macro_rules! com_interface {
($(#[$doc:meta])? $name:ident, $vtbl:ident, $iid:literal) => {
$(#[$doc])?
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::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);
}
};
}
#[doc(hidden)]
pub use com_interface;

View File

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

View File

@@ -0,0 +1,373 @@
#![allow(clippy::many_single_char_names)]
pub const fn sha1(data: &ConstBuffer) -> Digest {
let state: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
let len: u64 = 0;
let blocks = Blocks { len: 0, data: [0; 64] };
let (blocks, len, state) = process_blocks(blocks, data, len, state);
digest(state, len, blocks)
}
const BUFFER_SIZE: usize = 1024;
pub struct ConstBuffer {
data: [u8; BUFFER_SIZE],
head: usize,
}
impl ConstBuffer {
pub const fn for_class<T: crate::RuntimeName + crate::Interface>() -> Self {
Self::new().push_slice(b"rc(").push_slice(T::NAME.as_bytes()).push(b';').push_guid(&T::IID).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 std::fmt::Display for Digest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for i in self.data.iter() {
write!(f, "{:08x}", i)?;
}
Ok(())
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,114 @@
use super::*;
/// 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;
#[doc(hidden)]
const IID: GUID;
#[doc(hidden)]
const UNKNOWN: bool = true;
/// A reference to the interface's vtable
#[doc(hidden)]
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)]
unsafe fn assume_vtable<T: Interface>(&self) -> &T::Vtable {
&**(self.as_raw() as *mut *mut T::Vtable)
}
/// Returns the raw COM interface pointer. The resulting pointer continues to be owned by the `Interface` implementation.
#[inline(always)]
fn as_raw(&self) -> *mut std::ffi::c_void {
// SAFETY: implementors of this trait must guarantee that the implementing type has a pointer in-memory representation
unsafe { std::mem::transmute_copy(self) }
}
/// Returns the raw COM interface pointer and releases ownership. It the caller's responsibility to release the COM interface pointer.
fn into_raw(self) -> *mut std::ffi::c_void {
// SAFETY: implementors of this trait must guarantee that the implementing type has a pointer in-memory representation
let raw = self.as_raw();
std::mem::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 std::ffi::c_void) -> Self {
std::mem::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`.
unsafe fn from_raw_borrowed(raw: &*mut std::ffi::c_void) -> Option<&Self> {
if raw.is_null() {
None
} else {
Some(std::mem::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.
fn cast<T: Interface>(&self) -> Result<T> {
let mut result = None;
// 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 { _ = self.query(&T::IID, &mut result as *mut _ as _) };
result.ok_or_else(|| Error::from_hresult(crate::imp::E_NOINTERFACE))
}
/// Attempts to create a [`Weak`] reference to this object.
fn downgrade(&self) -> Result<Weak<Self>> {
self.cast::<crate::imp::IWeakReferenceSource>().and_then(|source| Weak::downgrade(&source))
}
/// Call `QueryInterface` on this interface
///
/// # Safety
///
/// `interface` must be a non-null, valid pointer for writing an interface pointer.
unsafe fn query(&self, iid: *const GUID, interface: *mut *mut std::ffi::c_void) -> HRESULT {
if Self::UNKNOWN {
(self.assume_vtable::<IUnknown>().QueryInterface)(self.as_raw(), iid, interface)
} else {
panic!("Non-COM interfaces cannot be queried.")
}
}
}
/// # Safety
#[doc(hidden)]
pub unsafe fn from_raw_borrowed<T: Interface>(raw: &*mut std::ffi::c_void) -> Option<&T> {
T::from_raw_borrowed(raw)
}

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

@@ -0,0 +1,53 @@
/*!
Learn more about Rust for Windows here: <https://github.com/microsoft/windows-rs>
*/
#![doc(html_no_source)]
#![allow(non_snake_case)]
#![cfg_attr(windows_debugger_visualizer, debugger_visualizer(natvis_file = "../.natvis"))]
extern crate self as windows_core;
#[doc(hidden)]
pub mod imp;
mod agile_reference;
mod array;
mod as_impl;
mod event;
mod guid;
mod inspectable;
mod interface;
mod param;
mod runtime_name;
mod runtime_type;
mod scoped_interface;
mod strings;
mod r#type;
mod unknown;
mod variant;
mod weak;
pub use agile_reference::*;
pub use array::*;
pub use as_impl::*;
pub use event::*;
pub use guid::*;
pub use inspectable::*;
pub use interface::*;
pub use param::*;
pub use r#type::*;
pub use runtime_name::*;
pub use runtime_type::*;
pub use scoped_interface::*;
pub use strings::*;
pub use unknown::*;
pub use variant::*;
pub use weak::*;
pub use windows_result::*;
/// Attempts to load the factory object for the given WinRT class.
/// This can be used to access COM interfaces implemented on a Windows Runtime class factory.
pub fn factory<C: RuntimeName, I: Interface>() -> Result<I> {
crate::imp::factory::<C, I>()
}

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

@@ -0,0 +1,93 @@
use super::*;
#[doc(hidden)]
pub enum Param<T: Type<T>> {
Owned(T),
Borrowed(T::Abi),
}
impl<T: Type<T>> Param<T> {
pub fn abi(&self) -> T::Abi {
unsafe {
match self {
Self::Owned(item) => std::mem::transmute_copy(item),
Self::Borrowed(borrowed) => std::mem::transmute_copy(borrowed),
}
}
}
}
#[doc(hidden)]
pub trait CanInto<T>: Sized {
const QUERY: bool = false;
}
impl<T> CanInto<T> for T where T: Clone {}
#[doc(hidden)]
pub trait IntoParam<T: TypeKind, C = <T as TypeKind>::TypeKind>: Sized
where
T: Type<T>,
{
unsafe fn into_param(self) -> Param<T>;
}
impl<T> IntoParam<T> for Option<&T>
where
T: Type<T>,
{
unsafe fn into_param(self) -> Param<T> {
Param::Borrowed(match self {
Some(item) => std::mem::transmute_copy(item),
None => std::mem::zeroed(),
})
}
}
impl<T, U> IntoParam<T, ReferenceType> for &U
where
T: TypeKind<TypeKind = ReferenceType> + Clone,
T: Interface,
U: Interface,
U: CanInto<T>,
{
unsafe fn into_param(self) -> Param<T> {
if U::QUERY {
self.cast().map_or(Param::Borrowed(std::mem::zeroed()), |ok| Param::Owned(ok))
} else {
Param::Borrowed(std::mem::transmute_copy(self))
}
}
}
impl<T> IntoParam<T, ValueType> for &T
where
T: TypeKind<TypeKind = ValueType> + Clone,
{
unsafe fn into_param(self) -> Param<T> {
Param::Borrowed(std::mem::transmute_copy(self))
}
}
impl<T, U> IntoParam<T, CopyType> for U
where
T: TypeKind<TypeKind = CopyType> + Clone,
U: TypeKind<TypeKind = CopyType> + Clone,
U: CanInto<T>,
{
unsafe fn into_param(self) -> Param<T> {
Param::Owned(std::mem::transmute_copy(&self))
}
}
impl IntoParam<PCWSTR> for &BSTR {
unsafe fn into_param(self) -> Param<PCWSTR> {
Param::Owned(PCWSTR(self.as_ptr()))
}
}
impl IntoParam<PCWSTR> for &HSTRING {
unsafe fn into_param(self) -> Param<PCWSTR> {
Param::Owned(PCWSTR(self.as_ptr()))
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

@@ -0,0 +1,105 @@
use super::*;
/// 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(std::ptr::NonNull<std::ffi::c_void>);
#[doc(hidden)]
#[repr(C)]
pub struct IUnknown_Vtbl {
pub QueryInterface: unsafe extern "system" fn(this: *mut std::ffi::c_void, iid: *const GUID, interface: *mut *mut std::ffi::c_void) -> HRESULT,
pub AddRef: unsafe extern "system" fn(this: *mut std::ffi::c_void) -> u32,
pub Release: unsafe extern "system" fn(this: *mut std::ffi::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)(std::mem::transmute_copy(self));
}
Self(self.0)
}
}
impl Drop for IUnknown {
fn drop(&mut self) {
unsafe {
(self.vtable().Release)(std::mem::transmute_copy(self));
}
}
}
impl PartialEq for IUnknown {
fn eq(&self, other: &Self) -> bool {
// Since COM objects may implement multiple interfaces, COM identity can only
// be determined by querying for `IUnknown` explicitly and then comparing the
// pointer values. This works since `QueryInterface` is required to return
// the same pointer value for queries for `IUnknown`.
self.cast::<IUnknown>().unwrap().0 == other.cast::<IUnknown>().unwrap().0
}
}
impl Eq for IUnknown {}
impl std::fmt::Debug for IUnknown {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("IUnknown").field(&self.0).finish()
}
}
#[doc(hidden)]
pub trait IUnknownImpl {
type Impl;
/// Get a reference to the backing implementation.
fn get_impl(&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 std::ffi::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 interfacer 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.
unsafe fn Release(&self) -> u32;
/// Gets the trust level of the current object.
unsafe fn GetTrustLevel(&self, value: *mut i32) -> HRESULT;
}
#[cfg(feature = "implement")]
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 std::ffi::c_void, iid: *const GUID, interface: *mut *mut std::ffi::c_void) -> HRESULT {
let this = (this as *mut *mut std::ffi::c_void).offset(OFFSET) as *mut T;
(*this).QueryInterface(iid, interface)
}
unsafe extern "system" fn AddRef<T: IUnknownImpl, const OFFSET: isize>(this: *mut std::ffi::c_void) -> u32 {
let this = (this as *mut *mut std::ffi::c_void).offset(OFFSET) as *mut T;
(*this).AddRef()
}
unsafe extern "system" fn Release<T: IUnknownImpl, const OFFSET: isize>(this: *mut std::ffi::c_void) -> u32 {
let this = (this as *mut *mut std::ffi::c_void).offset(OFFSET) as *mut T;
(*this).Release()
}
Self { QueryInterface: QueryInterface::<T, OFFSET>, AddRef: AddRef::<T, OFFSET>, Release: Release::<T, OFFSET> }
}
}

View File

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

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

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