1 // Copyright © 2017 winapi-rs developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
4 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
5 // All files in the project carrying such notice may not be copied, modified, or distributed
6 // except according to those terms.
7 
8 #![allow(unused)]
9 
10 use crate::winapi::CoInitializeEx;
11 use crate::winapi::IUnknown;
12 use crate::winapi::Interface;
13 use crate::winapi::BSTR;
14 use crate::winapi::COINIT_MULTITHREADED;
15 use crate::winapi::{SysFreeString, SysStringLen};
16 use crate::winapi::{HRESULT, S_FALSE, S_OK};
17 use std::ffi::{OsStr, OsString};
18 use std::mem::forget;
19 use std::ops::Deref;
20 use std::os::windows::ffi::{OsStrExt, OsStringExt};
21 use std::ptr::null_mut;
22 use std::slice::from_raw_parts;
23 
initialize() -> Result<(), HRESULT>24 pub fn initialize() -> Result<(), HRESULT> {
25     let err = unsafe { CoInitializeEx(null_mut(), COINIT_MULTITHREADED) };
26     if err != S_OK && err != S_FALSE {
27         // S_FALSE just means COM is already initialized
28         return Err(err);
29     }
30     Ok(())
31 }
32 
33 pub struct ComPtr<T>(*mut T)
34 where
35     T: Interface;
36 impl<T> ComPtr<T>
37 where
38     T: Interface,
39 {
40     /// Creates a `ComPtr` to wrap a raw pointer.
41     /// It takes ownership over the pointer which means it does __not__ call `AddRef`.
42     /// `T` __must__ be a COM interface that inherits from `IUnknown`.
from_raw(ptr: *mut T) -> ComPtr<T>43     pub unsafe fn from_raw(ptr: *mut T) -> ComPtr<T> {
44         assert!(!ptr.is_null());
45         ComPtr(ptr)
46     }
47     /// Casts up the inheritance chain
up<U>(self) -> ComPtr<U> where T: Deref<Target = U>, U: Interface,48     pub fn up<U>(self) -> ComPtr<U>
49     where
50         T: Deref<Target = U>,
51         U: Interface,
52     {
53         ComPtr(self.into_raw() as *mut U)
54     }
55     /// Extracts the raw pointer.
56     /// You are now responsible for releasing it yourself.
into_raw(self) -> *mut T57     pub fn into_raw(self) -> *mut T {
58         let p = self.0;
59         forget(self);
60         p
61     }
62     /// For internal use only.
as_unknown(&self) -> &IUnknown63     fn as_unknown(&self) -> &IUnknown {
64         unsafe { &*(self.0 as *mut IUnknown) }
65     }
66     /// Performs QueryInterface fun.
cast<U>(&self) -> Result<ComPtr<U>, i32> where U: Interface,67     pub fn cast<U>(&self) -> Result<ComPtr<U>, i32>
68     where
69         U: Interface,
70     {
71         let mut obj = null_mut();
72         let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) };
73         if err < 0 {
74             return Err(err);
75         }
76         Ok(unsafe { ComPtr::from_raw(obj as *mut U) })
77     }
78 }
79 impl<T> Deref for ComPtr<T>
80 where
81     T: Interface,
82 {
83     type Target = T;
deref(&self) -> &T84     fn deref(&self) -> &T {
85         unsafe { &*self.0 }
86     }
87 }
88 impl<T> Clone for ComPtr<T>
89 where
90     T: Interface,
91 {
clone(&self) -> Self92     fn clone(&self) -> Self {
93         unsafe {
94             self.as_unknown().AddRef();
95             ComPtr::from_raw(self.0)
96         }
97     }
98 }
99 impl<T> Drop for ComPtr<T>
100 where
101     T: Interface,
102 {
drop(&mut self)103     fn drop(&mut self) {
104         unsafe {
105             self.as_unknown().Release();
106         }
107     }
108 }
109 pub struct BStr(BSTR);
110 impl BStr {
from_raw(s: BSTR) -> BStr111     pub unsafe fn from_raw(s: BSTR) -> BStr {
112         BStr(s)
113     }
to_osstring(&self) -> OsString114     pub fn to_osstring(&self) -> OsString {
115         let len = unsafe { SysStringLen(self.0) };
116         let slice = unsafe { from_raw_parts(self.0, len as usize) };
117         OsStringExt::from_wide(slice)
118     }
119 }
120 impl Drop for BStr {
drop(&mut self)121     fn drop(&mut self) {
122         unsafe { SysFreeString(self.0) };
123     }
124 }
125 
126 pub trait ToWide {
to_wide(&self) -> Vec<u16>127     fn to_wide(&self) -> Vec<u16>;
to_wide_null(&self) -> Vec<u16>128     fn to_wide_null(&self) -> Vec<u16>;
129 }
130 impl<T> ToWide for T
131 where
132     T: AsRef<OsStr>,
133 {
to_wide(&self) -> Vec<u16>134     fn to_wide(&self) -> Vec<u16> {
135         self.as_ref().encode_wide().collect()
136     }
to_wide_null(&self) -> Vec<u16>137     fn to_wide_null(&self) -> Vec<u16> {
138         self.as_ref().encode_wide().chain(Some(0)).collect()
139     }
140 }
141 pub trait FromWide
142 where
143     Self: Sized,
144 {
from_wide(wide: &[u16]) -> Self145     fn from_wide(wide: &[u16]) -> Self;
from_wide_null(wide: &[u16]) -> Self146     fn from_wide_null(wide: &[u16]) -> Self {
147         let len = wide.iter().take_while(|&&c| c != 0).count();
148         Self::from_wide(&wide[..len])
149     }
150 }
151 impl FromWide for OsString {
from_wide(wide: &[u16]) -> OsString152     fn from_wide(wide: &[u16]) -> OsString {
153         OsStringExt::from_wide(wide)
154     }
155 }
156