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