// Copyright © 2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(unused)] use crate::{ winapi::{IUnknown, Interface}, windows_sys::{ CoInitializeEx, SysFreeString, SysStringLen, BSTR, COINIT_MULTITHREADED, HRESULT, S_FALSE, S_OK, }, }; use std::{ ffi::{OsStr, OsString}, mem::ManuallyDrop, ops::Deref, os::windows::ffi::{OsStrExt, OsStringExt}, ptr::{null, null_mut}, slice::from_raw_parts, }; pub fn initialize() -> Result<(), HRESULT> { let err = unsafe { CoInitializeEx(null(), COINIT_MULTITHREADED) }; if err != S_OK && err != S_FALSE { // S_FALSE just means COM is already initialized Err(err) } else { Ok(()) } } pub struct ComPtr(*mut T) where T: Interface; impl ComPtr where T: Interface, { /// 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 { assert!(!ptr.is_null()); ComPtr(ptr) } /// Casts up the inheritance chain pub fn up(self) -> ComPtr where T: Deref, U: Interface, { ComPtr(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 { ManuallyDrop::new(self).0 } /// For internal use only. fn as_unknown(&self) -> &IUnknown { unsafe { &*(self.0 as *mut IUnknown) } } /// Performs QueryInterface fun. pub fn cast(&self) -> Result, 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) }) } } impl Deref for ComPtr where T: Interface, { type Target = T; fn deref(&self) -> &T { unsafe { &*self.0 } } } impl Clone for ComPtr where T: Interface, { fn clone(&self) -> Self { unsafe { self.as_unknown().AddRef(); ComPtr::from_raw(self.0) } } } impl Drop for ComPtr where T: Interface, { fn drop(&mut self) { unsafe { self.as_unknown().Release(); } } } pub struct BStr(BSTR); impl BStr { pub unsafe fn from_raw(s: BSTR) -> BStr { BStr(s) } pub fn to_osstring(&self) -> OsString { let len = unsafe { SysStringLen(self.0) }; let slice = unsafe { from_raw_parts(self.0, len as usize) }; OsStringExt::from_wide(slice) } } impl Drop for BStr { fn drop(&mut self) { unsafe { SysFreeString(self.0) }; } } pub trait ToWide { fn to_wide(&self) -> Vec; fn to_wide_null(&self) -> Vec; } impl ToWide for T where T: AsRef, { fn to_wide(&self) -> Vec { self.as_ref().encode_wide().collect() } fn to_wide_null(&self) -> Vec { self.as_ref().encode_wide().chain(Some(0)).collect() } } pub trait FromWide where Self: Sized, { fn from_wide(wide: &[u16]) -> Self; fn from_wide_null(wide: &[u16]) -> Self { let len = wide.iter().take_while(|&&c| c != 0).count(); Self::from_wide(&wide[..len]) } } impl FromWide for OsString { fn from_wide(wide: &[u16]) -> OsString { OsStringExt::from_wide(wide) } }