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