]> git.saurik.com Git - wxWidgets.git/blame - src/msw/registry.cpp
wxImageList ctor now takes the same arguments as the MSW version (but it's
[wxWidgets.git] / src / msw / registry.cpp
CommitLineData
2bda0e17
KB
1///////////////////////////////////////////////////////////////////////////////
2// Name: msw/registry.cpp
3// Purpose: implementation of registry classes and functions
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 03.04.98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows license
10// TODO: - parsing of registry key names
11// - support of other (than REG_SZ/REG_DWORD) registry types
12// - add high level functions (RegisterOleServer, ...)
13///////////////////////////////////////////////////////////////////////////////
14
15// ============================================================================
16// declarations
17// ============================================================================
18
19// ----------------------------------------------------------------------------
20// headers
21// ----------------------------------------------------------------------------
22
23// for compilers that support precompilation, includes "wx.h".
24#include "wx/wxprec.h"
25
26#ifdef __BORLANDC__
27#pragma hdrstop
28#endif
29
30// other wxWindows headers
31#include "wx/string.h"
32#include "wx/intl.h"
33#include "wx/log.h"
34
35// Windows headers
36#define STRICT
37#define WIN32_LEAN_AND_MEAN
38#include <windows.h>
39
40// other std headers
41#include <stdlib.h> // for _MAX_PATH
42
43#ifndef _MAX_PATH
0b1c5a6c 44 #define _MAX_PATH 512
2bda0e17
KB
45#endif
46
47// our header
48#define HKEY_DEFINED // already defined in windows.h
49#include "wx/msw/registry.h"
50
51// some registry functions don't like signed chars
52typedef unsigned char *RegString;
53
54// ----------------------------------------------------------------------------
55// constants
56// ----------------------------------------------------------------------------
57
58// the standard key names, short names and handles all bundled together for
59// convenient access
60static struct
61{
62 HKEY hkey;
63 const char *szName;
64 const char *szShortName;
65}
66aStdKeys[] =
67{
68 { HKEY_CLASSES_ROOT, "HKEY_CLASSES_ROOT", "HKCR" },
69#ifdef __WIN32__
70 { HKEY_CURRENT_USER, "HKEY_CURRENT_USER", "HKCU" },
71 { HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", "HKLM" },
72 { HKEY_USERS, "HKEY_USERS", "HKU" }, // short name?
73 { HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA", "HKPD" },
74#if WINVER >= 0x0400
75 { HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG", "HKCC" },
76#ifndef __GNUWIN32__
77 { HKEY_DYN_DATA, "HKEY_DYN_DATA", "HKDD" }, // short name?
0b1c5a6c 78#endif //GNUWIN32
2bda0e17
KB
79#endif //WINVER >= 4.0
80#endif //WIN32
81};
82
83// the registry name separator (perhaps one day MS will change it to '/' ;-)
84#define REG_SEPARATOR '\\'
85
86// ----------------------------------------------------------------------------
87// macros
88// ----------------------------------------------------------------------------
89// @ const_cast<> is not yet supported by all compilers
90#define CONST_CAST ((wxRegKey *)this)->
91
92#if !USE_MUTABLE
93 #define m_dwLastError CONST_CAST m_dwLastError
94#endif
95
96// ----------------------------------------------------------------------------
97// non member functions
98// ----------------------------------------------------------------------------
99
0b1c5a6c
VZ
100// removes the trailing backslash from the string if it has one
101static inline void RemoveTrailingSeparator(wxString& str);
102
103// returns true if given registry key exists
2bda0e17
KB
104static bool KeyExists(HKEY hRootKey, const char *szKey);
105
106// combines value and key name (uses static buffer!)
107static const char *GetFullName(const wxRegKey *pKey,
108 const char *szValue = NULL);
109
110// ============================================================================
111// implementation of wxRegKey class
112// ============================================================================
113
114// ----------------------------------------------------------------------------
115// static functions and variables
116// ----------------------------------------------------------------------------
117
118const size_t wxRegKey::nStdKeys = WXSIZEOF(aStdKeys);
119
120// @@ should take a `StdKey key', but as it's often going to be used in loops
121// it would require casts in user code.
122const char *wxRegKey::GetStdKeyName(uint key)
123{
124 // return empty string if key is invalid
1311c7a9 125 wxCHECK_MSG( key < nStdKeys, "", "invalid key in wxRegKey::GetStdKeyName" );
2bda0e17
KB
126
127 return aStdKeys[key].szName;
128}
129
130const char *wxRegKey::GetStdKeyShortName(uint key)
131{
132 // return empty string if key is invalid
1311c7a9 133 wxCHECK( key < nStdKeys, "" );
2bda0e17
KB
134
135 return aStdKeys[key].szShortName;
136}
137
138wxRegKey::StdKey wxRegKey::ExtractKeyName(wxString& strKey)
139{
140 wxString strRoot = strKey.Left(REG_SEPARATOR);
141
142 HKEY hRootKey;
143 uint ui;
144 for ( ui = 0; ui < nStdKeys; ui++ ) {
145 if ( strRoot.CmpNoCase(aStdKeys[ui].szName) == 0 ||
146 strRoot.CmpNoCase(aStdKeys[ui].szShortName) == 0 ) {
147 hRootKey = aStdKeys[ui].hkey;
148 break;
149 }
150 }
151
152 if ( ui == nStdKeys ) {
153 wxFAIL_MSG("invalid key prefix in wxRegKey::ExtractKeyName.");
154
155 hRootKey = HKEY_CLASSES_ROOT;
156 }
157 else {
158 strKey = strKey.After(REG_SEPARATOR);
159 if ( !strKey.IsEmpty() && strKey.Last() == REG_SEPARATOR )
160 strKey.Truncate(strKey.Len() - 1);
161 }
162
163 return (wxRegKey::StdKey)(int)hRootKey;
164}
165
166wxRegKey::StdKey wxRegKey::GetStdKeyFromHkey(HKEY hkey)
167{
168 for ( uint ui = 0; ui < nStdKeys; ui++ ) {
169 if ( aStdKeys[ui].hkey == hkey )
170 return (StdKey)ui;
171 }
172
173 wxFAIL_MSG("non root hkey passed to wxRegKey::GetStdKeyFromHkey.");
174
175 return HKCR;
176}
177
178// ----------------------------------------------------------------------------
179// ctors and dtor
180// ----------------------------------------------------------------------------
181
182wxRegKey::wxRegKey()
183{
184 m_hKey = 0;
185 m_hRootKey = aStdKeys[HKCR].hkey;
186 m_dwLastError = 0;
187}
188
189wxRegKey::wxRegKey(const wxString& strKey) : m_strKey(strKey)
190{
191 m_hRootKey = aStdKeys[ExtractKeyName(m_strKey)].hkey;
192 m_hKey = NULL;
193 m_dwLastError = 0;
194}
195
196// parent is a predefined (and preopened) key
197wxRegKey::wxRegKey(StdKey keyParent, const wxString& strKey) : m_strKey(strKey)
198{
0b1c5a6c 199 RemoveTrailingSeparator(m_strKey);
2bda0e17
KB
200 m_hRootKey = aStdKeys[keyParent].hkey;
201 m_hKey = NULL;
202 m_dwLastError = 0;
203}
204
205// parent is a normal regkey
206wxRegKey::wxRegKey(const wxRegKey& keyParent, const wxString& strKey)
207 : m_strKey(keyParent.m_strKey)
208{
209 // combine our name with parent's to get the full name
0b1c5a6c 210 if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR )
2bda0e17
KB
211 m_strKey += REG_SEPARATOR;
212
213 m_strKey += strKey;
0b1c5a6c 214 RemoveTrailingSeparator(m_strKey);
2bda0e17
KB
215
216 m_hRootKey = keyParent.m_hRootKey;
217 m_hKey = NULL;
218 m_dwLastError = 0;
219}
220
221// dtor closes the key releasing system resource
222wxRegKey::~wxRegKey()
223{
224 Close();
225}
226
0b1c5a6c
VZ
227// ----------------------------------------------------------------------------
228// change the key name/hkey
229// ----------------------------------------------------------------------------
230
231// set the full key name
232void wxRegKey::SetName(const wxString& strKey)
233{
234 Close();
235
236 m_strKey = strKey;
237 m_hRootKey = aStdKeys[ExtractKeyName(m_strKey)].hkey;
238}
239
240// the name is relative to the parent key
241void wxRegKey::SetName(StdKey keyParent, const wxString& strKey)
242{
243 Close();
244
245 m_strKey = strKey;
246 RemoveTrailingSeparator(m_strKey);
247 m_hRootKey = aStdKeys[keyParent].hkey;
248}
249
250// the name is relative to the parent key
251void wxRegKey::SetName(const wxRegKey& keyParent, const wxString& strKey)
252{
253 Close();
254
255 // combine our name with parent's to get the full name
256 m_strKey = strKey;
257 if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR )
258 m_strKey += REG_SEPARATOR;
259
260 RemoveTrailingSeparator(m_strKey);
261
262 m_hRootKey = keyParent.m_hRootKey;
263}
264
265// hKey should be opened and will be closed in wxRegKey dtor
266void wxRegKey::SetHkey(HKEY hKey)
267{
268 Close();
269
270 m_hKey = hKey;
271}
272
2bda0e17
KB
273// ----------------------------------------------------------------------------
274// info about the key
275// ----------------------------------------------------------------------------
276
0b1c5a6c 277// returns true if the key exists
2bda0e17
KB
278bool wxRegKey::Exists() const
279{
280 // opened key has to exist, try to open it if not done yet
0b1c5a6c 281 return IsOpened() ? true : KeyExists(m_hRootKey, m_strKey);
2bda0e17
KB
282}
283
284// returns the full name of the key (prefix is abbreviated if bShortPrefix)
285wxString wxRegKey::GetName(bool bShortPrefix) const
286{
287 StdKey key = GetStdKeyFromHkey(m_hRootKey);
288 wxString str = bShortPrefix ? aStdKeys[key].szShortName
289 : aStdKeys[key].szName;
290 if ( !m_strKey.IsEmpty() )
291 str << "\\" << m_strKey;
292
293 return str;
294}
295
296// ----------------------------------------------------------------------------
297// operations
298// ----------------------------------------------------------------------------
299
300// opens key (it's not an error to call Open() on an already opened key)
301bool wxRegKey::Open()
302{
303 if ( IsOpened() )
0b1c5a6c 304 return true;
2bda0e17
KB
305
306 m_dwLastError = RegOpenKey(m_hRootKey, m_strKey, &m_hKey);
307 if ( m_dwLastError != ERROR_SUCCESS ) {
308 wxLogSysError(m_dwLastError, "can't open registry key '%s'",
309 GetName().c_str());
0b1c5a6c 310 return false;
2bda0e17
KB
311 }
312 else
0b1c5a6c 313 return true;
2bda0e17
KB
314}
315
316// creates key, failing if it exists and !bOkIfExists
317bool wxRegKey::Create(bool bOkIfExists)
318{
319 // check for existence only if asked (i.e. order is important!)
320 if ( !bOkIfExists && Exists() ) {
0b1c5a6c 321 return false;
2bda0e17
KB
322 }
323
324 if ( IsOpened() )
0b1c5a6c 325 return true;
2bda0e17
KB
326
327 m_dwLastError = RegCreateKey(m_hRootKey, m_strKey, &m_hKey);
328 if ( m_dwLastError != ERROR_SUCCESS ) {
329 wxLogSysError(m_dwLastError, "can't create registry key '%s'",
330 GetName().c_str());
0b1c5a6c 331 return false;
2bda0e17
KB
332 }
333 else
0b1c5a6c 334 return true;
2bda0e17
KB
335}
336
0b1c5a6c
VZ
337// close the key, it's not an error to call it when not opened
338bool wxRegKey::Close()
339{
340 if ( IsOpened() ) {
341 m_dwLastError = RegCloseKey(m_hKey);
342 if ( m_dwLastError != ERROR_SUCCESS ) {
343 wxLogSysError(m_dwLastError, "can't close registry key '%s'",
344 GetName().c_str());
345
346 m_hKey = 0;
347 return false;
348 }
349 else {
350 m_hKey = 0;
351 }
352 }
353
354 return true;
355}
356
357// ----------------------------------------------------------------------------
358// delete keys/values
359// ----------------------------------------------------------------------------
2bda0e17
KB
360bool wxRegKey::DeleteSelf()
361{
0b1c5a6c
VZ
362 {
363 wxLogNull nolog;
364 if ( !Open() ) {
365 // it already doesn't exist - ok!
366 return TRUE;
367 }
368 }
369
370 // we can't delete keys while enumerating because it confuses GetNextKey, so
371 // we first save the key names and then delete them all
372 wxArrayString astrSubkeys;
2bda0e17
KB
373
374 wxString strKey;
375 long lIndex;
376 bool bCont = GetFirstKey(strKey, lIndex);
377 while ( bCont ) {
0b1c5a6c 378 astrSubkeys.Add(strKey);
2bda0e17
KB
379
380 bCont = GetNextKey(strKey, lIndex);
381 }
382
0b1c5a6c
VZ
383 uint nKeyCount = astrSubkeys.Count();
384 for ( uint nKey = 0; nKey < nKeyCount; nKey++ ) {
385 wxRegKey key(*this, astrSubkeys[nKey]);
386 if ( !key.DeleteSelf() )
387 return FALSE;
388 }
389
390 // now delete this key itself
2bda0e17
KB
391 Close();
392
393 m_dwLastError = RegDeleteKey(m_hRootKey, m_strKey);
394 if ( m_dwLastError != ERROR_SUCCESS ) {
395 wxLogSysError(m_dwLastError, "can't delete key '%s'", GetName().c_str());
396 return FALSE;
397 }
398
399 return TRUE;
400}
401
402bool wxRegKey::DeleteKey(const char *szKey)
403{
404 if ( !Open() )
0b1c5a6c 405 return false;
2bda0e17
KB
406
407 wxRegKey key(*this, szKey);
408 return key.DeleteSelf();
409}
410
411bool wxRegKey::DeleteValue(const char *szValue)
412{
413 if ( !Open() )
0b1c5a6c 414 return false;
2bda0e17
KB
415
416 #ifdef __WIN32__
417 m_dwLastError = RegDeleteValue(m_hKey, szValue);
418 if ( m_dwLastError != ERROR_SUCCESS ) {
419 wxLogSysError(m_dwLastError, "can't delete value '%s' from key '%s'",
420 szValue, GetName().c_str());
0b1c5a6c 421 return false;
2bda0e17
KB
422 }
423 #else //WIN16
424 // named registry values don't exist in Win16 world
425 wxASSERT( IsEmpty(szValue) );
426
427 // just set the (default and unique) value of the key to ""
428 m_dwLastError = RegSetValue(m_hKey, NULL, REG_SZ, "", RESERVED);
429 if ( m_dwLastError != ERROR_SUCCESS ) {
430 wxLogSysError(m_dwLastError, "can't delete value of key '%s'",
431 GetName().c_str());
0b1c5a6c 432 return false;
2bda0e17
KB
433 }
434 #endif //WIN16/32
435
0b1c5a6c 436 return true;
2bda0e17
KB
437}
438
439// ----------------------------------------------------------------------------
440// access to values and subkeys
441// ----------------------------------------------------------------------------
442
0b1c5a6c
VZ
443// return true if value exists
444bool wxRegKey::HasValue(const char *szValue) const
445{
446 #ifdef __WIN32__
447 if ( CONST_CAST Open() ) {
448 return RegQueryValueEx(m_hKey, szValue, RESERVED,
449 NULL, NULL, NULL) == ERROR_SUCCESS;
450 }
451 else
452 return false;
453 #else // WIN16
454 // only unnamed value exists
455 return IsEmpty(szValue);
456 #endif // WIN16/32
457}
458
459// returns true if this key has any subkeys
2bda0e17
KB
460bool wxRegKey::HasSubkeys() const
461{
462 // just call GetFirstKey with dummy parameters
463 wxString str;
464 long l;
465 return CONST_CAST GetFirstKey(str, l);
466}
467
0b1c5a6c 468// returns true if given subkey exists
2bda0e17
KB
469bool wxRegKey::HasSubKey(const char *szKey) const
470{
471 if ( CONST_CAST Open() )
472 return KeyExists(m_hKey, szKey);
473 else
0b1c5a6c 474 return false;
2bda0e17
KB
475}
476
477wxRegKey::ValueType wxRegKey::GetValueType(const char *szValue)
478{
479 #ifdef __WIN32__
480 if ( !Open() )
481 return Type_None;
482
483 DWORD dwType;
484 m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED,
485 &dwType, NULL, NULL);
486 if ( m_dwLastError != ERROR_SUCCESS ) {
487 wxLogSysError(m_dwLastError, "can't read value of key '%s'",
488 GetName().c_str());
489 return Type_None;
490 }
491
492 return (ValueType)dwType;
493 #else //WIN16
494 return IsEmpty(szValue) ? Type_String : Type_None;
495 #endif //WIN16/32
496}
497
498#ifdef __WIN32__
499bool wxRegKey::SetValue(const char *szValue, long lValue)
500{
501 if ( CONST_CAST Open() ) {
502 m_dwLastError = RegSetValueEx(m_hKey, szValue, RESERVED, REG_DWORD,
503 (RegString)&lValue, sizeof(lValue));
504 if ( m_dwLastError == ERROR_SUCCESS )
0b1c5a6c 505 return true;
2bda0e17
KB
506 }
507
508 wxLogSysError(m_dwLastError, "can't set value of '%s'",
509 GetFullName(this, szValue));
0b1c5a6c 510 return false;
2bda0e17
KB
511}
512
513bool wxRegKey::QueryValue(const char *szValue, long *plValue) const
514{
515 if ( CONST_CAST Open() ) {
516 DWORD dwType, dwSize = sizeof(DWORD);
517 RegString pBuf = (RegString)plValue;
518 m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED,
519 &dwType, pBuf, &dwSize);
520 if ( m_dwLastError != ERROR_SUCCESS ) {
521 wxLogSysError(m_dwLastError, "can't read value of key '%s'",
522 GetName().c_str());
0b1c5a6c 523 return false;
2bda0e17
KB
524 }
525 else {
526 // check that we read the value of right type
527 wxASSERT_MSG( dwType == REG_DWORD,
528 "Type mismatch in wxRegKey::QueryValue()." );
529
0b1c5a6c 530 return true;
2bda0e17
KB
531 }
532 }
533 else
0b1c5a6c 534 return false;
2bda0e17
KB
535}
536
537#endif //Win32
538
539bool wxRegKey::QueryValue(const char *szValue, wxString& strValue) const
540{
541 if ( CONST_CAST Open() ) {
542 #ifdef __WIN32__
543 // first get the type and size of the data
544 DWORD dwType, dwSize;
545 m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED,
546 &dwType, NULL, &dwSize);
547 if ( m_dwLastError == ERROR_SUCCESS ) {
548 RegString pBuf = (RegString)strValue.GetWriteBuf(dwSize);
549 m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED,
550 &dwType, pBuf, &dwSize);
551 if ( m_dwLastError == ERROR_SUCCESS ) {
552 // check that it was the right type
553 wxASSERT_MSG( dwType == REG_SZ,
554 "Type mismatch in wxRegKey::QueryValue()." );
555
0b1c5a6c 556 return true;
2bda0e17
KB
557 }
558 }
559 #else //WIN16
560 // named registry values don't exist in Win16
561 wxASSERT( IsEmpty(szValue) );
562
563 m_dwLastError = RegQueryValue(m_hKey, 0, strValue.GetWriteBuf(256), &l);
564 if ( m_dwLastError == ERROR_SUCCESS )
0b1c5a6c 565 return true;
2bda0e17
KB
566 #endif //WIN16/32
567 }
568
569 wxLogSysError(m_dwLastError, "can't read value of '%s'",
570 GetFullName(this, szValue));
0b1c5a6c 571 return false;
2bda0e17
KB
572}
573
574bool wxRegKey::SetValue(const char *szValue, const wxString& strValue)
575{
576 if ( CONST_CAST Open() ) {
577 #ifdef __WIN32__
578 m_dwLastError = RegSetValueEx(m_hKey, szValue, RESERVED, REG_SZ,
579 (RegString)strValue.c_str(),
580 strValue.Len() + 1);
581 if ( m_dwLastError == ERROR_SUCCESS )
0b1c5a6c 582 return true;
2bda0e17
KB
583 #else //WIN16
584 // named registry values don't exist in Win16
585 wxASSERT( IsEmpty(szValue) );
586
587 m_dwLastError = RegSetValue(m_hKey, NULL, REG_SZ, strValue, NULL);
588 if ( m_dwLastError == ERROR_SUCCESS )
0b1c5a6c 589 return true;
2bda0e17
KB
590 #endif //WIN16/32
591 }
592
593 wxLogSysError(m_dwLastError, "can't set value of '%s'",
594 GetFullName(this, szValue));
0b1c5a6c 595 return false;
2bda0e17
KB
596}
597
598wxRegKey::operator wxString() const
599{
600 wxString str;
601 QueryValue(NULL, str);
602 return str;
603}
604
605// ----------------------------------------------------------------------------
606// enumeration
607// NB: all these functions require an index variable which allows to have
608// several concurrently running indexations on the same key
609// ----------------------------------------------------------------------------
610
2bda0e17
KB
611bool wxRegKey::GetFirstValue(wxString& strValueName, long& lIndex)
612{
613 if ( !Open() )
0b1c5a6c 614 return false;
2bda0e17
KB
615
616 lIndex = 0;
0b1c5a6c 617 return GetNextValue(strValueName, lIndex);
2bda0e17
KB
618}
619
620bool wxRegKey::GetNextValue(wxString& strValueName, long& lIndex) const
621{
622 wxASSERT( IsOpened() );
2bda0e17 623
0b1c5a6c
VZ
624 // are we already at the end of enumeration?
625 if ( lIndex == -1 )
626 return false;
2bda0e17 627
0b1c5a6c
VZ
628 #ifdef __WIN32__
629 char szValueName[1024]; // @@ use RegQueryInfoKey...
630 DWORD dwValueLen = WXSIZEOF(szValueName);
2bda0e17 631
0b1c5a6c
VZ
632 lIndex++;
633 m_dwLastError = RegEnumValue(m_hKey, lIndex,
634 szValueName, &dwValueLen,
635 RESERVED,
636 NULL, // [out] type
637 NULL, // [out] buffer for value
638 NULL); // [i/o] it's length
639
640 if ( m_dwLastError != ERROR_SUCCESS ) {
641 if ( m_dwLastError == ERROR_NO_MORE_ITEMS ) {
642 m_dwLastError = ERROR_SUCCESS;
643 lIndex = -1;
644 }
645 else {
646 wxLogSysError(m_dwLastError, "can't enumerate values of key '%s'",
647 GetName().c_str());
648 }
649
650 return false;
2bda0e17
KB
651 }
652
0b1c5a6c
VZ
653 strValueName = szValueName;
654 #else //WIN16
655 // only one unnamed value
656 wxASSERT( lIndex == 0 );
2bda0e17 657
0b1c5a6c
VZ
658 lIndex = -1;
659 strValueName.Empty();
660 #endif
661
662 return true;
2bda0e17 663}
2bda0e17
KB
664
665bool wxRegKey::GetFirstKey(wxString& strKeyName, long& lIndex)
666{
667 if ( !Open() )
0b1c5a6c 668 return false;
2bda0e17 669
2bda0e17 670 lIndex = 0;
0b1c5a6c 671 return GetNextKey(strKeyName, lIndex);
2bda0e17
KB
672}
673
674bool wxRegKey::GetNextKey(wxString& strKeyName, long& lIndex) const
675{
676 wxASSERT( IsOpened() );
0b1c5a6c
VZ
677
678 // are we already at the end of enumeration?
679 if ( lIndex == -1 )
680 return false;
2bda0e17
KB
681
682 char szKeyName[_MAX_PATH + 1];
0b1c5a6c 683 m_dwLastError = RegEnumKey(m_hKey, lIndex++, szKeyName, WXSIZEOF(szKeyName));
2bda0e17
KB
684
685 if ( m_dwLastError != ERROR_SUCCESS ) {
686 if ( m_dwLastError == ERROR_NO_MORE_ITEMS ) {
687 m_dwLastError = ERROR_SUCCESS;
688 lIndex = -1;
689 }
690 else {
691 wxLogSysError(m_dwLastError, "can't enumerate subkeys of key '%s'",
692 GetName().c_str());
693 }
694
0b1c5a6c 695 return false;
2bda0e17
KB
696 }
697
698 strKeyName = szKeyName;
0b1c5a6c 699 return true;
2bda0e17
KB
700}
701
702// ============================================================================
703// implementation of global functions
704// ============================================================================
705bool KeyExists(HKEY hRootKey, const char *szKey)
706{
707 HKEY hkeyDummy;
708 if ( RegOpenKey(hRootKey, szKey, &hkeyDummy) == ERROR_SUCCESS ) {
709 RegCloseKey(hkeyDummy);
0b1c5a6c 710 return true;
2bda0e17
KB
711 }
712 else
0b1c5a6c 713 return false;
2bda0e17
KB
714}
715
716const char *GetFullName(const wxRegKey *pKey, const char *szValue)
717{
718 static wxString s_str;
719 s_str = pKey->GetName();
720 if ( !IsEmpty(szValue) )
721 s_str << "\\" << szValue;
722
723 return s_str.c_str();
0b1c5a6c
VZ
724}
725
726void RemoveTrailingSeparator(wxString& str)
727{
728 if ( !str.IsEmpty() && str.Last() == REG_SEPARATOR )
729 str.Truncate(str.Len() - 1);
730}