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