diff options
Diffstat (limited to 'third_party/rust/wio/src/com.rs')
-rw-r--r-- | third_party/rust/wio/src/com.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/third_party/rust/wio/src/com.rs b/third_party/rust/wio/src/com.rs new file mode 100644 index 0000000000..d94d3d35cf --- /dev/null +++ b/third_party/rust/wio/src/com.rs @@ -0,0 +1,79 @@ +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option. +// All files in the project carrying such notice may not be copied, modified, or distributed +// except according to those terms. +use std::fmt::{Debug, Error as FmtError, Formatter}; +use std::mem::forget; +use std::ops::Deref; +use std::ptr::{NonNull, null_mut}; +use winapi::Interface; +use winapi::um::unknwnbase::IUnknown; + +// ComPtr to wrap COM interfaces sanely +#[repr(transparent)] +pub struct ComPtr<T>(NonNull<T>); +impl<T> ComPtr<T> { + /// Creates a `ComPtr` to wrap a raw pointer. + /// It takes ownership over the pointer which means it does __not__ call `AddRef`. + /// `T` __must__ be a COM interface that inherits from `IUnknown`. + pub unsafe fn from_raw(ptr: *mut T) -> ComPtr<T> where T: Interface { + ComPtr(NonNull::new(ptr).expect("ptr should not be null")) + } + /// Casts up the inheritance chain + pub fn up<U>(self) -> ComPtr<U> where T: Deref<Target=U>, U: Interface { + unsafe { ComPtr::from_raw(self.into_raw() as *mut U) } + } + /// Extracts the raw pointer. + /// You are now responsible for releasing it yourself. + pub fn into_raw(self) -> *mut T { + let p = self.0.as_ptr(); + forget(self); + p + } + /// For internal use only. + fn as_unknown(&self) -> &IUnknown { + unsafe { &*(self.as_raw() as *mut IUnknown) } + } + /// Performs QueryInterface fun. + pub fn cast<U>(&self) -> Result<ComPtr<U>, i32> where U: Interface { + let mut obj = null_mut(); + let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) }; + if err < 0 { return Err(err); } + Ok(unsafe { ComPtr::from_raw(obj as *mut U) }) + } + /// Obtains the raw pointer without transferring ownership. + /// Do __not__ release this pointer because it is still owned by the `ComPtr`. + pub fn as_raw(&self) -> *mut T { + self.0.as_ptr() + } +} +impl<T> Deref for ComPtr<T> { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*self.as_raw() } + } +} +impl<T> Clone for ComPtr<T> where T: Interface { + fn clone(&self) -> Self { + unsafe { + self.as_unknown().AddRef(); + ComPtr::from_raw(self.as_raw()) + } + } +} +impl<T> Debug for ComPtr<T> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "{:?}", self.0) + } +} +impl<T> Drop for ComPtr<T> { + fn drop(&mut self) { + unsafe { self.as_unknown().Release(); } + } +} +impl<T> PartialEq<ComPtr<T>> for ComPtr<T> where T: Interface { + fn eq(&self, other: &ComPtr<T>) -> bool { + self.0 == other.0 + } +} |