Skip to content

Commit c111f13

Browse files
authored
Merge pull request #160 from brson/vs2017
Add MSVC 2017 detection
2 parents 1bc6010 + 4ea110e commit c111f13

File tree

5 files changed

+694
-7
lines changed

5 files changed

+694
-7
lines changed

src/com.rs

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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 std::ffi::{OsStr, OsString};
11+
use std::mem::forget;
12+
use std::ops::Deref;
13+
use std::os::windows::ffi::{OsStrExt, OsStringExt};
14+
use std::ptr::null_mut;
15+
use std::slice::from_raw_parts;
16+
use winapi::Interface;
17+
use winapi::BSTR;
18+
use winapi::CoInitializeEx;
19+
use winapi::COINIT_MULTITHREADED;
20+
use winapi::{SysFreeString, SysStringLen};
21+
use winapi::IUnknown;
22+
use winapi::{S_OK, S_FALSE, HRESULT};
23+
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) where T: Interface;
34+
impl<T> ComPtr<T> where T: Interface {
35+
/// Creates a `ComPtr` to wrap a raw pointer.
36+
/// It takes ownership over the pointer which means it does __not__ call `AddRef`.
37+
/// `T` __must__ be a COM interface that inherits from `IUnknown`.
38+
pub unsafe fn from_raw(ptr: *mut T) -> ComPtr<T> {
39+
assert!(!ptr.is_null());
40+
ComPtr(ptr)
41+
}
42+
/// Casts up the inheritance chain
43+
pub fn up<U>(self) -> ComPtr<U> where T: Deref<Target=U>, U: Interface {
44+
ComPtr(self.into_raw() as *mut U)
45+
}
46+
/// Extracts the raw pointer.
47+
/// You are now responsible for releasing it yourself.
48+
pub fn into_raw(self) -> *mut T {
49+
let p = self.0;
50+
forget(self);
51+
p
52+
}
53+
/// For internal use only.
54+
fn as_unknown(&self) -> &IUnknown {
55+
unsafe { &*(self.0 as *mut IUnknown) }
56+
}
57+
/// Performs QueryInterface fun.
58+
pub fn cast<U>(&self) -> Result<ComPtr<U>, i32> where U: Interface {
59+
let mut obj = null_mut();
60+
let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) };
61+
if err < 0 { return Err(err); }
62+
Ok(unsafe { ComPtr::from_raw(obj as *mut U) })
63+
}
64+
}
65+
impl<T> Deref for ComPtr<T> where T: Interface {
66+
type Target = T;
67+
fn deref(&self) -> &T {
68+
unsafe { &*self.0 }
69+
}
70+
}
71+
impl<T> Clone for ComPtr<T> where T: Interface {
72+
fn clone(&self) -> Self {
73+
unsafe {
74+
self.as_unknown().AddRef();
75+
ComPtr::from_raw(self.0)
76+
}
77+
}
78+
}
79+
impl<T> Drop for ComPtr<T> where T: Interface {
80+
fn drop(&mut self) {
81+
unsafe { self.as_unknown().Release(); }
82+
}
83+
}
84+
pub struct BStr(BSTR);
85+
impl BStr {
86+
pub unsafe fn from_raw(s: BSTR) -> BStr {
87+
BStr(s)
88+
}
89+
pub fn to_osstring(&self) -> OsString {
90+
let len = unsafe { SysStringLen(self.0) };
91+
let slice = unsafe { from_raw_parts(self.0, len as usize) };
92+
OsStringExt::from_wide(slice)
93+
}
94+
}
95+
impl Drop for BStr {
96+
fn drop(&mut self) {
97+
unsafe { SysFreeString(self.0) };
98+
}
99+
}
100+
101+
pub trait ToWide {
102+
fn to_wide(&self) -> Vec<u16>;
103+
fn to_wide_null(&self) -> Vec<u16>;
104+
}
105+
impl<T> ToWide for T where T: AsRef<OsStr> {
106+
fn to_wide(&self) -> Vec<u16> {
107+
self.as_ref().encode_wide().collect()
108+
}
109+
fn to_wide_null(&self) -> Vec<u16> {
110+
self.as_ref().encode_wide().chain(Some(0)).collect()
111+
}
112+
}
113+
pub trait FromWide where Self: Sized {
114+
fn from_wide(wide: &[u16]) -> Self;
115+
fn from_wide_null(wide: &[u16]) -> Self {
116+
let len = wide.iter().take_while(|&&c| c != 0).count();
117+
Self::from_wide(&wide[..len])
118+
}
119+
}
120+
impl FromWide for OsString {
121+
fn from_wide(wide: &[u16]) -> OsString {
122+
OsStringExt::from_wide(wide)
123+
}
124+
}
125+

src/lib.rs

+10
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,18 @@ use std::process::{Command, Stdio, Child};
5757
use std::io::{self, BufReader, BufRead, Read, Write};
5858
use std::thread::{self, JoinHandle};
5959

60+
// These modules are all glue to support reading the MSVC version from
61+
// the registry and from COM interfaces
6062
#[cfg(windows)]
6163
mod registry;
64+
#[cfg(windows)]
65+
#[macro_use]
66+
mod winapi;
67+
#[cfg(windows)]
68+
mod com;
69+
#[cfg(windows)]
70+
mod setup_config;
71+
6272
pub mod windows_registry;
6373

6474
/// Extra configuration to pass to gcc.

0 commit comments

Comments
 (0)