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 //---------------------------------------
25 //
26 //---------------------------------------
27
28 #include "registryw9x.hxx"
29
30 #include <windows.h>
31 #include <malloc.h>
32 #include "registryvalueimpl.hxx"
33 #include "registryexception.hxx"
34 #include "stringconverter.hxx"
35
36 #include <assert.h>
37
38 #ifdef _MSC_VER
39 #pragma warning(disable : 4786 4350)
40 #endif
41
42 //---------------------------------------
43 //
44 //---------------------------------------
45
46 const size_t MAX_TMP_BUFF_SIZE = 1024 * sizeof(wchar_t);
47
48
49 //############################################
50 // Creation
51 // only possible through WindowsRegistry class
52 //############################################
53
54
55 //-----------------------------------------------------
56 /** Create instance and open the specified Registry key
57 */
RegistryKeyImplWin9x(HKEY RootKey,const std::wstring & KeyName)58 RegistryKeyImplWin9x::RegistryKeyImplWin9x(HKEY RootKey, const std::wstring& KeyName) :
59 RegistryKeyImpl(RootKey, KeyName)
60 {
61 }
62
63 //-----------------------------------------------------
64 /** Create instance and open the specified Registry key
65 */
RegistryKeyImplWin9x(HKEY RootKey)66 RegistryKeyImplWin9x::RegistryKeyImplWin9x(HKEY RootKey) :
67 RegistryKeyImpl(RootKey)
68 {
69 }
70
71 //-----------------------------------------------------
72 /** Create an instances of the specified Registry key,
73 the key is assumed to be already opened.
74 */
RegistryKeyImplWin9x(HKEY RootKey,HKEY SubKey,const std::wstring & KeyName,bool Writeable)75 RegistryKeyImplWin9x::RegistryKeyImplWin9x(HKEY RootKey, HKEY SubKey, const std::wstring& KeyName, bool Writeable) :
76 RegistryKeyImpl(RootKey, SubKey, KeyName, Writeable)
77 {
78 }
79
80
81 //############################################
82 // Queries
83 //############################################
84
85
86 //-----------------------------------------------------
87 /** The number of sub values of the key at hand
88
89 @precond IsOpen = true
90
91 @throws
92 */
GetSubValueCount() const93 size_t RegistryKeyImplWin9x::GetSubValueCount() const
94 {
95 assert(IsOpen());
96
97 DWORD nSubValues = 0;
98
99 LONG rc = RegQueryInfoKeyA(
100 m_hSubKey,
101 0, 0, 0, 0, 0, 0, &nSubValues, 0, 0, 0, 0);
102
103 if (ERROR_INVALID_HANDLE == rc)
104 throw RegistryIOException(rc);
105 else if (ERROR_SUCCESS != rc)
106 throw RegistryException(rc);
107
108 return nSubValues;
109 }
110
111 //-----------------------------------------------------
112 /** The number of sub-keys of the key at hand
113
114 @precond IsOpen = true
115
116 @throws
117 */
GetSubKeyCount() const118 size_t RegistryKeyImplWin9x::GetSubKeyCount() const
119 {
120 assert(IsOpen());
121
122 DWORD nSubKeys = 0;
123
124 LONG rc = RegQueryInfoKeyA(
125 m_hSubKey,
126 0, 0, 0, &nSubKeys, 0, 0, 0, 0, 0, 0, 0);
127
128 if (ERROR_INVALID_HANDLE == rc)
129 throw RegistryIOException(rc);
130 else if (ERROR_SUCCESS != rc)
131 throw RegistryException(rc);
132
133 return nSubKeys;
134 }
135
136 //-----------------------------------------------------
137 /**
138 */
GetSubKeyNames() const139 StringListPtr RegistryKeyImplWin9x::GetSubKeyNames() const
140 {
141 assert(IsOpen());
142
143 char buff[1024];
144 DWORD buff_size = sizeof(buff);
145 FILETIME ftime;
146
147 StringList* key_names = new StringList();
148
149 LONG rc = ERROR_SUCCESS;
150
151 for (DWORD i = 0; /* left empty */; i++)
152 {
153 rc = RegEnumKeyExA(
154 m_hSubKey, i, buff, &buff_size,
155 0, 0, 0, &ftime);
156
157 if (ERROR_SUCCESS != rc &&
158 ERROR_MORE_DATA != rc)
159 break;
160
161 buff_size = sizeof(buff);
162
163 key_names->push_back(AnsiToUnicodeString(buff));
164 }
165
166 if (ERROR_INVALID_HANDLE == rc)
167 throw RegistryIOException(rc);
168 else if (ERROR_NO_MORE_ITEMS != rc && ERROR_SUCCESS != rc)
169 throw RegistryException(rc);
170
171 return (StringListPtr) key_names;
172 }
173
174 //-----------------------------------------------------
175 /**
176 */
GetSubValueNames() const177 StringListPtr RegistryKeyImplWin9x::GetSubValueNames() const
178 {
179 assert(IsOpen());
180
181 char buff[1024];
182 DWORD buff_size = sizeof(buff);
183
184 StringList* value_names = new StringList();
185
186 LONG rc = ERROR_SUCCESS;
187
188 for (DWORD i = 0; /* left empty */; i++)
189 {
190 rc = RegEnumValueA(
191 m_hSubKey, i, buff, &buff_size,
192 0, 0, 0, 0);
193
194 if (ERROR_SUCCESS != rc &&
195 ERROR_MORE_DATA != rc)
196 break;
197
198 buff_size = sizeof(buff);
199
200 value_names->push_back(AnsiToUnicodeString(buff));
201 }
202
203 if (ERROR_INVALID_HANDLE == rc)
204 throw RegistryIOException(rc);
205 else if (ERROR_NO_MORE_ITEMS != rc && ERROR_SUCCESS != rc)
206 throw RegistryException(rc);
207
208 return (StringListPtr) value_names;
209 }
210
211 //-----------------------------------------------------
212 /** Get the specified registry value
213
214 @precond IsOpen = true
215 */
GetValue(const std::wstring & Name) const216 RegistryValue RegistryKeyImplWin9x::GetValue(const std::wstring& Name) const
217 {
218 assert(IsOpen());
219
220 DWORD Type;
221 char buff[MAX_TMP_BUFF_SIZE];
222 DWORD size = sizeof(buff);
223
224 LONG rc = RegQueryValueExA(
225 m_hSubKey,
226 UnicodeToAnsiString(Name).c_str(),
227 0,
228 &Type,
229 reinterpret_cast<LPBYTE>(buff),
230 &size);
231
232 if (ERROR_FILE_NOT_FOUND == rc)
233 throw RegistryValueNotFoundException(rc);
234 else if (ERROR_ACCESS_DENIED == rc)
235 throw RegistryAccessDeniedException(rc);
236 else if (ERROR_SUCCESS != rc)
237 throw RegistryException(rc);
238
239 RegistryValue regval;
240
241 if (REG_DWORD == Type)
242 {
243 regval = RegistryValue(new RegistryValueImpl(Name, *(reinterpret_cast<int*>(buff))));
244 }
245 else if (REG_SZ == Type || REG_EXPAND_SZ == Type || REG_MULTI_SZ == Type)
246 {
247 if (size > 0)
248 regval = RegistryValue(new RegistryValueImpl(Name, std::string(reinterpret_cast<char*>(buff))));
249 else
250 regval = RegistryValue(new RegistryValueImpl(Name, std::string()));
251 }
252 else
253 {
254 assert(false);
255 }
256
257 return regval;
258 }
259
260 //-----------------------------------------------------
261 /** Get the specified registry value, return the given
262 default value if value not found
263
264 @precond IsOpen = true
265 */
GetValue(const std::wstring & Name,const RegistryValue & Default) const266 RegistryValue RegistryKeyImplWin9x::GetValue(const std::wstring& Name, const RegistryValue& Default) const
267 {
268 assert(IsOpen());
269
270 DWORD Type;
271 char buff[MAX_TMP_BUFF_SIZE];
272 DWORD size = sizeof(buff);
273
274 LONG rc = RegQueryValueExA(
275 m_hSubKey,
276 UnicodeToAnsiString(Name).c_str(),
277 0,
278 &Type,
279 reinterpret_cast<LPBYTE>(buff),
280 &size);
281
282 if (ERROR_FILE_NOT_FOUND == rc)
283 {
284 #if !defined(__MINGW32__) && (_MSC_VER < 1300)
285 return Default;
286 #else
287 RegistryValue regval_ptr;
288 regval_ptr = RegistryValue(new RegistryValueImpl(*Default));
289 return regval_ptr;
290 #endif
291 }
292
293 if (ERROR_ACCESS_DENIED == rc)
294 throw RegistryAccessDeniedException(rc);
295 else if (ERROR_SUCCESS != rc)
296 throw RegistryException(rc);
297
298 RegistryValue regval;
299
300 if (REG_DWORD == Type)
301 regval = RegistryValue(new RegistryValueImpl(Name, *reinterpret_cast<int*>(buff)));
302 else if (REG_SZ == Type || REG_EXPAND_SZ == Type || REG_MULTI_SZ == Type)
303 regval = RegistryValue(new RegistryValueImpl(Name, std::string(reinterpret_cast<char*>(buff))));
304 else
305 assert(false);
306
307 return regval;
308 }
309
310
311 //############################################
312 // Commands
313 //############################################
314
315
316 //-----------------------------------------------------
317 /** Open the registry key, has no effect if
318 the key is already open
319
320 @precond IsOpen = false
321
322 @throws RegistryKeyNotFoundException
323 RegistryWriteAccessDenyException
324 RegistryAccessDenyException
325 */
Open(bool Writeable)326 void RegistryKeyImplWin9x::Open(bool Writeable)
327 {
328 assert(!IsOpen());
329
330 REGSAM regsam = KEY_READ;
331
332 if (Writeable)
333 regsam |= KEY_WRITE;
334
335 LONG rc = RegOpenKeyExA(
336 m_hRootKey,
337 UnicodeToAnsiString(m_KeyName).c_str(),
338 0,
339 regsam,
340 &m_hSubKey);
341
342 if (ERROR_FILE_NOT_FOUND == rc)
343 throw RegistryKeyNotFoundException(rc);
344 else if (ERROR_ACCESS_DENIED == rc)
345 throw RegistryAccessDeniedException(rc);
346 else if (ERROR_SUCCESS != rc)
347 throw RegistryException(rc);
348
349 m_IsWriteable = Writeable;
350
351 assert(IsOpen());
352 }
353
354 //-----------------------------------------------------
355 /** Open the specified sub-key of the registry key
356 at hand
357
358 @precond IsOpen = true
359 HasSubKey(Name) = true
360
361 @throws RegistryIOException
362 RegistryKeyNotFoundException
363 RegistryAccessDeniedException
364 */
OpenSubKey(const std::wstring & Name,bool Writeable)365 RegistryKey RegistryKeyImplWin9x::OpenSubKey(const std::wstring& Name, bool Writeable)
366 {
367 RegistryKey regkey(new RegistryKeyImplWin9x(m_hSubKey, Name));
368 regkey->Open(Writeable);
369 return regkey;
370 }
371
372 //-----------------------------------------------------
373 /** Creates a new sub-key below the key at hand
374
375 @precond IsOpen = true
376 IsWriteable = true
377
378 @throws RegistryIOException
379 RegistryWriteAccessDenyException
380 */
381
CreateSubKey(const std::wstring & Name)382 RegistryKey RegistryKeyImplWin9x::CreateSubKey(const std::wstring& Name)
383 {
384 assert(IsOpen());
385 assert(IsWriteable());
386
387 HKEY hRoot = IsRootKey() ? m_hRootKey : m_hSubKey;
388
389 HKEY hKey;
390
391 LONG rc = RegCreateKeyExA(
392 hRoot,
393 UnicodeToAnsiString(Name).c_str(),
394 0,
395 0,
396 REG_OPTION_NON_VOLATILE,
397 KEY_READ | KEY_WRITE,
398 0,
399 &hKey,
400 0);
401
402 if (ERROR_INVALID_HANDLE == rc)
403 throw RegistryIOException(rc);
404 else if (ERROR_ACCESS_DENIED == rc)
405 throw RegistryAccessDeniedException(rc);
406 else if (ERROR_SUCCESS != rc)
407 throw RegistryException(rc);
408
409 return RegistryKey(new RegistryKeyImplWin9x(hRoot, hKey, Name));
410 }
411
412 //-----------------------------------------------------
413 /** Deletes a sub-key below the key at hand, the
414 key must not have sub-keys
415
416 @precond IsOpen = true
417 IsWriteable = true
418
419 @throws RegistryIOException
420 RegistryWriteAccessDenyException
421 */
DeleteSubKey(const std::wstring & Name)422 void RegistryKeyImplWin9x::DeleteSubKey(const std::wstring& Name)
423 {
424 assert(IsOpen());
425 assert(IsWriteable());
426 assert(HasSubKey(Name));
427
428 RegistryKey SubKey = OpenSubKey(Name);
429
430 size_t nSubKeyCount = SubKey->GetSubKeyCount();
431
432 assert(0 == nSubKeyCount);
433
434 if (nSubKeyCount)
435 throw RegistryInvalidOperationException(ERROR_NOT_SUPPORTED);
436
437 LONG rc = RegDeleteKeyA(m_hSubKey, UnicodeToAnsiString(Name).c_str());
438
439 if (ERROR_INVALID_HANDLE == rc)
440 throw RegistryIOException(rc);
441 else if (ERROR_ACCESS_DENIED == rc)
442 throw RegistryAccessDeniedException(rc);
443 else if (ERROR_SUCCESS != rc)
444 throw RegistryException(rc);
445 }
446
447 //-----------------------------------------------------
448 /** Deletes a sub-key below the key at hand with all
449 its sub-keys
450
451 @precond IsOpen = true
452 IsWriteable = true;
453
454 @throws RegistryIOException
455 RegistryWriteAccessDenyException
456 */
DeleteSubKeyTree(const std::wstring & Name)457 void RegistryKeyImplWin9x::DeleteSubKeyTree(const std::wstring& Name)
458 {
459 LONG rc = RegDeleteKeyA(m_hSubKey, UnicodeToAnsiString(Name).c_str());
460
461 if (ERROR_INVALID_HANDLE == rc)
462 throw RegistryIOException(rc);
463 else if (ERROR_ACCESS_DENIED == rc)
464 throw RegistryAccessDeniedException(rc);
465 else if (ERROR_SUCCESS != rc)
466 throw RegistryException(rc);
467 }
468
469 //-----------------------------------------------------
470 /** Delete the specified value
471
472 @precond IsOpen = true
473 IsWriteable = true
474 HasValue(Name) = true
475
476 @throws RegistryIOException
477 RegistryWriteAccessDeniedException
478 RegistryValueNotFoundException
479 */
DeleteValue(const std::wstring & Name)480 void RegistryKeyImplWin9x::DeleteValue(const std::wstring& Name)
481 {
482 assert(IsOpen());
483 assert(HasValue(Name));
484 assert(IsWriteable());
485
486 LONG rc = RegDeleteValueA(
487 m_hSubKey,
488 UnicodeToAnsiString(Name).c_str());
489
490 if (ERROR_INVALID_HANDLE == rc)
491 throw RegistryIOException(rc);
492 else if (ERROR_ACCESS_DENIED == rc)
493 throw RegistryNoWriteAccessException(rc);
494 else if (ERROR_FILE_NOT_FOUND == rc)
495 throw RegistryValueNotFoundException(rc);
496 else if (ERROR_SUCCESS != rc)
497 throw RegistryException(rc);
498 }
499
500 //-----------------------------------------------------
501 /** Set the specified registry value
502
503 @precond IsOpen = true
504 IsWriteable = true
505
506 @throws RegistryIOException
507 RegistryWriteAccessDenyException
508 */
SetValue(const RegistryValue & Value)509 void RegistryKeyImplWin9x::SetValue(const RegistryValue& Value)
510 {
511 assert(IsOpen());
512 assert(IsWriteable());
513
514 LONG rc = ERROR_SUCCESS;
515
516 if (REG_SZ == Value->GetType())
517 {
518 std::string AnsiStr = Value->GetDataAsAnsiString();
519
520 rc = RegSetValueExA(
521 m_hSubKey,
522 UnicodeToAnsiString(Value->GetName()).c_str(),
523 0,
524 Value->GetType(),
525 reinterpret_cast<const unsigned char*>(AnsiStr.c_str()),
526 static_cast<DWORD>((AnsiStr.length() + 1)));
527 }
528 else
529 {
530 rc = RegSetValueExA(
531 m_hSubKey,
532 UnicodeToAnsiString(Value->GetName()).c_str(),
533 0,
534 Value->GetType(),
535 reinterpret_cast<const unsigned char*>(Value->GetDataBuffer()),
536 static_cast<DWORD>(Value->GetDataSize()));
537 }
538
539 if (ERROR_INVALID_HANDLE == rc)
540 throw RegistryIOException(rc);
541 else if (ERROR_ACCESS_DENIED == rc)
542 throw RegistryAccessDeniedException(rc);
543 else if (ERROR_SUCCESS != rc)
544 throw RegistryException(rc);
545 }
546
547