]> git.proxmox.com Git - rustc.git/blob - src/vendor/gcc/src/registry.rs
New upstream version 1.15.0+dfsg1
[rustc.git] / src / vendor / gcc / src / registry.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::ffi::{OsString, OsStr};
12 use std::io;
13 use std::ops::RangeFrom;
14 use std::os::raw;
15 use std::os::windows::prelude::*;
16
17 pub struct RegistryKey(Repr);
18
19 type HKEY = *mut u8;
20 type DWORD = u32;
21 type LPDWORD = *mut DWORD;
22 type LPCWSTR = *const u16;
23 type LPWSTR = *mut u16;
24 type LONG = raw::c_long;
25 type PHKEY = *mut HKEY;
26 type PFILETIME = *mut u8;
27 type LPBYTE = *mut u8;
28 type REGSAM = u32;
29
30 const ERROR_SUCCESS: DWORD = 0;
31 const ERROR_NO_MORE_ITEMS: DWORD = 259;
32 const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
33 const REG_SZ: DWORD = 1;
34 const KEY_READ: DWORD = 0x20019;
35 const KEY_WOW64_32KEY: DWORD = 0x200;
36
37 #[link(name = "advapi32")]
38 extern "system" {
39 fn RegOpenKeyExW(key: HKEY,
40 lpSubKey: LPCWSTR,
41 ulOptions: DWORD,
42 samDesired: REGSAM,
43 phkResult: PHKEY) -> LONG;
44 fn RegEnumKeyExW(key: HKEY,
45 dwIndex: DWORD,
46 lpName: LPWSTR,
47 lpcName: LPDWORD,
48 lpReserved: LPDWORD,
49 lpClass: LPWSTR,
50 lpcClass: LPDWORD,
51 lpftLastWriteTime: PFILETIME) -> LONG;
52 fn RegQueryValueExW(hKey: HKEY,
53 lpValueName: LPCWSTR,
54 lpReserved: LPDWORD,
55 lpType: LPDWORD,
56 lpData: LPBYTE,
57 lpcbData: LPDWORD) -> LONG;
58 fn RegCloseKey(hKey: HKEY) -> LONG;
59 }
60
61 struct OwnedKey(HKEY);
62
63 enum Repr {
64 Const(HKEY),
65 Owned(OwnedKey),
66 }
67
68 pub struct Iter<'a> {
69 idx: RangeFrom<DWORD>,
70 key: &'a RegistryKey,
71 }
72
73 unsafe impl Sync for Repr {}
74 unsafe impl Send for Repr {}
75
76 pub static LOCAL_MACHINE: RegistryKey =
77 RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE));
78
79 impl RegistryKey {
80 fn raw(&self) -> HKEY {
81 match self.0 {
82 Repr::Const(val) => val,
83 Repr::Owned(ref val) => val.0,
84 }
85 }
86
87 pub fn open(&self, key: &OsStr) -> io::Result<RegistryKey> {
88 let key = key.encode_wide().chain(Some(0)).collect::<Vec<_>>();
89 let mut ret = 0 as *mut _;
90 let err = unsafe {
91 RegOpenKeyExW(self.raw(), key.as_ptr(), 0,
92 KEY_READ | KEY_WOW64_32KEY, &mut ret)
93 };
94 if err == ERROR_SUCCESS as LONG {
95 Ok(RegistryKey(Repr::Owned(OwnedKey(ret))))
96 } else {
97 Err(io::Error::from_raw_os_error(err as i32))
98 }
99 }
100
101 pub fn iter(&self) -> Iter {
102 Iter { idx: 0.., key: self }
103 }
104
105 pub fn query_str(&self, name: &str) -> io::Result<OsString> {
106 let name: &OsStr = name.as_ref();
107 let name = name.encode_wide().chain(Some(0)).collect::<Vec<_>>();
108 let mut len = 0;
109 let mut kind = 0;
110 unsafe {
111 let err = RegQueryValueExW(self.raw(), name.as_ptr(), 0 as *mut _,
112 &mut kind, 0 as *mut _, &mut len);
113 if err != ERROR_SUCCESS as LONG {
114 return Err(io::Error::from_raw_os_error(err as i32))
115 }
116 if kind != REG_SZ {
117 return Err(io::Error::new(io::ErrorKind::Other,
118 "registry key wasn't a string"))
119 }
120
121 // The length here is the length in bytes, but we're using wide
122 // characters so we need to be sure to halve it for the capacity
123 // passed in.
124 let mut v = Vec::with_capacity(len as usize / 2);
125 let err = RegQueryValueExW(self.raw(), name.as_ptr(), 0 as *mut _,
126 0 as *mut _, v.as_mut_ptr() as *mut _,
127 &mut len);
128 if err != ERROR_SUCCESS as LONG {
129 return Err(io::Error::from_raw_os_error(err as i32))
130 }
131 v.set_len(len as usize / 2);
132
133 // Some registry keys may have a terminating nul character, but
134 // we're not interested in that, so chop it off if it's there.
135 if v[v.len() - 1] == 0 {
136 v.pop();
137 }
138 Ok(OsString::from_wide(&v))
139 }
140 }
141 }
142
143 impl Drop for OwnedKey {
144 fn drop(&mut self) {
145 unsafe { RegCloseKey(self.0); }
146 }
147 }
148
149 impl<'a> Iterator for Iter<'a> {
150 type Item = io::Result<OsString>;
151
152 fn next(&mut self) -> Option<io::Result<OsString>> {
153 self.idx.next().and_then(|i| unsafe {
154 let mut v = Vec::with_capacity(256);
155 let mut len = v.capacity() as DWORD;
156 let ret = RegEnumKeyExW(self.key.raw(), i, v.as_mut_ptr(), &mut len,
157 0 as *mut _, 0 as *mut _, 0 as *mut _,
158 0 as *mut _);
159 if ret == ERROR_NO_MORE_ITEMS as LONG {
160 None
161 } else if ret != ERROR_SUCCESS as LONG {
162 Some(Err(io::Error::from_raw_os_error(ret as i32)))
163 } else {
164 v.set_len(len as usize);
165 Some(Ok(OsString::from_wide(&v)))
166 }
167 })
168 }
169 }