1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "registry.hxx"
29 
30 #include <Shlwapi.h>
31 #include <assert.h>
32 #include <algorithm>
33 
34 #ifdef _MSC_VER
35 #pragma warning(disable : 4786 4350)
36 #endif
37 
38 //-----------------------------------------------------
39 /** Create instance and open the specified Registry key
40 
41 	@throws  RegistryWriteAccessDenyException
42 			 RegistryAccessDenyException
43 			 RegistryKeyNotFoundException
44 */
45 RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey, const std::wstring& KeyName) :
46 	m_hRootKey(RootKey),
47 	m_hSubKey(0),
48 	m_KeyName(KeyName),
49 	m_IsWriteable(false)
50 {
51 }
52 
53 //-----------------------------------------------------
54 /** Create instance and open the specified Registry key
55 
56 	@throws  RegistryWriteAccessDenyException
57 			 RegistryAccessDenyException
58 			 RegistryKeyNotFoundException
59 */
60 RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey) :
61 	m_hRootKey(RootKey),
62 	m_hSubKey(0),
63 	m_IsWriteable(false)
64 {
65 }
66 
67 //-----------------------------------------------------
68 /** Create an instances of the specified Registry key,
69 	the key is assumed to be already opened.
70 */
71 RegistryKeyImpl::RegistryKeyImpl(HKEY RootKey, HKEY SubKey, const std::wstring& KeyName, bool Writeable) :
72 	m_hRootKey(RootKey),
73 	m_hSubKey(SubKey),
74 	m_KeyName(KeyName),
75 	m_IsWriteable(Writeable)
76 {
77 }
78 
79 //-----------------------------------------------------
80 /**
81 */
82 RegistryKeyImpl::~RegistryKeyImpl()
83 {
84 	if (IsOpen())
85 		Close();
86 }
87 
88 
89 //############################################
90 // Queries
91 //############################################
92 
93 
94 //-----------------------------------------------------
95 /** The name of the key at hand, maybe empty
96 	if this is any of the root keys
97 */
98 std::wstring RegistryKeyImpl::GetName() const
99 {
100 	return m_KeyName;
101 }
102 
103 //-----------------------------------------------------
104 /**
105 */
106 bool RegistryKeyImpl::IsOpen() const
107 {
108 	return m_hSubKey != 0;
109 }
110 
111 //-----------------------------------------------------
112 /** Is this one of the root keys
113 	HKEY_CLASSES_ROOT
114 	HKEY_CURRENT_USER
115 	etc.
116 */
117 bool RegistryKeyImpl::IsRootKey() const
118 {
119 	return (0 == m_KeyName.length());
120 }
121 
122 //-----------------------------------------------------
123 /** Do we have write access on the key at hand
124 */
125 bool RegistryKeyImpl::IsWriteable() const
126 {
127 	return m_IsWriteable;
128 }
129 
130 //-----------------------------------------------------
131 /** Convenience function to determine if the
132 	Registry key at hand has the specified
133 	value
134 
135 	@precond IsOpen = true
136 
137 	throws RegistryAccessDenyException
138 */
139 bool RegistryKeyImpl::HasValue(const std::wstring& Name) const
140 {
141 	StringListPtr names = GetSubValueNames();
142 
143 	StringList::iterator iter_end = names->end();
144 	StringList::iterator iter = std::find(names->begin(), iter_end, Name);
145 
146 	return (iter != iter_end);
147 }
148 
149 struct CompareNamesCaseInsensitive
150 {
151 	CompareNamesCaseInsensitive(const std::wstring& Name) :
152 		name_(Name)
153 	{}
154 
155 	bool operator() (const std::wstring& value)
156 	{
157 		return (0 == StrCmpI(value.c_str(), name_.c_str()));
158 	}
159 
160 	std::wstring name_;
161 };
162 
163 //-----------------------------------------------------
164 /** Convenience function to determine if the
165 	Registry key at hand has the specified
166 	sub-key
167 
168 	@precond IsOpen = true
169 
170 	throws RegistryAccessDenyException
171 */
172 bool RegistryKeyImpl::HasSubKey(const std::wstring& Name) const
173 {
174 	StringListPtr names = GetSubKeyNames();
175 
176 	StringList::iterator iter_end = names->end();
177 	StringList::iterator iter = std::find_if(names->begin(), iter_end, CompareNamesCaseInsensitive(Name));
178 
179 	return (iter != iter_end);
180 }
181 
182 //-----------------------------------------------------
183 /**
184 */
185 void RegistryKeyImpl::Close()
186 {
187 	if (RegCloseKey(m_hSubKey) != ERROR_SUCCESS) {
188         assert(false);
189     }
190 
191 	m_hSubKey = 0;
192 	m_IsWriteable = false;
193 }
194 
195 //-----------------------------------------------------
196 /** Copies the specified value from RegistryKey to
197 	the registry key at hand, if a value with this
198 	name already exist under the registry key at hand
199 	it will be overwritten
200 
201 	@precond IsOpen = true
202 			 IsWriteable = true
203 			 RegistryKey.HasSubValue(Name) = true
204 
205 	@throws RegistryIOException
206 			RegistryWriteAccessDeniedException
207 			RegistryValueNotFoundException
208 */
209 void RegistryKeyImpl::CopyValue(const RegistryKey& RegistryKey, const std::wstring& Name)
210 {
211 	assert(RegistryKey->HasValue(Name));
212 #ifdef __MINGW32__
213 	SetValue((const RegistryValue&)(RegistryKey->GetValue(Name)));
214 #else
215 	SetValue(RegistryKey->GetValue(Name));
216 #endif
217     assert(HasValue(Name));
218 }
219 
220 /** Copies the specified value from RegistryKey to
221 	the registry key at hand under a new name,
222 	if a value with this name already exist there
223 	it will be overwritten
224 
225 	@precond IsOpen = true
226 			 IsWriteable = true
227 			 RegistryKey.HasSubValue(Name) = true
228 
229 	@throws RegistryIOException
230 			RegistryWriteAccessDeniedException
231 			RegistryValueNotFoundException
232 */
233 void RegistryKeyImpl::CopyValue(const RegistryKey& RegistryKey, const std::wstring& Name, const std::wstring& NewName)
234 {
235 	assert(RegistryKey->HasValue(Name));
236 
237 	RegistryValue RegVal = RegistryKey->GetValue(Name);
238 	RegVal->SetName(NewName);
239 	SetValue(RegVal);
240 
241     assert(HasValue(NewName));
242 }
243