xref: /AOO41X/main/setup_native/source/win32/customactions/reg4msdoc/registryw9x.cxx (revision 32b1fd08cf0851da51c0ed68f50bc63c4ee660e0)
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