forked from rust-lang/cc-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This teaches gcc-rs to find tools installed by MSVC 2017. It's not obvious to what extent the new COM interfaces are expected to be used. This patch only uses it to find the product installation directory, then infers everything else. A lot of COM scaffolding to do very little. The toolchains seem to have a different directory structure in this release to better support cross-compilation. It looks to me like all the lib/include logic is pretty much the same as it always has been. This is tested to fix the rustup installation logic, and to fix rustc in basic use cases on x86_64. cc rust-lang#143 cc rust-lang/rustup#1003 cc rust-lang/rust#38584 cc alexcrichton/curl-rust#161
- Loading branch information
Showing
5 changed files
with
694 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// Copyright © 2017 winapi-rs developers | ||
// 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. | ||
|
||
#![allow(unused)] | ||
|
||
use std::ffi::{OsStr, OsString}; | ||
use std::mem::forget; | ||
use std::ops::Deref; | ||
use std::os::windows::ffi::{OsStrExt, OsStringExt}; | ||
use std::ptr::null_mut; | ||
use std::slice::from_raw_parts; | ||
use winapi::Interface; | ||
use winapi::BSTR; | ||
use winapi::CoInitializeEx; | ||
use winapi::COINIT_MULTITHREADED; | ||
use winapi::{SysFreeString, SysStringLen}; | ||
use winapi::IUnknown; | ||
use winapi::{S_OK, S_FALSE, HRESULT}; | ||
|
||
pub fn initialize() -> Result<(), HRESULT> { | ||
let err = unsafe { CoInitializeEx(null_mut(), COINIT_MULTITHREADED) }; | ||
if err != S_OK && err != S_FALSE { | ||
// S_FALSE just means COM is already initialized | ||
return Err(err); | ||
} | ||
Ok(()) | ||
} | ||
|
||
pub struct ComPtr<T>(*mut T) where T: Interface; | ||
impl<T> ComPtr<T> 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<T> { | ||
assert!(!ptr.is_null()); | ||
ComPtr(ptr) | ||
} | ||
/// Casts up the inheritance chain | ||
pub fn up<U>(self) -> ComPtr<U> where T: Deref<Target=U>, 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 { | ||
let p = self.0; | ||
forget(self); | ||
p | ||
} | ||
/// For internal use only. | ||
fn as_unknown(&self) -> &IUnknown { | ||
unsafe { &*(self.0 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) }) | ||
} | ||
} | ||
impl<T> Deref for ComPtr<T> where T: Interface { | ||
type Target = T; | ||
fn deref(&self) -> &T { | ||
unsafe { &*self.0 } | ||
} | ||
} | ||
impl<T> Clone for ComPtr<T> where T: Interface { | ||
fn clone(&self) -> Self { | ||
unsafe { | ||
self.as_unknown().AddRef(); | ||
ComPtr::from_raw(self.0) | ||
} | ||
} | ||
} | ||
impl<T> Drop for ComPtr<T> 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<u16>; | ||
fn to_wide_null(&self) -> Vec<u16>; | ||
} | ||
impl<T> ToWide for T where T: AsRef<OsStr> { | ||
fn to_wide(&self) -> Vec<u16> { | ||
self.as_ref().encode_wide().collect() | ||
} | ||
fn to_wide_null(&self) -> Vec<u16> { | ||
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) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.