]> git.saurik.com Git - wxWidgets.git/blob - src/msw/registry.cpp
added some wxMSW stuff
[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 // ============================================================================
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
52 typedef 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
60 static struct
61 {
62 HKEY hkey;
63 const char *szName;
64 const char *szShortName;
65 }
66 aStdKeys[] =
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
101 static bool KeyExists(HKEY hRootKey, const char *szKey);
102
103 // combines value and key name (uses static buffer!)
104 static 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
115 const 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.
119 const 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
127 const 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
135 wxRegKey::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
163 wxRegKey::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
179 wxRegKey::wxRegKey()
180 {
181 m_hKey = 0;
182 m_hRootKey = aStdKeys[HKCR].hkey;
183 m_dwLastError = 0;
184 }
185
186 wxRegKey::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
194 wxRegKey::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
205 wxRegKey::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
222 wxRegKey::~wxRegKey()
223 {
224 Close();
225 }
226
227 // ----------------------------------------------------------------------------
228 // info about the key
229 // ----------------------------------------------------------------------------
230
231 // returns TRUE if the key exists
232 bool 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)
239 wxString 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)
255 bool 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
271 bool 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
291 bool 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
318 bool wxRegKey::DeleteKey(const char *szKey)
319 {
320 if ( !Open() )
321 return FALSE;
322
323 wxRegKey key(*this, szKey);
324 return key.DeleteSelf();
325 }
326
327 bool 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
356 bool 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
380 bool 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
389 bool 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
397 wxRegKey::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__
419 bool 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
433 bool 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
459 bool 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
494 bool 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
518 wxRegKey::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__
532 bool 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
563 bool 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
596 bool 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
622 bool 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 // ============================================================================
651 bool 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
662 const 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 }