Additional makefiles; changes for compilation with BC++ and GnuWin32
[wxWidgets.git] / src / msw / registry.cpp
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 #ifdef __GNUG__
16 #pragma implementation "registry.h"
17 #endif
18
19 // ============================================================================
20 // declarations
21 // ============================================================================
22
23 // ----------------------------------------------------------------------------
24 // headers
25 // ----------------------------------------------------------------------------
26
27 // for compilers that support precompilation, includes "wx.h".
28 #include "wx/wxprec.h"
29
30 #ifdef __BORLANDC__
31 #pragma hdrstop
32 #endif
33
34 // other wxWindows headers
35 #include "wx/string.h"
36 #include "wx/intl.h"
37 #include "wx/log.h"
38
39 #include "wx/config.h" // for wxExpandEnvVars
40
41 // Windows headers
42 /*
43 #define STRICT
44 #define WIN32_LEAN_AND_MEAN
45 */
46
47 #include <windows.h>
48
49 // other std headers
50 #include <stdlib.h> // for _MAX_PATH
51
52 #ifndef _MAX_PATH
53 #define _MAX_PATH 512
54 #endif
55
56 // our header
57 #define HKEY_DEFINED // already defined in windows.h
58 #include "wx/msw/registry.h"
59
60 // some registry functions don't like signed chars
61 typedef unsigned char *RegString;
62
63 // ----------------------------------------------------------------------------
64 // constants
65 // ----------------------------------------------------------------------------
66
67 // the standard key names, short names and handles all bundled together for
68 // convenient access
69 static struct
70 {
71 HKEY hkey;
72 const char *szName;
73 const char *szShortName;
74 }
75 aStdKeys[] =
76 {
77 { HKEY_CLASSES_ROOT, "HKEY_CLASSES_ROOT", "HKCR" },
78 #ifdef __WIN32__
79 { HKEY_CURRENT_USER, "HKEY_CURRENT_USER", "HKCU" },
80 { HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", "HKLM" },
81 { HKEY_USERS, "HKEY_USERS", "HKU" }, // short name?
82 { HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA", "HKPD" },
83 #if WINVER >= 0x0400
84 { HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG", "HKCC" },
85 #ifndef __GNUWIN32__
86 { HKEY_DYN_DATA, "HKEY_DYN_DATA", "HKDD" }, // short name?
87 #endif //GNUWIN32
88 #endif //WINVER >= 4.0
89 #endif //WIN32
90 };
91
92 // the registry name separator (perhaps one day MS will change it to '/' ;-)
93 #define REG_SEPARATOR '\\'
94
95 // useful for Windows programmers: makes somewhat more clear all these zeroes
96 // being passed to Windows APIs
97 #define RESERVED (NULL)
98
99 // ----------------------------------------------------------------------------
100 // macros
101 // ----------------------------------------------------------------------------
102 // @ const_cast<> is not yet supported by all compilers
103 #define CONST_CAST ((wxRegKey *)this)->
104
105 #if !USE_MUTABLE
106 #define m_dwLastError CONST_CAST m_dwLastError
107 #endif
108
109 // ----------------------------------------------------------------------------
110 // non member functions
111 // ----------------------------------------------------------------------------
112
113 // removes the trailing backslash from the string if it has one
114 static inline void RemoveTrailingSeparator(wxString& str);
115
116 // returns TRUE if given registry key exists
117 static bool KeyExists(WXHKEY hRootKey, const char *szKey);
118
119 // combines value and key name (uses static buffer!)
120 static const char *GetFullName(const wxRegKey *pKey,
121 const char *szValue = NULL);
122
123 // ============================================================================
124 // implementation of wxRegKey class
125 // ============================================================================
126
127 // ----------------------------------------------------------------------------
128 // static functions and variables
129 // ----------------------------------------------------------------------------
130
131 const size_t wxRegKey::nStdKeys = WXSIZEOF(aStdKeys);
132
133 // @@ should take a `StdKey key', but as it's often going to be used in loops
134 // it would require casts in user code.
135 const char *wxRegKey::GetStdKeyName(size_t key)
136 {
137 // return empty string if key is invalid
138 wxCHECK_MSG( key < nStdKeys, "", "invalid key in wxRegKey::GetStdKeyName" );
139
140 return aStdKeys[key].szName;
141 }
142
143 const char *wxRegKey::GetStdKeyShortName(size_t key)
144 {
145 // return empty string if key is invalid
146 wxCHECK( key < nStdKeys, "" );
147
148 return aStdKeys[key].szShortName;
149 }
150
151 wxRegKey::StdKey wxRegKey::ExtractKeyName(wxString& strKey)
152 {
153 wxString strRoot = strKey.Left(REG_SEPARATOR);
154
155 HKEY hRootKey;
156 size_t ui;
157 for ( ui = 0; ui < nStdKeys; ui++ ) {
158 if ( strRoot.CmpNoCase(aStdKeys[ui].szName) == 0 ||
159 strRoot.CmpNoCase(aStdKeys[ui].szShortName) == 0 ) {
160 hRootKey = aStdKeys[ui].hkey;
161 break;
162 }
163 }
164
165 if ( ui == nStdKeys ) {
166 wxFAIL_MSG("invalid key prefix in wxRegKey::ExtractKeyName.");
167
168 hRootKey = HKEY_CLASSES_ROOT;
169 }
170 else {
171 strKey = strKey.After(REG_SEPARATOR);
172 if ( !strKey.IsEmpty() && strKey.Last() == REG_SEPARATOR )
173 strKey.Truncate(strKey.Len() - 1);
174 }
175
176 return (wxRegKey::StdKey)(int)hRootKey;
177 }
178
179 wxRegKey::StdKey wxRegKey::GetStdKeyFromHkey(WXHKEY hkey)
180 {
181 for ( size_t ui = 0; ui < nStdKeys; ui++ ) {
182 if ( (int) aStdKeys[ui].hkey == (int) hkey )
183 return (StdKey)ui;
184 }
185
186 wxFAIL_MSG("non root hkey passed to wxRegKey::GetStdKeyFromHkey.");
187
188 return HKCR;
189 }
190
191 // ----------------------------------------------------------------------------
192 // ctors and dtor
193 // ----------------------------------------------------------------------------
194
195 wxRegKey::wxRegKey()
196 {
197 m_hKey = 0;
198 m_hRootKey = (WXHKEY) aStdKeys[HKCR].hkey;
199 m_dwLastError = 0;
200 }
201
202 wxRegKey::wxRegKey(const wxString& strKey) : m_strKey(strKey)
203 {
204 m_hRootKey = (WXHKEY) aStdKeys[ExtractKeyName(m_strKey)].hkey;
205 m_hKey = NULL;
206 m_dwLastError = 0;
207 }
208
209 // parent is a predefined (and preopened) key
210 wxRegKey::wxRegKey(StdKey keyParent, const wxString& strKey) : m_strKey(strKey)
211 {
212 RemoveTrailingSeparator(m_strKey);
213 m_hRootKey = (WXHKEY) aStdKeys[keyParent].hkey;
214 m_hKey = NULL;
215 m_dwLastError = 0;
216 }
217
218 // parent is a normal regkey
219 wxRegKey::wxRegKey(const wxRegKey& keyParent, const wxString& strKey)
220 : m_strKey(keyParent.m_strKey)
221 {
222 // combine our name with parent's to get the full name
223 if ( !m_strKey.IsEmpty() &&
224 (strKey.IsEmpty() || strKey[0] != REG_SEPARATOR) ) {
225 m_strKey += REG_SEPARATOR;
226 }
227
228 m_strKey += strKey;
229 RemoveTrailingSeparator(m_strKey);
230
231 m_hRootKey = keyParent.m_hRootKey;
232 m_hKey = NULL;
233 m_dwLastError = 0;
234 }
235
236 // dtor closes the key releasing system resource
237 wxRegKey::~wxRegKey()
238 {
239 Close();
240 }
241
242 // ----------------------------------------------------------------------------
243 // change the key name/hkey
244 // ----------------------------------------------------------------------------
245
246 // set the full key name
247 void wxRegKey::SetName(const wxString& strKey)
248 {
249 Close();
250
251 m_strKey = strKey;
252 m_hRootKey = (WXHKEY) aStdKeys[ExtractKeyName(m_strKey)].hkey;
253 }
254
255 // the name is relative to the parent key
256 void wxRegKey::SetName(StdKey keyParent, const wxString& strKey)
257 {
258 Close();
259
260 m_strKey = strKey;
261 RemoveTrailingSeparator(m_strKey);
262 m_hRootKey = (WXHKEY) aStdKeys[keyParent].hkey;
263 }
264
265 // the name is relative to the parent key
266 void wxRegKey::SetName(const wxRegKey& keyParent, const wxString& strKey)
267 {
268 Close();
269
270 // combine our name with parent's to get the full name
271 m_strKey = keyParent.m_strKey;
272 if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR )
273 m_strKey += REG_SEPARATOR;
274 m_strKey += strKey;
275
276 RemoveTrailingSeparator(m_strKey);
277
278 m_hRootKey = keyParent.m_hRootKey;
279 }
280
281 // hKey should be opened and will be closed in wxRegKey dtor
282 void wxRegKey::SetHkey(WXHKEY hKey)
283 {
284 Close();
285
286 m_hKey = hKey;
287 }
288
289 // ----------------------------------------------------------------------------
290 // info about the key
291 // ----------------------------------------------------------------------------
292
293 // returns TRUE if the key exists
294 bool wxRegKey::Exists() const
295 {
296 // opened key has to exist, try to open it if not done yet
297 return IsOpened() ? TRUE : KeyExists(m_hRootKey, m_strKey);
298 }
299
300 // returns the full name of the key (prefix is abbreviated if bShortPrefix)
301 wxString wxRegKey::GetName(bool bShortPrefix) const
302 {
303 StdKey key = GetStdKeyFromHkey((StdKey) m_hRootKey);
304 wxString str = bShortPrefix ? aStdKeys[key].szShortName
305 : aStdKeys[key].szName;
306 if ( !m_strKey.IsEmpty() )
307 str << "\\" << m_strKey;
308
309 return str;
310 }
311
312 #ifdef __GNUWIN32__
313 bool wxRegKey::GetKeyInfo(size_t* pnSubKeys,
314 size_t* pnMaxKeyLen,
315 size_t* pnValues,
316 size_t* pnMaxValueLen) const
317 #else
318 bool wxRegKey::GetKeyInfo(ulong *pnSubKeys,
319 ulong *pnMaxKeyLen,
320 ulong *pnValues,
321 ulong *pnMaxValueLen) const
322 #endif
323 {
324 #ifdef __WIN32__
325 m_dwLastError = ::RegQueryInfoKey
326 (
327 (HKEY) m_hKey,
328 NULL, // class name
329 NULL, // (ptr to) size of class name buffer
330 RESERVED,
331 pnSubKeys, // [out] number of subkeys
332 pnMaxKeyLen, // [out] max length of a subkey name
333 NULL, // longest subkey class name
334 pnValues, // [out] number of values
335 pnMaxValueLen, // [out] max length of a value name
336 NULL, // longest value data
337 NULL, // security descriptor
338 NULL // time of last modification
339 );
340
341 if ( m_dwLastError != ERROR_SUCCESS ) {
342 wxLogSysError(m_dwLastError, _("can't get info about registry key '%s'"),
343 GetName().c_str());
344 return FALSE;
345 }
346 else
347 return TRUE;
348 #else // Win16
349 wxFAIL_MSG("GetKeyInfo() not implemented");
350
351 return FALSE;
352 #endif
353 }
354
355 // ----------------------------------------------------------------------------
356 // operations
357 // ----------------------------------------------------------------------------
358
359 // opens key (it's not an error to call Open() on an already opened key)
360 bool wxRegKey::Open()
361 {
362 if ( IsOpened() )
363 return TRUE;
364
365 HKEY tmpKey;
366 m_dwLastError = RegOpenKey((HKEY) m_hRootKey, m_strKey, &tmpKey);
367 if ( m_dwLastError != ERROR_SUCCESS ) {
368 wxLogSysError(m_dwLastError, _("can't open registry key '%s'"),
369 GetName().c_str());
370 return FALSE;
371 }
372 else
373 {
374 m_hKey = (WXHKEY) tmpKey;
375 return TRUE;
376 }
377 }
378
379 // creates key, failing if it exists and !bOkIfExists
380 bool wxRegKey::Create(bool bOkIfExists)
381 {
382 // check for existence only if asked (i.e. order is important!)
383 if ( !bOkIfExists && Exists() ) {
384 return FALSE;
385 }
386
387 if ( IsOpened() )
388 return TRUE;
389
390 HKEY tmpKey;
391 m_dwLastError = RegCreateKey((HKEY) m_hRootKey, m_strKey, &tmpKey);
392 if ( m_dwLastError != ERROR_SUCCESS ) {
393 wxLogSysError(m_dwLastError, _("can't create registry key '%s'"),
394 GetName().c_str());
395 return FALSE;
396 }
397 else
398 {
399 m_hKey = (WXHKEY) tmpKey;
400 return TRUE;
401 }
402 }
403
404 // close the key, it's not an error to call it when not opened
405 bool wxRegKey::Close()
406 {
407 if ( IsOpened() ) {
408 m_dwLastError = RegCloseKey((HKEY) m_hKey);
409 if ( m_dwLastError != ERROR_SUCCESS ) {
410 wxLogSysError(m_dwLastError, _("can't close registry key '%s'"),
411 GetName().c_str());
412
413 m_hKey = 0;
414 return FALSE;
415 }
416 else {
417 m_hKey = 0;
418 }
419 }
420
421 return TRUE;
422 }
423
424 // ----------------------------------------------------------------------------
425 // delete keys/values
426 // ----------------------------------------------------------------------------
427 bool wxRegKey::DeleteSelf()
428 {
429 {
430 wxLogNull nolog;
431 if ( !Open() ) {
432 // it already doesn't exist - ok!
433 return TRUE;
434 }
435 }
436
437 // we can't delete keys while enumerating because it confuses GetNextKey, so
438 // we first save the key names and then delete them all
439 wxArrayString astrSubkeys;
440
441 wxString strKey;
442 long lIndex;
443 bool bCont = GetFirstKey(strKey, lIndex);
444 while ( bCont ) {
445 astrSubkeys.Add(strKey);
446
447 bCont = GetNextKey(strKey, lIndex);
448 }
449
450 size_t nKeyCount = astrSubkeys.Count();
451 for ( size_t nKey = 0; nKey < nKeyCount; nKey++ ) {
452 wxRegKey key(*this, astrSubkeys[nKey]);
453 if ( !key.DeleteSelf() )
454 return FALSE;
455 }
456
457 // now delete this key itself
458 Close();
459
460 m_dwLastError = RegDeleteKey((HKEY) m_hRootKey, m_strKey);
461 if ( m_dwLastError != ERROR_SUCCESS ) {
462 wxLogSysError(m_dwLastError, _("can't delete key '%s'"),
463 GetName().c_str());
464 return FALSE;
465 }
466
467 return TRUE;
468 }
469
470 bool wxRegKey::DeleteKey(const char *szKey)
471 {
472 if ( !Open() )
473 return FALSE;
474
475 wxRegKey key(*this, szKey);
476 return key.DeleteSelf();
477 }
478
479 bool wxRegKey::DeleteValue(const char *szValue)
480 {
481 if ( !Open() )
482 return FALSE;
483
484 #ifdef __WIN32__
485 m_dwLastError = RegDeleteValue((HKEY) m_hKey, szValue);
486 if ( m_dwLastError != ERROR_SUCCESS ) {
487 wxLogSysError(m_dwLastError, _("can't delete value '%s' from key '%s'"),
488 szValue, GetName().c_str());
489 return FALSE;
490 }
491 #else //WIN16
492 // named registry values don't exist in Win16 world
493 wxASSERT( IsEmpty(szValue) );
494
495 // just set the (default and unique) value of the key to ""
496 m_dwLastError = RegSetValue((HKEY) m_hKey, NULL, REG_SZ, "", RESERVED);
497 if ( m_dwLastError != ERROR_SUCCESS ) {
498 wxLogSysError(m_dwLastError, _("can't delete value of key '%s'"),
499 GetName().c_str());
500 return FALSE;
501 }
502 #endif //WIN16/32
503
504 return TRUE;
505 }
506
507 // ----------------------------------------------------------------------------
508 // access to values and subkeys
509 // ----------------------------------------------------------------------------
510
511 // return TRUE if value exists
512 bool wxRegKey::HasValue(const char *szValue) const
513 {
514 // this function should be silent, so suppress possible messages from Open()
515 wxLogNull nolog;
516
517 #ifdef __WIN32__
518 if ( CONST_CAST Open() ) {
519 return RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
520 NULL, NULL, NULL) == ERROR_SUCCESS;
521 }
522 else
523 return FALSE;
524 #else // WIN16
525 // only unnamed value exists
526 return IsEmpty(szValue);
527 #endif // WIN16/32
528 }
529
530 // returns TRUE if this key has any subkeys
531 bool wxRegKey::HasSubkeys() const
532 {
533 // just call GetFirstKey with dummy parameters
534 wxString str;
535 long l;
536 return CONST_CAST GetFirstKey(str, l);
537 }
538
539 // returns TRUE if given subkey exists
540 bool wxRegKey::HasSubKey(const char *szKey) const
541 {
542 if ( CONST_CAST Open() )
543 return KeyExists(m_hKey, szKey);
544 else
545 return FALSE;
546 }
547
548 wxRegKey::ValueType wxRegKey::GetValueType(const char *szValue)
549 {
550 #ifdef __WIN32__
551 if ( !Open() )
552 return Type_None;
553
554 DWORD dwType;
555 m_dwLastError = RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
556 &dwType, NULL, NULL);
557 if ( m_dwLastError != ERROR_SUCCESS ) {
558 wxLogSysError(m_dwLastError, _("can't read value of key '%s'"),
559 GetName().c_str());
560 return Type_None;
561 }
562
563 return (ValueType)dwType;
564 #else //WIN16
565 return IsEmpty(szValue) ? Type_String : Type_None;
566 #endif //WIN16/32
567 }
568
569 #ifdef __WIN32__
570 bool wxRegKey::SetValue(const char *szValue, long lValue)
571 {
572 if ( CONST_CAST Open() ) {
573 m_dwLastError = RegSetValueEx((HKEY) m_hKey, szValue, RESERVED, REG_DWORD,
574 (RegString)&lValue, sizeof(lValue));
575 if ( m_dwLastError == ERROR_SUCCESS )
576 return TRUE;
577 }
578
579 wxLogSysError(m_dwLastError, _("can't set value of '%s'"),
580 GetFullName(this, szValue));
581 return FALSE;
582 }
583
584 bool wxRegKey::QueryValue(const char *szValue, long *plValue) const
585 {
586 if ( CONST_CAST Open() ) {
587 DWORD dwType, dwSize = sizeof(DWORD);
588 RegString pBuf = (RegString)plValue;
589 m_dwLastError = RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
590 &dwType, pBuf, &dwSize);
591 if ( m_dwLastError != ERROR_SUCCESS ) {
592 wxLogSysError(m_dwLastError, _("can't read value of key '%s'"),
593 GetName().c_str());
594 return FALSE;
595 }
596 else {
597 // check that we read the value of right type
598 wxASSERT_MSG( dwType == REG_DWORD,
599 "Type mismatch in wxRegKey::QueryValue()." );
600
601 return TRUE;
602 }
603 }
604 else
605 return FALSE;
606 }
607
608 #endif //Win32
609
610 bool wxRegKey::QueryValue(const char *szValue, wxString& strValue) const
611 {
612 if ( CONST_CAST Open() ) {
613 #ifdef __WIN32__
614 // first get the type and size of the data
615 DWORD dwType, dwSize;
616 m_dwLastError = RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
617 &dwType, NULL, &dwSize);
618 if ( m_dwLastError == ERROR_SUCCESS ) {
619 RegString pBuf = (RegString)strValue.GetWriteBuf(dwSize);
620 m_dwLastError = RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
621 &dwType, pBuf, &dwSize);
622 strValue.UngetWriteBuf();
623 if ( m_dwLastError == ERROR_SUCCESS ) {
624 // check that it was the right type
625 wxASSERT_MSG( dwType == REG_SZ,
626 "Type mismatch in wxRegKey::QueryValue()." );
627
628 return TRUE;
629 }
630 }
631 #else //WIN16
632 // named registry values don't exist in Win16
633 wxASSERT( IsEmpty(szValue) );
634
635 m_dwLastError = RegQueryValue((HKEY) m_hKey, 0, strValue.GetWriteBuf(256), &l);
636 strValue.UngetWriteBuf();
637 if ( m_dwLastError == ERROR_SUCCESS )
638 return TRUE;
639 #endif //WIN16/32
640 }
641
642 wxLogSysError(m_dwLastError, _("can't read value of '%s'"),
643 GetFullName(this, szValue));
644 return FALSE;
645 }
646
647 bool wxRegKey::SetValue(const char *szValue, const wxString& strValue)
648 {
649 if ( CONST_CAST Open() ) {
650 #ifdef __WIN32__
651 m_dwLastError = RegSetValueEx((HKEY) m_hKey, szValue, RESERVED, REG_SZ,
652 (RegString)strValue.c_str(),
653 strValue.Len() + 1);
654 if ( m_dwLastError == ERROR_SUCCESS )
655 return TRUE;
656 #else //WIN16
657 // named registry values don't exist in Win16
658 wxASSERT( IsEmpty(szValue) );
659
660 m_dwLastError = RegSetValue((HKEY) m_hKey, NULL, REG_SZ, strValue, NULL);
661 if ( m_dwLastError == ERROR_SUCCESS )
662 return TRUE;
663 #endif //WIN16/32
664 }
665
666 wxLogSysError(m_dwLastError, _("can't set value of '%s'"),
667 GetFullName(this, szValue));
668 return FALSE;
669 }
670
671 wxRegKey::operator wxString() const
672 {
673 wxString str;
674 QueryValue(NULL, str);
675 return str;
676 }
677
678 // ----------------------------------------------------------------------------
679 // enumeration
680 // NB: all these functions require an index variable which allows to have
681 // several concurrently running indexations on the same key
682 // ----------------------------------------------------------------------------
683
684 bool wxRegKey::GetFirstValue(wxString& strValueName, long& lIndex)
685 {
686 if ( !Open() )
687 return FALSE;
688
689 lIndex = 0;
690 return GetNextValue(strValueName, lIndex);
691 }
692
693 bool wxRegKey::GetNextValue(wxString& strValueName, long& lIndex) const
694 {
695 wxASSERT( IsOpened() );
696
697 // are we already at the end of enumeration?
698 if ( lIndex == -1 )
699 return FALSE;
700
701 #ifdef __WIN32__
702 char szValueName[1024]; // @@ use RegQueryInfoKey...
703 DWORD dwValueLen = WXSIZEOF(szValueName);
704
705 lIndex++;
706 m_dwLastError = RegEnumValue((HKEY) m_hKey, lIndex,
707 szValueName, &dwValueLen,
708 RESERVED,
709 NULL, // [out] type
710 NULL, // [out] buffer for value
711 NULL); // [i/o] it's length
712
713 if ( m_dwLastError != ERROR_SUCCESS ) {
714 if ( m_dwLastError == ERROR_NO_MORE_ITEMS ) {
715 m_dwLastError = ERROR_SUCCESS;
716 lIndex = -1;
717 }
718 else {
719 wxLogSysError(m_dwLastError, _("can't enumerate values of key '%s'"),
720 GetName().c_str());
721 }
722
723 return FALSE;
724 }
725
726 strValueName = szValueName;
727 #else //WIN16
728 // only one unnamed value
729 wxASSERT( lIndex == 0 );
730
731 lIndex = -1;
732 strValueName.Empty();
733 #endif
734
735 return TRUE;
736 }
737
738 bool wxRegKey::GetFirstKey(wxString& strKeyName, long& lIndex)
739 {
740 if ( !Open() )
741 return FALSE;
742
743 lIndex = 0;
744 return GetNextKey(strKeyName, lIndex);
745 }
746
747 bool wxRegKey::GetNextKey(wxString& strKeyName, long& lIndex) const
748 {
749 wxASSERT( IsOpened() );
750
751 // are we already at the end of enumeration?
752 if ( lIndex == -1 )
753 return FALSE;
754
755 char szKeyName[_MAX_PATH + 1];
756 m_dwLastError = RegEnumKey((HKEY) m_hKey, lIndex++, szKeyName, WXSIZEOF(szKeyName));
757
758 if ( m_dwLastError != ERROR_SUCCESS ) {
759 if ( m_dwLastError == ERROR_NO_MORE_ITEMS ) {
760 m_dwLastError = ERROR_SUCCESS;
761 lIndex = -1;
762 }
763 else {
764 wxLogSysError(m_dwLastError, _("can't enumerate subkeys of key '%s'"),
765 GetName().c_str());
766 }
767
768 return FALSE;
769 }
770
771 strKeyName = szKeyName;
772 return TRUE;
773 }
774
775 // ============================================================================
776 // implementation of global private functions
777 // ============================================================================
778 bool KeyExists(WXHKEY hRootKey, const char *szKey)
779 {
780 HKEY hkeyDummy;
781 if ( RegOpenKey( (HKEY) hRootKey, szKey, &hkeyDummy) == ERROR_SUCCESS ) {
782 RegCloseKey(hkeyDummy);
783 return TRUE;
784 }
785 else
786 return FALSE;
787 }
788
789 const char *GetFullName(const wxRegKey *pKey, const char *szValue)
790 {
791 static wxString s_str;
792 s_str = pKey->GetName();
793 if ( !IsEmpty(szValue) )
794 s_str << "\\" << szValue;
795
796 return s_str.c_str();
797 }
798
799 void RemoveTrailingSeparator(wxString& str)
800 {
801 if ( !str.IsEmpty() && str.Last() == REG_SEPARATOR )
802 str.Truncate(str.Len() - 1);
803 }
804
805 // ============================================================================
806 // global public functions
807 // ============================================================================
808
809 bool GetExtensionFromMimeType(wxString *pExt, const wxString& strMimeType)
810 {
811 // @@@ VZ: I don't know of any official documentation which mentions this
812 // location, but as a matter of fact IE uses it, so why not we?
813 static const char *szMimeDbase = "MIME\\Database\\Content Type\\";
814
815 wxString strKey = szMimeDbase;
816 strKey << strMimeType;
817
818 // suppress possible error messages
819 wxLogNull nolog;
820 wxRegKey key(wxRegKey::HKCR, strKey);
821 if ( key.Open() ) {
822 if ( key.QueryValue("Extension", *pExt) )
823 return TRUE;
824 }
825
826 // no such MIME type or no extension for it
827 return FALSE;
828 }
829
830 bool GetMimeTypeFromExtension(wxString *pMimeType, const wxString& strExt)
831 {
832 wxCHECK( !strExt.IsEmpty(), FALSE );
833
834 // add the leading point if necessary
835 wxString str;
836 if ( strExt[0] != '.' ) {
837 str = '.';
838 }
839 str << strExt;
840
841 // suppress possible error messages
842 wxLogNull nolog;
843 wxRegKey key(wxRegKey::HKCR, str);
844 if ( key.Open() ) {
845 if ( key.QueryValue("Content Type", *pMimeType) )
846 return TRUE;
847 }
848
849 // no such extension or no content-type
850 return FALSE;
851 }
852
853 bool GetFileTypeFromExtension(wxString *pFileType, const wxString& strExt)
854 {
855 wxCHECK( !strExt.IsEmpty(), FALSE );
856
857 // add the leading point if necessary
858 wxString str;
859 if ( strExt[0] != '.' ) {
860 str = '.';
861 }
862 str << strExt;
863
864 // suppress possible error messages
865 wxLogNull nolog;
866 wxRegKey key(wxRegKey::HKCR, str);
867 if ( key.Open() ) {
868 if ( key.QueryValue("", *pFileType) ) // it's the default value of the key
869 return TRUE;
870 }
871
872 // no such extension or no value
873 return FALSE;
874 }
875
876 bool GetFileTypeIcon(wxIcon *pIcon, const wxString& strFileType)
877 {
878 wxCHECK( !strFileType.IsEmpty(), FALSE );
879
880 wxString strIconKey;
881 strIconKey << strFileType << REG_SEPARATOR << "DefaultIcon";
882
883 // suppress possible error messages
884 wxLogNull nolog;
885 wxRegKey key(wxRegKey::HKCR, strIconKey);
886
887 if ( key.Open() ) {
888 wxString strIcon;
889 if ( key.QueryValue("", strIcon) ) { // it's the default value of the key
890 // the format is the following: <full path to file>, <icon index>
891 // NB: icon index may be negative as well as positive and the full path
892 // may contain the environment variables inside '%'
893 wxString strFullPath = strIcon.Before(','),
894 strIndex = strIcon.Right(',');
895
896 // index may be omitted, in which case Before(',') is empty and
897 // Right(',') is the whole string
898 if ( strFullPath.IsEmpty() ) {
899 strFullPath = strIndex;
900 strIndex = "0";
901 }
902
903 wxString strExpPath = wxExpandEnvVars(strFullPath);
904 int nIndex = atoi(strIndex);
905
906 HICON hIcon = ExtractIcon(GetModuleHandle(NULL), strExpPath, nIndex);
907 switch ( (int)hIcon ) {
908 case 0: // means no icons were found
909 case 1: // means no such file or it wasn't a DLL/EXE/OCX/ICO/...
910 wxLogDebug("incorrect registry entry '%s': no such icon.",
911 GetFullName(&key));
912 break;
913
914 default:
915 pIcon->SetHICON((WXHICON)hIcon);
916 return TRUE;
917 }
918 }
919 }
920
921 // no such file type or no value or incorrect icon entry
922 return FALSE;
923 }
924
925 bool GetFileTypeDescription(wxString *pDesc, const wxString& strFileType)
926 {
927 wxCHECK( !strFileType.IsEmpty(), FALSE );
928
929 // suppress possible error messages
930 wxLogNull nolog;
931 wxRegKey key(wxRegKey::HKCR, strFileType);
932
933 if ( key.Open() ) {
934 if ( key.QueryValue("", *pDesc) ) // it's the default value of the key
935 return TRUE;
936 }
937
938 // no such file type or no value
939 return FALSE;
940 }
941
942