]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/back/msvc/registry.rs
Auto merge of #30286 - oli-obk:const_error_span, r=nikomatsakis
[rust.git] / src / librustc_trans / back / msvc / 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::io;
12 use std::ffi::{OsString, OsStr};
13 use std::os::windows::prelude::*;
14 use std::ptr;
15 use libc::{c_void, c_long};
16
17 type DWORD = u32;
18 type LPCWSTR = *const u16;
19 type LONG = c_long;
20 type LPDWORD = *mut DWORD;
21 type LPBYTE = *mut u8;
22
23
24 const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
25 const KEY_WOW64_32KEY: REGSAM = 0x0200;
26 const KEY_READ: REGSAM = (STANDARD_RIGTS_READ | KEY_QUERY_VALUE |
27                           KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & !SYNCHRONIZE;
28 const STANDARD_RIGTS_READ: REGSAM = READ_CONTROL;
29 const READ_CONTROL: REGSAM = 0x00020000;
30 const KEY_QUERY_VALUE: REGSAM = 0x0001;
31 const KEY_ENUMERATE_SUB_KEYS: REGSAM = 0x0008;
32 const KEY_NOTIFY: REGSAM = 0x0010;
33 const SYNCHRONIZE: REGSAM = 0x00100000;
34 const REG_SZ: DWORD = 1;
35 const ERROR_SUCCESS: i32 = 0;
36
37 enum __HKEY__ {}
38 pub type HKEY = *mut __HKEY__;
39 pub type PHKEY = *mut HKEY;
40 pub type REGSAM = DWORD;
41 pub type LPWSTR = *mut u16;
42 pub type PFILETIME = *mut c_void;
43
44 #[link(name = "advapi32")]
45 extern "system" {
46     fn RegOpenKeyExW(hKey: HKEY,
47                      lpSubKey: LPCWSTR,
48                      ulOptions: DWORD,
49                      samDesired: REGSAM,
50                      phkResult: PHKEY) -> LONG;
51     fn RegQueryValueExW(hKey: HKEY,
52                         lpValueName: LPCWSTR,
53                         lpReserved: LPDWORD,
54                         lpType: LPDWORD,
55                         lpData: LPBYTE,
56                         lpcbData: LPDWORD) -> LONG;
57     fn RegCloseKey(hKey: HKEY) -> LONG;
58 }
59
60 pub struct RegistryKey(Repr);
61
62 struct OwnedKey(HKEY);
63
64 enum Repr {
65     Const(HKEY),
66     Owned(OwnedKey),
67 }
68
69 unsafe impl Sync for RegistryKey {}
70 unsafe impl Send for RegistryKey {}
71
72 pub static LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE));
73
74 impl RegistryKey {
75     fn raw(&self) -> HKEY {
76         match self.0 {
77             Repr::Const(val) => val,
78             Repr::Owned(ref val) => val.0,
79         }
80     }
81
82     pub fn open(&self, key: &OsStr) -> io::Result<RegistryKey> {
83         let key = key.encode_wide().chain(Some(0)).collect::<Vec<_>>();
84         let mut ret = ptr::null_mut();
85         let err = unsafe {
86             RegOpenKeyExW(self.raw(), key.as_ptr(), 0,
87                           KEY_READ | KEY_WOW64_32KEY, &mut ret)
88         };
89         if err == ERROR_SUCCESS {
90             Ok(RegistryKey(Repr::Owned(OwnedKey(ret))))
91         } else {
92             Err(io::Error::from_raw_os_error(err as i32))
93         }
94     }
95
96     pub fn query_str(&self, name: &str) -> io::Result<OsString> {
97         let name: &OsStr = name.as_ref();
98         let name = name.encode_wide().chain(Some(0)).collect::<Vec<_>>();
99         let mut len = 0;
100         let mut kind = 0;
101         unsafe {
102             let err = RegQueryValueExW(self.raw(), name.as_ptr(), ptr::null_mut(),
103                                        &mut kind, ptr::null_mut(), &mut len);
104             if err != ERROR_SUCCESS {
105                 return Err(io::Error::from_raw_os_error(err as i32))
106             }
107             if kind != REG_SZ {
108                 return Err(io::Error::new(io::ErrorKind::Other,
109                                           "registry key wasn't a string"))
110             }
111
112             // The length here is the length in bytes, but we're using wide
113             // characters so we need to be sure to halve it for the capacity
114             // passed in.
115             let mut v = Vec::with_capacity(len as usize / 2);
116             let err = RegQueryValueExW(self.raw(), name.as_ptr(), ptr::null_mut(),
117                                        ptr::null_mut(), v.as_mut_ptr() as *mut _,
118                                        &mut len);
119             if err != ERROR_SUCCESS {
120                 return Err(io::Error::from_raw_os_error(err as i32))
121             }
122             v.set_len(len as usize / 2);
123
124             // Some registry keys may have a terminating nul character, but
125             // we're not interested in that, so chop it off if it's there.
126             if v[v.len() - 1] == 0 {
127                 v.pop();
128             }
129             Ok(OsString::from_wide(&v))
130         }
131     }
132 }
133
134 impl Drop for OwnedKey {
135     fn drop(&mut self) {
136         unsafe { RegCloseKey(self.0); }
137     }
138 }