]> git.saurik.com Git - wxWidgets.git/blame - src/msw/registry.cpp
More wxMotif work, OGL enhancements, USE_ macro corrections, object.cpp delete
[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
27529614
JS
15#ifdef __GNUG__
16#pragma implementation "registry.h"
17#endif
18
2bda0e17
KB
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
41286812
VZ
39#include "wx/config.h" // for wxExpandEnvVars
40
2bda0e17 41// Windows headers
57a7b7c1 42/*
2bda0e17
KB
43#define STRICT
44#define WIN32_LEAN_AND_MEAN
57a7b7c1
JS
45*/
46
2bda0e17
KB
47#include <windows.h>
48
49// other std headers
50#include <stdlib.h> // for _MAX_PATH
51
52#ifndef _MAX_PATH
0b1c5a6c 53 #define _MAX_PATH 512
2bda0e17
KB
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
61typedef 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
69static struct
70{
71 HKEY hkey;
72 const char *szName;
73 const char *szShortName;
74}
75aStdKeys[] =
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?
0b1c5a6c 87#endif //GNUWIN32
2bda0e17
KB
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
c86f1403
VZ
95// useful for Windows programmers: makes somewhat more clear all these zeroes
96// being passed to Windows APIs
97#define RESERVED (NULL)
98
2bda0e17
KB
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
0b1c5a6c
VZ
113// removes the trailing backslash from the string if it has one
114static inline void RemoveTrailingSeparator(wxString& str);
115
cf447356 116// returns TRUE if given registry key exists
fd6c844b 117static bool KeyExists(WXHKEY hRootKey, const char *szKey);
2bda0e17
KB
118
119// combines value and key name (uses static buffer!)
120static 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
131const 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.
c86f1403 135const char *wxRegKey::GetStdKeyName(size_t key)
2bda0e17
KB
136{
137 // return empty string if key is invalid
1311c7a9 138 wxCHECK_MSG( key < nStdKeys, "", "invalid key in wxRegKey::GetStdKeyName" );
2bda0e17
KB
139
140 return aStdKeys[key].szName;
141}
142
c86f1403 143const char *wxRegKey::GetStdKeyShortName(size_t key)
2bda0e17
KB
144{
145 // return empty string if key is invalid
1311c7a9 146 wxCHECK( key < nStdKeys, "" );
2bda0e17
KB
147
148 return aStdKeys[key].szShortName;
149}
150
151wxRegKey::StdKey wxRegKey::ExtractKeyName(wxString& strKey)
152{
153 wxString strRoot = strKey.Left(REG_SEPARATOR);
154
155 HKEY hRootKey;
c86f1403 156 size_t ui;
2bda0e17
KB
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
fd6c844b 179wxRegKey::StdKey wxRegKey::GetStdKeyFromHkey(WXHKEY hkey)
2bda0e17 180{
c86f1403 181 for ( size_t ui = 0; ui < nStdKeys; ui++ ) {
fd6c844b 182 if ( (int) aStdKeys[ui].hkey == (int) hkey )
2bda0e17
KB
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
195wxRegKey::wxRegKey()
196{
197 m_hKey = 0;
fd6c844b 198 m_hRootKey = (WXHKEY) aStdKeys[HKCR].hkey;
2bda0e17
KB
199 m_dwLastError = 0;
200}
201
202wxRegKey::wxRegKey(const wxString& strKey) : m_strKey(strKey)
203{
fd6c844b 204 m_hRootKey = (WXHKEY) aStdKeys[ExtractKeyName(m_strKey)].hkey;
2bda0e17
KB
205 m_hKey = NULL;
206 m_dwLastError = 0;
207}
208
209// parent is a predefined (and preopened) key
210wxRegKey::wxRegKey(StdKey keyParent, const wxString& strKey) : m_strKey(strKey)
211{
0b1c5a6c 212 RemoveTrailingSeparator(m_strKey);
fd6c844b 213 m_hRootKey = (WXHKEY) aStdKeys[keyParent].hkey;
2bda0e17
KB
214 m_hKey = NULL;
215 m_dwLastError = 0;
216}
217
218// parent is a normal regkey
219wxRegKey::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
32c66ea2
VZ
223 if ( !m_strKey.IsEmpty() &&
224 (strKey.IsEmpty() || strKey[0] != REG_SEPARATOR) ) {
225 m_strKey += REG_SEPARATOR;
226 }
2bda0e17
KB
227
228 m_strKey += strKey;
0b1c5a6c 229 RemoveTrailingSeparator(m_strKey);
2bda0e17
KB
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
237wxRegKey::~wxRegKey()
238{
239 Close();
240}
241
0b1c5a6c
VZ
242// ----------------------------------------------------------------------------
243// change the key name/hkey
244// ----------------------------------------------------------------------------
245
246// set the full key name
247void wxRegKey::SetName(const wxString& strKey)
248{
249 Close();
250
251 m_strKey = strKey;
fd6c844b 252 m_hRootKey = (WXHKEY) aStdKeys[ExtractKeyName(m_strKey)].hkey;
0b1c5a6c
VZ
253}
254
255// the name is relative to the parent key
256void wxRegKey::SetName(StdKey keyParent, const wxString& strKey)
257{
258 Close();
259
260 m_strKey = strKey;
261 RemoveTrailingSeparator(m_strKey);
fd6c844b 262 m_hRootKey = (WXHKEY) aStdKeys[keyParent].hkey;
0b1c5a6c
VZ
263}
264
265// the name is relative to the parent key
266void wxRegKey::SetName(const wxRegKey& keyParent, const wxString& strKey)
267{
268 Close();
269
270 // combine our name with parent's to get the full name
02569ba8 271 m_strKey = keyParent.m_strKey;
0b1c5a6c
VZ
272 if ( !strKey.IsEmpty() && strKey[0] != REG_SEPARATOR )
273 m_strKey += REG_SEPARATOR;
02569ba8 274 m_strKey += strKey;
0b1c5a6c
VZ
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
fd6c844b 282void wxRegKey::SetHkey(WXHKEY hKey)
0b1c5a6c
VZ
283{
284 Close();
285
286 m_hKey = hKey;
287}
288
2bda0e17
KB
289// ----------------------------------------------------------------------------
290// info about the key
291// ----------------------------------------------------------------------------
292
cf447356 293// returns TRUE if the key exists
2bda0e17
KB
294bool wxRegKey::Exists() const
295{
296 // opened key has to exist, try to open it if not done yet
cf447356 297 return IsOpened() ? TRUE : KeyExists(m_hRootKey, m_strKey);
2bda0e17
KB
298}
299
300// returns the full name of the key (prefix is abbreviated if bShortPrefix)
301wxString wxRegKey::GetName(bool bShortPrefix) const
302{
fd6c844b 303 StdKey key = GetStdKeyFromHkey((StdKey) m_hRootKey);
2bda0e17
KB
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
088a95f5 312#ifdef __GNUWIN32__
c86f1403
VZ
313bool wxRegKey::GetKeyInfo(size_t* pnSubKeys,
314 size_t* pnMaxKeyLen,
315 size_t* pnValues,
316 size_t* pnMaxValueLen) const
088a95f5 317#else
02569ba8
VZ
318bool wxRegKey::GetKeyInfo(ulong *pnSubKeys,
319 ulong *pnMaxKeyLen,
320 ulong *pnValues,
321 ulong *pnMaxValueLen) const
088a95f5 322#endif
02569ba8
VZ
323{
324#ifdef __WIN32__
325 m_dwLastError = ::RegQueryInfoKey
326 (
fd6c844b 327 (HKEY) m_hKey,
02569ba8
VZ
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
2bda0e17
KB
355// ----------------------------------------------------------------------------
356// operations
357// ----------------------------------------------------------------------------
358
359// opens key (it's not an error to call Open() on an already opened key)
360bool wxRegKey::Open()
361{
362 if ( IsOpened() )
cf447356 363 return TRUE;
2bda0e17 364
fd6c844b
JS
365 HKEY tmpKey;
366 m_dwLastError = RegOpenKey((HKEY) m_hRootKey, m_strKey, &tmpKey);
2bda0e17 367 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 368 wxLogSysError(m_dwLastError, _("can't open registry key '%s'"),
2bda0e17 369 GetName().c_str());
cf447356 370 return FALSE;
2bda0e17
KB
371 }
372 else
fd6c844b
JS
373 {
374 m_hKey = (WXHKEY) tmpKey;
cf447356 375 return TRUE;
fd6c844b 376 }
2bda0e17
KB
377}
378
379// creates key, failing if it exists and !bOkIfExists
380bool wxRegKey::Create(bool bOkIfExists)
381{
382 // check for existence only if asked (i.e. order is important!)
383 if ( !bOkIfExists && Exists() ) {
cf447356 384 return FALSE;
2bda0e17
KB
385 }
386
387 if ( IsOpened() )
cf447356 388 return TRUE;
2bda0e17 389
fd6c844b
JS
390 HKEY tmpKey;
391 m_dwLastError = RegCreateKey((HKEY) m_hRootKey, m_strKey, &tmpKey);
2bda0e17 392 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 393 wxLogSysError(m_dwLastError, _("can't create registry key '%s'"),
2bda0e17 394 GetName().c_str());
cf447356 395 return FALSE;
2bda0e17
KB
396 }
397 else
fd6c844b
JS
398 {
399 m_hKey = (WXHKEY) tmpKey;
cf447356 400 return TRUE;
fd6c844b 401 }
2bda0e17
KB
402}
403
0b1c5a6c
VZ
404// close the key, it's not an error to call it when not opened
405bool wxRegKey::Close()
406{
407 if ( IsOpened() ) {
fd6c844b 408 m_dwLastError = RegCloseKey((HKEY) m_hKey);
0b1c5a6c 409 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 410 wxLogSysError(m_dwLastError, _("can't close registry key '%s'"),
0b1c5a6c
VZ
411 GetName().c_str());
412
413 m_hKey = 0;
cf447356 414 return FALSE;
0b1c5a6c
VZ
415 }
416 else {
417 m_hKey = 0;
418 }
419 }
420
cf447356 421 return TRUE;
0b1c5a6c
VZ
422}
423
424// ----------------------------------------------------------------------------
425// delete keys/values
426// ----------------------------------------------------------------------------
2bda0e17
KB
427bool wxRegKey::DeleteSelf()
428{
0b1c5a6c
VZ
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;
2bda0e17
KB
440
441 wxString strKey;
442 long lIndex;
443 bool bCont = GetFirstKey(strKey, lIndex);
444 while ( bCont ) {
0b1c5a6c 445 astrSubkeys.Add(strKey);
2bda0e17
KB
446
447 bCont = GetNextKey(strKey, lIndex);
448 }
449
c86f1403
VZ
450 size_t nKeyCount = astrSubkeys.Count();
451 for ( size_t nKey = 0; nKey < nKeyCount; nKey++ ) {
0b1c5a6c
VZ
452 wxRegKey key(*this, astrSubkeys[nKey]);
453 if ( !key.DeleteSelf() )
454 return FALSE;
455 }
456
457 // now delete this key itself
2bda0e17
KB
458 Close();
459
fd6c844b 460 m_dwLastError = RegDeleteKey((HKEY) m_hRootKey, m_strKey);
2bda0e17 461 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8
VZ
462 wxLogSysError(m_dwLastError, _("can't delete key '%s'"),
463 GetName().c_str());
2bda0e17
KB
464 return FALSE;
465 }
466
467 return TRUE;
468}
469
470bool wxRegKey::DeleteKey(const char *szKey)
471{
472 if ( !Open() )
cf447356 473 return FALSE;
2bda0e17
KB
474
475 wxRegKey key(*this, szKey);
476 return key.DeleteSelf();
477}
478
479bool wxRegKey::DeleteValue(const char *szValue)
480{
481 if ( !Open() )
cf447356 482 return FALSE;
2bda0e17
KB
483
484 #ifdef __WIN32__
fd6c844b 485 m_dwLastError = RegDeleteValue((HKEY) m_hKey, szValue);
2bda0e17 486 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 487 wxLogSysError(m_dwLastError, _("can't delete value '%s' from key '%s'"),
2bda0e17 488 szValue, GetName().c_str());
cf447356 489 return FALSE;
2bda0e17
KB
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 ""
fd6c844b 496 m_dwLastError = RegSetValue((HKEY) m_hKey, NULL, REG_SZ, "", RESERVED);
2bda0e17 497 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 498 wxLogSysError(m_dwLastError, _("can't delete value of key '%s'"),
2bda0e17 499 GetName().c_str());
cf447356 500 return FALSE;
2bda0e17
KB
501 }
502 #endif //WIN16/32
503
cf447356 504 return TRUE;
2bda0e17
KB
505}
506
507// ----------------------------------------------------------------------------
508// access to values and subkeys
509// ----------------------------------------------------------------------------
510
cf447356 511// return TRUE if value exists
0b1c5a6c
VZ
512bool wxRegKey::HasValue(const char *szValue) const
513{
32c66ea2
VZ
514 // this function should be silent, so suppress possible messages from Open()
515 wxLogNull nolog;
516
0b1c5a6c
VZ
517 #ifdef __WIN32__
518 if ( CONST_CAST Open() ) {
fd6c844b 519 return RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
0b1c5a6c
VZ
520 NULL, NULL, NULL) == ERROR_SUCCESS;
521 }
522 else
cf447356 523 return FALSE;
0b1c5a6c
VZ
524 #else // WIN16
525 // only unnamed value exists
526 return IsEmpty(szValue);
527 #endif // WIN16/32
528}
529
cf447356 530// returns TRUE if this key has any subkeys
2bda0e17
KB
531bool 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
cf447356 539// returns TRUE if given subkey exists
2bda0e17
KB
540bool wxRegKey::HasSubKey(const char *szKey) const
541{
542 if ( CONST_CAST Open() )
543 return KeyExists(m_hKey, szKey);
544 else
cf447356 545 return FALSE;
2bda0e17
KB
546}
547
548wxRegKey::ValueType wxRegKey::GetValueType(const char *szValue)
549{
550 #ifdef __WIN32__
551 if ( !Open() )
552 return Type_None;
553
554 DWORD dwType;
fd6c844b 555 m_dwLastError = RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
2bda0e17
KB
556 &dwType, NULL, NULL);
557 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 558 wxLogSysError(m_dwLastError, _("can't read value of key '%s'"),
2bda0e17
KB
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__
570bool wxRegKey::SetValue(const char *szValue, long lValue)
571{
572 if ( CONST_CAST Open() ) {
fd6c844b 573 m_dwLastError = RegSetValueEx((HKEY) m_hKey, szValue, RESERVED, REG_DWORD,
2bda0e17
KB
574 (RegString)&lValue, sizeof(lValue));
575 if ( m_dwLastError == ERROR_SUCCESS )
cf447356 576 return TRUE;
2bda0e17
KB
577 }
578
02569ba8 579 wxLogSysError(m_dwLastError, _("can't set value of '%s'"),
2bda0e17 580 GetFullName(this, szValue));
cf447356 581 return FALSE;
2bda0e17
KB
582}
583
584bool 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;
fd6c844b 589 m_dwLastError = RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
2bda0e17
KB
590 &dwType, pBuf, &dwSize);
591 if ( m_dwLastError != ERROR_SUCCESS ) {
02569ba8 592 wxLogSysError(m_dwLastError, _("can't read value of key '%s'"),
2bda0e17 593 GetName().c_str());
cf447356 594 return FALSE;
2bda0e17
KB
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
cf447356 601 return TRUE;
2bda0e17
KB
602 }
603 }
604 else
cf447356 605 return FALSE;
2bda0e17
KB
606}
607
608#endif //Win32
609
610bool 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;
fd6c844b 616 m_dwLastError = RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
2bda0e17
KB
617 &dwType, NULL, &dwSize);
618 if ( m_dwLastError == ERROR_SUCCESS ) {
619 RegString pBuf = (RegString)strValue.GetWriteBuf(dwSize);
fd6c844b 620 m_dwLastError = RegQueryValueEx((HKEY) m_hKey, szValue, RESERVED,
2bda0e17 621 &dwType, pBuf, &dwSize);
44a6c8e6 622 strValue.UngetWriteBuf();
2bda0e17
KB
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
cf447356 628 return TRUE;
2bda0e17
KB
629 }
630 }
631 #else //WIN16
632 // named registry values don't exist in Win16
633 wxASSERT( IsEmpty(szValue) );
634
fd6c844b 635 m_dwLastError = RegQueryValue((HKEY) m_hKey, 0, strValue.GetWriteBuf(256), &l);
44a6c8e6 636 strValue.UngetWriteBuf();
2bda0e17 637 if ( m_dwLastError == ERROR_SUCCESS )
cf447356 638 return TRUE;
2bda0e17
KB
639 #endif //WIN16/32
640 }
641
02569ba8 642 wxLogSysError(m_dwLastError, _("can't read value of '%s'"),
2bda0e17 643 GetFullName(this, szValue));
cf447356 644 return FALSE;
2bda0e17
KB
645}
646
647bool wxRegKey::SetValue(const char *szValue, const wxString& strValue)
648{
649 if ( CONST_CAST Open() ) {
650 #ifdef __WIN32__
fd6c844b 651 m_dwLastError = RegSetValueEx((HKEY) m_hKey, szValue, RESERVED, REG_SZ,
2bda0e17
KB
652 (RegString)strValue.c_str(),
653 strValue.Len() + 1);
654 if ( m_dwLastError == ERROR_SUCCESS )
cf447356 655 return TRUE;
2bda0e17
KB
656 #else //WIN16
657 // named registry values don't exist in Win16
658 wxASSERT( IsEmpty(szValue) );
659
fd6c844b 660 m_dwLastError = RegSetValue((HKEY) m_hKey, NULL, REG_SZ, strValue, NULL);
2bda0e17 661 if ( m_dwLastError == ERROR_SUCCESS )
cf447356 662 return TRUE;
2bda0e17
KB
663 #endif //WIN16/32
664 }
665
02569ba8 666 wxLogSysError(m_dwLastError, _("can't set value of '%s'"),
2bda0e17 667 GetFullName(this, szValue));
cf447356 668 return FALSE;
2bda0e17
KB
669}
670
671wxRegKey::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
2bda0e17
KB
684bool wxRegKey::GetFirstValue(wxString& strValueName, long& lIndex)
685{
686 if ( !Open() )
cf447356 687 return FALSE;
2bda0e17
KB
688
689 lIndex = 0;
0b1c5a6c 690 return GetNextValue(strValueName, lIndex);
2bda0e17
KB
691}
692
693bool wxRegKey::GetNextValue(wxString& strValueName, long& lIndex) const
694{
695 wxASSERT( IsOpened() );
2bda0e17 696
0b1c5a6c
VZ
697 // are we already at the end of enumeration?
698 if ( lIndex == -1 )
cf447356 699 return FALSE;
2bda0e17 700
0b1c5a6c
VZ
701 #ifdef __WIN32__
702 char szValueName[1024]; // @@ use RegQueryInfoKey...
703 DWORD dwValueLen = WXSIZEOF(szValueName);
2bda0e17 704
0b1c5a6c 705 lIndex++;
fd6c844b 706 m_dwLastError = RegEnumValue((HKEY) m_hKey, lIndex,
0b1c5a6c
VZ
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 {
02569ba8 719 wxLogSysError(m_dwLastError, _("can't enumerate values of key '%s'"),
0b1c5a6c
VZ
720 GetName().c_str());
721 }
722
cf447356 723 return FALSE;
2bda0e17
KB
724 }
725
0b1c5a6c
VZ
726 strValueName = szValueName;
727 #else //WIN16
728 // only one unnamed value
729 wxASSERT( lIndex == 0 );
2bda0e17 730
0b1c5a6c
VZ
731 lIndex = -1;
732 strValueName.Empty();
733 #endif
734
cf447356 735 return TRUE;
2bda0e17 736}
2bda0e17
KB
737
738bool wxRegKey::GetFirstKey(wxString& strKeyName, long& lIndex)
739{
740 if ( !Open() )
cf447356 741 return FALSE;
2bda0e17 742
2bda0e17 743 lIndex = 0;
0b1c5a6c 744 return GetNextKey(strKeyName, lIndex);
2bda0e17
KB
745}
746
747bool wxRegKey::GetNextKey(wxString& strKeyName, long& lIndex) const
748{
749 wxASSERT( IsOpened() );
0b1c5a6c
VZ
750
751 // are we already at the end of enumeration?
752 if ( lIndex == -1 )
cf447356 753 return FALSE;
2bda0e17
KB
754
755 char szKeyName[_MAX_PATH + 1];
fd6c844b 756 m_dwLastError = RegEnumKey((HKEY) m_hKey, lIndex++, szKeyName, WXSIZEOF(szKeyName));
2bda0e17
KB
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 {
02569ba8 764 wxLogSysError(m_dwLastError, _("can't enumerate subkeys of key '%s'"),
2bda0e17
KB
765 GetName().c_str());
766 }
767
cf447356 768 return FALSE;
2bda0e17
KB
769 }
770
771 strKeyName = szKeyName;
cf447356 772 return TRUE;
2bda0e17
KB
773}
774
775// ============================================================================
1880e452 776// implementation of global private functions
2bda0e17 777// ============================================================================
fd6c844b 778bool KeyExists(WXHKEY hRootKey, const char *szKey)
2bda0e17
KB
779{
780 HKEY hkeyDummy;
fd6c844b 781 if ( RegOpenKey( (HKEY) hRootKey, szKey, &hkeyDummy) == ERROR_SUCCESS ) {
2bda0e17 782 RegCloseKey(hkeyDummy);
cf447356 783 return TRUE;
2bda0e17
KB
784 }
785 else
cf447356 786 return FALSE;
2bda0e17
KB
787}
788
789const 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();
0b1c5a6c
VZ
797}
798
799void RemoveTrailingSeparator(wxString& str)
800{
801 if ( !str.IsEmpty() && str.Last() == REG_SEPARATOR )
802 str.Truncate(str.Len() - 1);
803}
1880e452
VZ
804
805// ============================================================================
806// global public functions
807// ============================================================================
808
809bool 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);
41286812 821 if ( key.Open() ) {
1880e452
VZ
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
830bool 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);
41286812 844 if ( key.Open() ) {
1880e452
VZ
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
853bool 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);
41286812 867 if ( key.Open() ) {
1880e452
VZ
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;
41286812
VZ
874}
875
876bool 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(','),
040f0110 894 strIndex = strIcon.Right(',');
41286812 895
040f0110
VZ
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 }
41286812
VZ
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
925bool 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}
fd6c844b
JS
941
942