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.
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.
11 use std
::ffi
::{OsString, OsStr}
;
13 use std
::ops
::RangeFrom
;
15 use std
::os
::windows
::prelude
::*;
17 pub struct RegistryKey(Repr
);
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;
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;
37 #[link(name = "advapi32")]
39 fn RegOpenKeyExW(key
: HKEY
,
43 phkResult
: PHKEY
) -> LONG
;
44 fn RegEnumKeyExW(key
: HKEY
,
51 lpftLastWriteTime
: PFILETIME
) -> LONG
;
52 fn RegQueryValueExW(hKey
: HKEY
,
57 lpcbData
: LPDWORD
) -> LONG
;
58 fn RegCloseKey(hKey
: HKEY
) -> LONG
;
61 struct OwnedKey(HKEY
);
69 idx
: RangeFrom
<DWORD
>,
73 unsafe impl Sync
for Repr {}
74 unsafe impl Send
for Repr {}
76 pub static LOCAL_MACHINE
: RegistryKey
=
77 RegistryKey(Repr
::Const(HKEY_LOCAL_MACHINE
));
80 fn raw(&self) -> HKEY
{
82 Repr
::Const(val
) => val
,
83 Repr
::Owned(ref val
) => val
.0,
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 _
;
91 RegOpenKeyExW(self.raw(), key
.as_ptr(), 0,
92 KEY_READ
| KEY_WOW64_32KEY
, &mut ret
)
94 if err
== ERROR_SUCCESS
as LONG
{
95 Ok(RegistryKey(Repr
::Owned(OwnedKey(ret
))))
97 Err(io
::Error
::from_raw_os_error(err
as i32))
101 pub fn iter(&self) -> Iter
{
102 Iter { idx: 0.., key: self }
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
<_
>>();
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))
117 return Err(io
::Error
::new(io
::ErrorKind
::Other
,
118 "registry key wasn't a string"))
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
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 _
,
128 if err
!= ERROR_SUCCESS
as LONG
{
129 return Err(io
::Error
::from_raw_os_error(err
as i32))
131 v
.set_len(len
as usize / 2);
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 {
138 Ok(OsString
::from_wide(&v
))
143 impl Drop
for OwnedKey
{
145 unsafe { RegCloseKey(self.0); }
149 impl<'a
> Iterator
for Iter
<'a
> {
150 type Item
= io
::Result
<OsString
>;
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 _
,
159 if ret
== ERROR_NO_MORE_ITEMS
as LONG
{
161 } else if ret
!= ERROR_SUCCESS
as LONG
{
162 Some(Err(io
::Error
::from_raw_os_error(ret
as i32)))
164 v
.set_len(len
as usize);
165 Some(Ok(OsString
::from_wide(&v
)))