1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "registry.hxx"
25
26 #include <Shlwapi.h>
27 #include <assert.h>
28 #include <algorithm>
29
30 #ifdef _MSC_VER
31 #pragma warning(disable : 4786 4350)
32 #endif
33
34 //-----------------------------------------------------
35 /** Create instance and open the specified Registry key
36
37 @throws RegistryWriteAccessDenyException
38 RegistryAccessDenyException
39 RegistryKeyNotFoundException
40 */
RegistryKeyImpl(HKEY RootKey,const std::wstring & KeyName)41 RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey, const std::wstring& KeyName) :
42 m_hRootKey(RootKey),
43 m_hSubKey(0),
44 m_KeyName(KeyName),
45 m_IsWriteable(false)
46 {
47 }
48
49 //-----------------------------------------------------
50 /** Create instance and open the specified Registry key
51
52 @throws RegistryWriteAccessDenyException
53 RegistryAccessDenyException
54 RegistryKeyNotFoundException
55 */
RegistryKeyImpl(HKEY RootKey)56 RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey) :
57 m_hRootKey(RootKey),
58 m_hSubKey(0),
59 m_IsWriteable(false)
60 {
61 }
62
63 //-----------------------------------------------------
64 /** Create an instances of the specified Registry key,
65 the key is assumed to be already opened.
66 */
RegistryKeyImpl(HKEY RootKey,HKEY SubKey,const std::wstring & KeyName,bool Writeable)67 RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey, HKEY SubKey, const std::wstring& KeyName, bool Writeable) :
68 m_hRootKey(RootKey),
69 m_hSubKey(SubKey),
70 m_KeyName(KeyName),
71 m_IsWriteable(Writeable)
72 {
73 }
74
75 //-----------------------------------------------------
76 /**
77 */
~RegistryKeyImpl()78 RegistryKeyImpl::~RegistryKeyImpl()
79 {
80 if (IsOpen())
81 Close();
82 }
83
84
85 //############################################
86 // Queries
87 //############################################
88
89
90 //-----------------------------------------------------
91 /** The name of the key at hand, maybe empty
92 if this is any of the root keys
93 */
GetName() const94 std::wstring RegistryKeyImpl::GetName() const
95 {
96 return m_KeyName;
97 }
98
99 //-----------------------------------------------------
100 /**
101 */
IsOpen() const102 bool RegistryKeyImpl::IsOpen() const
103 {
104 return m_hSubKey != 0;
105 }
106
107 //-----------------------------------------------------
108 /** Is this one of the root keys
109 HKEY_CLASSES_ROOT
110 HKEY_CURRENT_USER
111 etc.
112 */
IsRootKey() const113 bool RegistryKeyImpl::IsRootKey() const
114 {
115 return (0 == m_KeyName.length());
116 }
117
118 //-----------------------------------------------------
119 /** Do we have write access on the key at hand
120 */
IsWriteable() const121 bool RegistryKeyImpl::IsWriteable() const
122 {
123 return m_IsWriteable;
124 }
125
126 //-----------------------------------------------------
127 /** Convenience function to determine if the
128 Registry key at hand has the specified
129 value
130
131 @precond IsOpen = true
132
133 throws RegistryAccessDenyException
134 */
HasValue(const std::wstring & Name) const135 bool RegistryKeyImpl::HasValue(const std::wstring& Name) const
136 {
137 StringListPtr names = GetSubValueNames();
138
139 StringList::iterator iter_end = names->end();
140 StringList::iterator iter = std::find(names->begin(), iter_end, Name);
141
142 return (iter != iter_end);
143 }
144
145 struct CompareNamesCaseInsensitive
146 {
CompareNamesCaseInsensitiveCompareNamesCaseInsensitive147 CompareNamesCaseInsensitive(const std::wstring& Name) :
148 name_(Name)
149 {}
150
operator ()CompareNamesCaseInsensitive151 bool operator() (const std::wstring& value)
152 {
153 return (0 == StrCmpI(value.c_str(), name_.c_str()));
154 }
155
156 std::wstring name_;
157 };
158
159 //-----------------------------------------------------
160 /** Convenience function to determine if the
161 Registry key at hand has the specified
162 sub-key
163
164 @precond IsOpen = true
165
166 throws RegistryAccessDenyException
167 */
HasSubKey(const std::wstring & Name) const168 bool RegistryKeyImpl::HasSubKey(const std::wstring& Name) const
169 {
170 StringListPtr names = GetSubKeyNames();
171
172 StringList::iterator iter_end = names->end();
173 StringList::iterator iter = std::find_if(names->begin(), iter_end, CompareNamesCaseInsensitive(Name));
174
175 return (iter != iter_end);
176 }
177
178 //-----------------------------------------------------
179 /**
180 */
Close()181 void RegistryKeyImpl::Close()
182 {
183 if (RegCloseKey(m_hSubKey) != ERROR_SUCCESS) {
184 assert(false);
185 }
186
187 m_hSubKey = 0;
188 m_IsWriteable = false;
189 }
190
191 //-----------------------------------------------------
192 /** Copies the specified value from RegistryKey to
193 the registry key at hand, if a value with this
194 name already exist under the registry key at hand
195 it will be overwritten
196
197 @precond IsOpen = true
198 IsWriteable = true
199 RegistryKey.HasSubValue(Name) = true
200
201 @throws RegistryIOException
202 RegistryWriteAccessDeniedException
203 RegistryValueNotFoundException
204 */
CopyValue(const RegistryKey & RegistryKey,const std::wstring & Name)205 void RegistryKeyImpl::CopyValue(const RegistryKey& RegistryKey, const std::wstring& Name)
206 {
207 assert(RegistryKey->HasValue(Name));
208 #ifdef __MINGW32__
209 SetValue((const RegistryValue&)(RegistryKey->GetValue(Name)));
210 #else
211 SetValue(RegistryKey->GetValue(Name));
212 #endif
213 assert(HasValue(Name));
214 }
215
216 /** Copies the specified value from RegistryKey to
217 the registry key at hand under a new name,
218 if a value with this name already exist there
219 it will be overwritten
220
221 @precond IsOpen = true
222 IsWriteable = true
223 RegistryKey.HasSubValue(Name) = true
224
225 @throws RegistryIOException
226 RegistryWriteAccessDeniedException
227 RegistryValueNotFoundException
228 */
CopyValue(const RegistryKey & RegistryKey,const std::wstring & Name,const std::wstring & NewName)229 void RegistryKeyImpl::CopyValue(const RegistryKey& RegistryKey, const std::wstring& Name, const std::wstring& NewName)
230 {
231 assert(RegistryKey->HasValue(Name));
232
233 RegistryValue RegVal = RegistryKey->GetValue(Name);
234 RegVal->SetName(NewName);
235 SetValue(RegVal);
236
237 assert(HasValue(NewName));
238 }
239