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