]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/back/msvc/registry.rs
Imported Upstream version 1.7.0+dfsg1
[rustc.git] / src / librustc_trans / back / msvc / registry.rs
CommitLineData
c1a9b12d
SL
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
11use std::io;
12use std::ffi::{OsString, OsStr};
13use std::os::windows::prelude::*;
e9174d1e 14use std::ptr;
92a42be0
SL
15use libc::{c_void, c_long};
16
9cc50fc6 17pub type DWORD = u32;
92a42be0
SL
18type LPCWSTR = *const u16;
19type LONG = c_long;
20type LPDWORD = *mut DWORD;
21type LPBYTE = *mut u8;
22
c1a9b12d
SL
23
24const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
25const KEY_WOW64_32KEY: REGSAM = 0x0200;
26const KEY_READ: REGSAM = (STANDARD_RIGTS_READ | KEY_QUERY_VALUE |
27 KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & !SYNCHRONIZE;
28const STANDARD_RIGTS_READ: REGSAM = READ_CONTROL;
29const READ_CONTROL: REGSAM = 0x00020000;
30const KEY_QUERY_VALUE: REGSAM = 0x0001;
31const KEY_ENUMERATE_SUB_KEYS: REGSAM = 0x0008;
32const KEY_NOTIFY: REGSAM = 0x0010;
33const SYNCHRONIZE: REGSAM = 0x00100000;
34const REG_SZ: DWORD = 1;
92a42be0 35const ERROR_SUCCESS: i32 = 0;
c1a9b12d 36
9cc50fc6 37pub enum __HKEY__ {}
c1a9b12d
SL
38pub type HKEY = *mut __HKEY__;
39pub type PHKEY = *mut HKEY;
40pub type REGSAM = DWORD;
41pub type LPWSTR = *mut u16;
42pub type PFILETIME = *mut c_void;
43
44#[link(name = "advapi32")]
45extern "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;
c1a9b12d
SL
57 fn RegCloseKey(hKey: HKEY) -> LONG;
58}
59
60pub struct RegistryKey(Repr);
61
62struct OwnedKey(HKEY);
63
64enum Repr {
65 Const(HKEY),
66 Owned(OwnedKey),
67}
68
c1a9b12d
SL
69unsafe impl Sync for RegistryKey {}
70unsafe impl Send for RegistryKey {}
71
72pub static LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE));
73
74impl 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<_>>();
e9174d1e 84 let mut ret = ptr::null_mut();
c1a9b12d
SL
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
c1a9b12d
SL
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 {
e9174d1e
SL
102 let err = RegQueryValueExW(self.raw(), name.as_ptr(), ptr::null_mut(),
103 &mut kind, ptr::null_mut(), &mut len);
c1a9b12d
SL
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);
e9174d1e
SL
116 let err = RegQueryValueExW(self.raw(), name.as_ptr(), ptr::null_mut(),
117 ptr::null_mut(), v.as_mut_ptr() as *mut _,
c1a9b12d
SL
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
134impl Drop for OwnedKey {
135 fn drop(&mut self) {
136 unsafe { RegCloseKey(self.0); }
137 }
138}