]> git.saurik.com Git - wxWidgets.git/blame - src/msw/registry.cpp
VZ: I removed (CASTWNDPROC) from ::CallWndProc - it doesn't compile here with it
[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
02569ba8 259 m_strKey = keyParent.m_strKey;
0b1c5a6c
VZ
260 if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR )
261 m_strKey += REG_SEPARATOR;
02569ba8 262 m_strKey += strKey;
0b1c5a6c
VZ
263
264 RemoveTrailingSeparator(m_strKey);
265
266 m_hRootKey = keyParent.m_hRootKey;
267}
268
269// hKey should be opened and will be closed in wxRegKey dtor
270void wxRegKey::SetHkey(HKEY hKey)
271{
272 Close();
273
274 m_hKey = hKey;
275}
276
2bda0e17
KB
277// ----------------------------------------------------------------------------
278// info about the key
279// ----------------------------------------------------------------------------
280
cf447356 281// returns TRUE if the key exists
2bda0e17
KB
282bool wxRegKey::Exists() const
283{
284 // opened key has to exist, try to open it if not done yet
cf447356 285 return IsOpened() ? TRUE : KeyExists(m_hRootKey, m_strKey);
2bda0e17
KB
286}
287
288// returns the full name of the key (prefix is abbreviated if bShortPrefix)
289wxString wxRegKey::GetName(bool bShortPrefix) const
290{
291 StdKey key = GetStdKeyFromHkey(m_hRootKey);
292 wxString str = bShortPrefix ? aStdKeys[key].szShortName
293 : aStdKeys[key].szName;
294 if ( !m_strKey.IsEmpty() )
295 str << "\\" << m_strKey;
296
297 return str;
298}
299
02569ba8
VZ
300bool wxRegKey::GetKeyInfo(ulong *pnSubKeys,
301 ulong *pnMaxKeyLen,
302 ulong *pnValues,
303 ulong *pnMaxValueLen) const
304{
305#ifdef __WIN32__
306 m_dwLastError = ::RegQueryInfoKey
307 (
308 m_hKey,
309 NULL, // class name
310 NULL, // (ptr to) size of class name buffer
311 RESERVED,
312 pnSubKeys, // [out] number of subkeys
313 pnMaxKeyLen, // [out] max length of a subkey name
314 NULL, // longest subkey class name
315 pnValues, // [out] number of values
316 pnMaxValueLen, // [out] max length of a value name
317 NULL, // longest value data
318 NULL, // security descriptor
319 NULL // time of last modification
320 );
321
322 if ( m_dwLastError != ERROR_SUCCESS ) {
323 wxLogSysError(m_dwLastError, _("can't get info about registry key '%s'"),
324 GetName().c_str());
325 return FALSE;
326 }
327 else
328 return TRUE;
329#else // Win16
330 wxFAIL_MSG("GetKeyInfo() not implemented");
331
332 return FALSE;
333#endif
334}
335
2bda0e17
KB
336// ----------------------------------------------------------------------------
337// operations
338// ----------------------------------------------------------------------------
339
340// opens key (it's not an error to call Open() on an already opened key)
341bool wxRegKey::Open()
342{
343 if ( IsOpened() )
cf447356 344 return TRUE;
2bda0e17
KB
345
346 m_dwLastError = RegOpenKey(m_hRootKey, m_strKey, &m_hKey);
347 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 348 wxLogSysError(m_dwLastError, _("can't open registry key '%s'"),
2bda0e17 349 GetName().c_str());
cf447356 350 return FALSE;
2bda0e17
KB
351 }
352 else
cf447356 353 return TRUE;
2bda0e17
KB
354}
355
356// creates key, failing if it exists and !bOkIfExists
357bool wxRegKey::Create(bool bOkIfExists)
358{
359 // check for existence only if asked (i.e. order is important!)
360 if ( !bOkIfExists && Exists() ) {
cf447356 361 return FALSE;
2bda0e17
KB
362 }
363
364 if ( IsOpened() )
cf447356 365 return TRUE;
2bda0e17
KB
366
367 m_dwLastError = RegCreateKey(m_hRootKey, m_strKey, &m_hKey);
368 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 369 wxLogSysError(m_dwLastError, _("can't create registry key '%s'"),
2bda0e17 370 GetName().c_str());
cf447356 371 return FALSE;
2bda0e17
KB
372 }
373 else
cf447356 374 return TRUE;
2bda0e17
KB
375}
376
0b1c5a6c
VZ
377// close the key, it's not an error to call it when not opened
378bool wxRegKey::Close()
379{
380 if ( IsOpened() ) {
381 m_dwLastError = RegCloseKey(m_hKey);
382 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 383 wxLogSysError(m_dwLastError, _("can't close registry key '%s'"),
0b1c5a6c
VZ
384 GetName().c_str());
385
386 m_hKey = 0;
cf447356 387 return FALSE;
0b1c5a6c
VZ
388 }
389 else {
390 m_hKey = 0;
391 }
392 }
393
cf447356 394 return TRUE;
0b1c5a6c
VZ
395}
396
397// ----------------------------------------------------------------------------
398// delete keys/values
399// ----------------------------------------------------------------------------
2bda0e17
KB
400bool wxRegKey::DeleteSelf()
401{
0b1c5a6c
VZ
402 {
403 wxLogNull nolog;
404 if ( !Open() ) {
405 // it already doesn't exist - ok!
406 return TRUE;
407 }
408 }
409
410 // we can't delete keys while enumerating because it confuses GetNextKey, so
411 // we first save the key names and then delete them all
412 wxArrayString astrSubkeys;
2bda0e17
KB
413
414 wxString strKey;
415 long lIndex;
416 bool bCont = GetFirstKey(strKey, lIndex);
417 while ( bCont ) {
0b1c5a6c 418 astrSubkeys.Add(strKey);
2bda0e17
KB
419
420 bCont = GetNextKey(strKey, lIndex);
421 }
422
0b1c5a6c
VZ
423 uint nKeyCount = astrSubkeys.Count();
424 for ( uint nKey = 0; nKey < nKeyCount; nKey++ ) {
425 wxRegKey key(*this, astrSubkeys[nKey]);
426 if ( !key.DeleteSelf() )
427 return FALSE;
428 }
429
430 // now delete this key itself
2bda0e17
KB
431 Close();
432
433 m_dwLastError = RegDeleteKey(m_hRootKey, m_strKey);
434 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8
VZ
435 wxLogSysError(m_dwLastError, _("can't delete key '%s'"),
436 GetName().c_str());
2bda0e17
KB
437 return FALSE;
438 }
439
440 return TRUE;
441}
442
443bool wxRegKey::DeleteKey(const char *szKey)
444{
445 if ( !Open() )
cf447356 446 return FALSE;
2bda0e17
KB
447
448 wxRegKey key(*this, szKey);
449 return key.DeleteSelf();
450}
451
452bool wxRegKey::DeleteValue(const char *szValue)
453{
454 if ( !Open() )
cf447356 455 return FALSE;
2bda0e17
KB
456
457 #ifdef __WIN32__
458 m_dwLastError = RegDeleteValue(m_hKey, szValue);
459 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 460 wxLogSysError(m_dwLastError, _("can't delete value '%s' from key '%s'"),
2bda0e17 461 szValue, GetName().c_str());
cf447356 462 return FALSE;
2bda0e17
KB
463 }
464 #else //WIN16
465 // named registry values don't exist in Win16 world
466 wxASSERT( IsEmpty(szValue) );
467
468 // just set the (default and unique) value of the key to ""
469 m_dwLastError = RegSetValue(m_hKey, NULL, REG_SZ, "", RESERVED);
470 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 471 wxLogSysError(m_dwLastError, _("can't delete value of key '%s'"),
2bda0e17 472 GetName().c_str());
cf447356 473 return FALSE;
2bda0e17
KB
474 }
475 #endif //WIN16/32
476
cf447356 477 return TRUE;
2bda0e17
KB
478}
479
480// ----------------------------------------------------------------------------
481// access to values and subkeys
482// ----------------------------------------------------------------------------
483
cf447356 484// return TRUE if value exists
0b1c5a6c
VZ
485bool wxRegKey::HasValue(const char *szValue) const
486{
487 #ifdef __WIN32__
488 if ( CONST_CAST Open() ) {
489 return RegQueryValueEx(m_hKey, szValue, RESERVED,
490 NULL, NULL, NULL) == ERROR_SUCCESS;
491 }
492 else
cf447356 493 return FALSE;
0b1c5a6c
VZ
494 #else // WIN16
495 // only unnamed value exists
496 return IsEmpty(szValue);
497 #endif // WIN16/32
498}
499
cf447356 500// returns TRUE if this key has any subkeys
2bda0e17
KB
501bool wxRegKey::HasSubkeys() const
502{
503 // just call GetFirstKey with dummy parameters
504 wxString str;
505 long l;
506 return CONST_CAST GetFirstKey(str, l);
507}
508
cf447356 509// returns TRUE if given subkey exists
2bda0e17
KB
510bool wxRegKey::HasSubKey(const char *szKey) const
511{
512 if ( CONST_CAST Open() )
513 return KeyExists(m_hKey, szKey);
514 else
cf447356 515 return FALSE;
2bda0e17
KB
516}
517
518wxRegKey::ValueType wxRegKey::GetValueType(const char *szValue)
519{
520 #ifdef __WIN32__
521 if ( !Open() )
522 return Type_None;
523
524 DWORD dwType;
525 m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED,
526 &dwType, NULL, NULL);
527 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 528 wxLogSysError(m_dwLastError, _("can't read value of key '%s'"),
2bda0e17
KB
529 GetName().c_str());
530 return Type_None;
531 }
532
533 return (ValueType)dwType;
534 #else //WIN16
535 return IsEmpty(szValue) ? Type_String : Type_None;
536 #endif //WIN16/32
537}
538
539#ifdef __WIN32__
540bool wxRegKey::SetValue(const char *szValue, long lValue)
541{
542 if ( CONST_CAST Open() ) {
543 m_dwLastError = RegSetValueEx(m_hKey, szValue, RESERVED, REG_DWORD,
544 (RegString)&lValue, sizeof(lValue));
545 if ( m_dwLastError == ERROR_SUCCESS )
cf447356 546 return TRUE;
2bda0e17
KB
547 }
548
02569ba8 549 wxLogSysError(m_dwLastError, _("can't set value of '%s'"),
2bda0e17 550 GetFullName(this, szValue));
cf447356 551 return FALSE;
2bda0e17
KB
552}
553
554bool wxRegKey::QueryValue(const char *szValue, long *plValue) const
555{
556 if ( CONST_CAST Open() ) {
557 DWORD dwType, dwSize = sizeof(DWORD);
558 RegString pBuf = (RegString)plValue;
559 m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED,
560 &dwType, pBuf, &dwSize);
561 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 562 wxLogSysError(m_dwLastError, _("can't read value of key '%s'"),
2bda0e17 563 GetName().c_str());
cf447356 564 return FALSE;
2bda0e17
KB
565 }
566 else {
567 // check that we read the value of right type
568 wxASSERT_MSG( dwType == REG_DWORD,
569 "Type mismatch in wxRegKey::QueryValue()." );
570
cf447356 571 return TRUE;
2bda0e17
KB
572 }
573 }
574 else
cf447356 575 return FALSE;
2bda0e17
KB
576}
577
578#endif //Win32
579
580bool wxRegKey::QueryValue(const char *szValue, wxString& strValue) const
581{
582 if ( CONST_CAST Open() ) {
583 #ifdef __WIN32__
584 // first get the type and size of the data
585 DWORD dwType, dwSize;
586 m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED,
587 &dwType, NULL, &dwSize);
588 if ( m_dwLastError == ERROR_SUCCESS ) {
589 RegString pBuf = (RegString)strValue.GetWriteBuf(dwSize);
590 m_dwLastError = RegQueryValueEx(m_hKey, szValue, RESERVED,
591 &dwType, pBuf, &dwSize);
44a6c8e6 592 strValue.UngetWriteBuf();
2bda0e17
KB
593 if ( m_dwLastError == ERROR_SUCCESS ) {
594 // check that it was the right type
595 wxASSERT_MSG( dwType == REG_SZ,
596 "Type mismatch in wxRegKey::QueryValue()." );
597
cf447356 598 return TRUE;
2bda0e17
KB
599 }
600 }
601 #else //WIN16
602 // named registry values don't exist in Win16
603 wxASSERT( IsEmpty(szValue) );
604
605 m_dwLastError = RegQueryValue(m_hKey, 0, strValue.GetWriteBuf(256), &l);
44a6c8e6 606 strValue.UngetWriteBuf();
2bda0e17 607 if ( m_dwLastError == ERROR_SUCCESS )
cf447356 608 return TRUE;
2bda0e17
KB
609 #endif //WIN16/32
610 }
611
02569ba8 612 wxLogSysError(m_dwLastError, _("can't read value of '%s'"),
2bda0e17 613 GetFullName(this, szValue));
cf447356 614 return FALSE;
2bda0e17
KB
615}
616
617bool wxRegKey::SetValue(const char *szValue, const wxString& strValue)
618{
619 if ( CONST_CAST Open() ) {
620 #ifdef __WIN32__
621 m_dwLastError = RegSetValueEx(m_hKey, szValue, RESERVED, REG_SZ,
622 (RegString)strValue.c_str(),
623 strValue.Len() + 1);
624 if ( m_dwLastError == ERROR_SUCCESS )
cf447356 625 return TRUE;
2bda0e17
KB
626 #else //WIN16
627 // named registry values don't exist in Win16
628 wxASSERT( IsEmpty(szValue) );
629
630 m_dwLastError = RegSetValue(m_hKey, NULL, REG_SZ, strValue, NULL);
631 if ( m_dwLastError == ERROR_SUCCESS )
cf447356 632 return TRUE;
2bda0e17
KB
633 #endif //WIN16/32
634 }
635
02569ba8 636 wxLogSysError(m_dwLastError, _("can't set value of '%s'"),
2bda0e17 637 GetFullName(this, szValue));
cf447356 638 return FALSE;
2bda0e17
KB
639}
640
641wxRegKey::operator wxString() const
642{
643 wxString str;
644 QueryValue(NULL, str);
645 return str;
646}
647
648// ----------------------------------------------------------------------------
649// enumeration
650// NB: all these functions require an index variable which allows to have
651// several concurrently running indexations on the same key
652// ----------------------------------------------------------------------------
653
2bda0e17
KB
654bool wxRegKey::GetFirstValue(wxString& strValueName, long& lIndex)
655{
656 if ( !Open() )
cf447356 657 return FALSE;
2bda0e17
KB
658
659 lIndex = 0;
0b1c5a6c 660 return GetNextValue(strValueName, lIndex);
2bda0e17
KB
661}
662
663bool wxRegKey::GetNextValue(wxString& strValueName, long& lIndex) const
664{
665 wxASSERT( IsOpened() );
2bda0e17 666
0b1c5a6c
VZ
667 // are we already at the end of enumeration?
668 if ( lIndex == -1 )
cf447356 669 return FALSE;
2bda0e17 670
0b1c5a6c
VZ
671 #ifdef __WIN32__
672 char szValueName[1024]; // @@ use RegQueryInfoKey...
673 DWORD dwValueLen = WXSIZEOF(szValueName);
2bda0e17 674
0b1c5a6c
VZ
675 lIndex++;
676 m_dwLastError = RegEnumValue(m_hKey, lIndex,
677 szValueName, &dwValueLen,
678 RESERVED,
679 NULL, // [out] type
680 NULL, // [out] buffer for value
681 NULL); // [i/o] it's length
682
683 if ( m_dwLastError != ERROR_SUCCESS ) {
684 if ( m_dwLastError == ERROR_NO_MORE_ITEMS ) {
685 m_dwLastError = ERROR_SUCCESS;
686 lIndex = -1;
687 }
688 else {
02569ba8 689 wxLogSysError(m_dwLastError, _("can't enumerate values of key '%s'"),
0b1c5a6c
VZ
690 GetName().c_str());
691 }
692
cf447356 693 return FALSE;
2bda0e17
KB
694 }
695
0b1c5a6c
VZ
696 strValueName = szValueName;
697 #else //WIN16
698 // only one unnamed value
699 wxASSERT( lIndex == 0 );
2bda0e17 700
0b1c5a6c
VZ
701 lIndex = -1;
702 strValueName.Empty();
703 #endif
704
cf447356 705 return TRUE;
2bda0e17 706}
2bda0e17
KB
707
708bool wxRegKey::GetFirstKey(wxString& strKeyName, long& lIndex)
709{
710 if ( !Open() )
cf447356 711 return FALSE;
2bda0e17 712
2bda0e17 713 lIndex = 0;
0b1c5a6c 714 return GetNextKey(strKeyName, lIndex);
2bda0e17
KB
715}
716
717bool wxRegKey::GetNextKey(wxString& strKeyName, long& lIndex) const
718{
719 wxASSERT( IsOpened() );
0b1c5a6c
VZ
720
721 // are we already at the end of enumeration?
722 if ( lIndex == -1 )
cf447356 723 return FALSE;
2bda0e17
KB
724
725 char szKeyName[_MAX_PATH + 1];
0b1c5a6c 726 m_dwLastError = RegEnumKey(m_hKey, lIndex++, szKeyName, WXSIZEOF(szKeyName));
2bda0e17
KB
727
728 if ( m_dwLastError != ERROR_SUCCESS ) {
729 if ( m_dwLastError == ERROR_NO_MORE_ITEMS ) {
730 m_dwLastError = ERROR_SUCCESS;
731 lIndex = -1;
732 }
733 else {
02569ba8 734 wxLogSysError(m_dwLastError, _("can't enumerate subkeys of key '%s'"),
2bda0e17
KB
735 GetName().c_str());
736 }
737
cf447356 738 return FALSE;
2bda0e17
KB
739 }
740
741 strKeyName = szKeyName;
cf447356 742 return TRUE;
2bda0e17
KB
743}
744
745// ============================================================================
746// implementation of global functions
747// ============================================================================
748bool KeyExists(HKEY hRootKey, const char *szKey)
749{
750 HKEY hkeyDummy;
751 if ( RegOpenKey(hRootKey, szKey, &hkeyDummy) == ERROR_SUCCESS ) {
752 RegCloseKey(hkeyDummy);
cf447356 753 return TRUE;
2bda0e17
KB
754 }
755 else
cf447356 756 return FALSE;
2bda0e17
KB
757}
758
759const char *GetFullName(const wxRegKey *pKey, const char *szValue)
760{
761 static wxString s_str;
762 s_str = pKey->GetName();
763 if ( !IsEmpty(szValue) )
764 s_str << "\\" << szValue;
765
766 return s_str.c_str();
0b1c5a6c
VZ
767}
768
769void RemoveTrailingSeparator(wxString& str)
770{
771 if ( !str.IsEmpty() && str.Last() == REG_SEPARATOR )
772 str.Truncate(str.Len() - 1);
773}