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