Use angle brackets for system headers
[TortoiseGit.git] / src / Utils / registry.h
blob8d60ebf06a248cfa0398b732cfb1e264430ff749
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2011 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #pragma once
20 #include <string>
21 #include <memory>
22 #include <shlwapi.h>
23 #include "tstring.h"
24 #include "auto_buffer.h"
25 #include "FormatMessageWrapper.h"
27 #ifndef ASSERT
28 #define ASSERT(x)
29 #endif
31 /**
32 * \ingroup Utils
33 * Base class for the registry classes.
35 * \par requirements
36 * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later
37 * - import library Shlwapi.lib
40 template<class S>
41 class CRegBaseCommon
43 protected:
45 /**
46 * String type specific operations.
49 virtual LPCTSTR GetPlainString (const S& s) const = 0;
50 virtual DWORD GetLength (const S& s) const = 0;
52 public: //methods
54 /** Default constructor.
56 CRegBaseCommon();
57 /**
58 * Constructor.
59 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
60 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
61 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
63 CRegBaseCommon(const S& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
65 /**
66 * Removes the whole registry key including all values. So if you set the registry
67 * entry to be HKCU\Software\Company\Product\key\value there will only be
68 * HKCU\Software\Company\Product key in the registry.
69 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
71 DWORD removeKey();
72 /**
73 * Removes the value of the registry object. If you set the registry entry to
74 * be HKCU\Software\Company\Product\key\value there will only be
75 * HKCU\Software\Company\Product\key\ in the registry.
76 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
78 LONG removeValue();
80 /**
81 * Returns the string of the last error occurred.
83 virtual S getErrorString()
85 CFormatMessageWrapper errorMessage(LastError);
86 S result ((LPCTSTR)errorMessage);
87 return result;
90 /// get failure info for last operation
92 LONG GetLastError() const
94 return LastError;
97 /// used in subclass templates to specify the correct string type
99 typedef S StringT;
101 protected:
103 //members
104 HKEY m_base; ///< handle to the registry base
105 S m_key; ///< the name of the value
106 S m_path; ///< the path to the key
107 LONG LastError; ///< the value of the last error occurred
108 REGSAM m_sam; ///< the security attributes to pass to the registry command
110 bool m_read; ///< indicates if the value has already been read from the registry
111 bool m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry
112 bool m_exists; ///< true, if the registry actually exists
115 // implement CRegBaseCommon<> members
117 template<class S>
118 CRegBaseCommon<S>::CRegBaseCommon()
119 : m_base (HKEY_CURRENT_USER)
120 , m_key()
121 , m_path()
122 , LastError (ERROR_SUCCESS)
123 , m_sam (0)
124 , m_read (false)
125 , m_force (false)
126 , m_exists (false)
130 template<class S>
131 CRegBaseCommon<S>::CRegBaseCommon (const S& key, bool force, HKEY base, REGSAM sam)
132 : m_base (base)
133 , m_key (key)
134 , m_path()
135 , LastError (ERROR_SUCCESS)
136 , m_sam (sam)
137 , m_read (false)
138 , m_force (force)
139 , m_exists (false)
143 template<class S>
144 DWORD CRegBaseCommon<S>::removeKey()
146 m_exists = false;
147 m_read = true;
149 HKEY hKey = NULL;
150 RegOpenKeyEx (m_base, GetPlainString (m_path), 0, KEY_WRITE|m_sam, &hKey);
151 return SHDeleteKey(m_base, GetPlainString (m_path));
154 template<class S>
155 LONG CRegBaseCommon<S>::removeValue()
157 m_exists = false;
158 m_read = true;
160 HKEY hKey = NULL;
161 RegOpenKeyEx(m_base, GetPlainString (m_path), 0, KEY_WRITE|m_sam, &hKey);
162 return RegDeleteValue(hKey, GetPlainString (m_key));
166 * \ingroup Utils
167 * Base class for MFC type registry classes.
170 #ifdef __CSTRINGT_H__
171 class CRegBase : public CRegBaseCommon<CString>
173 protected:
176 * String type specific operations.
179 virtual LPCTSTR GetPlainString (const CString& s) const {return (LPCTSTR)s;}
180 virtual DWORD GetLength (const CString& s) const {return s.GetLength();}
182 public: //methods
184 /** Default constructor.
186 CRegBase();
188 * Constructor.
189 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
190 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
191 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
193 CRegBase(const CString& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
196 * Returns the string of the last error occurred.
198 CString getErrorString()
200 CString error = CRegBaseCommon<CString>::getErrorString();
201 #if defined IDS_REG_ERROR
202 CString sTemp;
203 sTemp.FormatMessage(IDS_REG_ERROR, (LPCTSTR)m_key, (LPCTSTR)error);
204 return sTemp;
205 #else
206 return error;
207 #endif
210 #endif
215 * \ingroup Utils
216 * Base class for STL string type registry classes.
219 class CRegStdBase : public CRegBaseCommon<tstring>
221 protected:
224 * String type specific operations.
227 virtual LPCTSTR GetPlainString (const tstring& s) const {return s.c_str();}
228 virtual DWORD GetLength (const tstring& s) const {return static_cast<DWORD>(s.size());}
230 public: //methods
232 /** Default constructor.
234 CRegStdBase();
236 * Constructor.
237 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
238 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
239 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
241 CRegStdBase(const tstring& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
245 * \ingroup Utils
246 * DWORD value in registry. with this class you can use DWORD values in registry
247 * like normal DWORD variables in your program.
248 * Usage:
249 * in your header file, declare your registry DWORD variable:
250 * \code
251 * CRegDWORD regvalue;
252 * \endcode
253 * next initialize the variable e.g. in the constructor of your class:
254 * \code
255 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
256 * \endcode
257 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
258 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
259 * an error occurred during read from the registry, a default
260 * value of 100 is used when accessing the variable.
261 * now the variable can be used like any other DWORD variable:
262 * \code
263 * regvalue = 200; //stores the value 200 in the registry
264 * int temp = regvalue + 300; //temp has value 500 now
265 * regvalue += 300; //now the registry has the value 500 too
266 * \endcode
267 * to avoid too much access to the registry the value is cached inside the object.
268 * once the value is read, no more read accesses to the registry will be made.
269 * this means the variable will contain a wrong value if the corresponding registry
270 * entry is changed by anything else than this variable! If you think that could happen
271 * then use
272 * \code
273 * regvalue.read();
274 * \endcode
275 * to force a refresh of the variable with the registry.
276 * a write to the registry is only made if the new value assigned with the variable
277 * is different than the last assigned value.
278 * to force a write use the method write();
279 * another option to force reads and writes to the registry is to specify TRUE as the
280 * third parameter in the constructor.
282 template<class T, class Base>
283 class CRegTypedBase : public Base
285 private:
287 T m_value; ///< the cached value of the registry
288 T m_defaultvalue; ///< the default value to use
291 * time stamp of the last registry lookup, i.e \ref read() call
294 DWORD lastRead;
297 * \ref read() will be called, if \ref lastRead differs from the
298 * current time stamp by more than this.
299 * (DWORD)(-1) -> no automatic refresh.
302 DWORD lookupInterval;
305 * Check time stamps etc.
306 * If the current data is out-dated, reset the \ref m_read flag.
309 void HandleAutoRefresh();
312 * sub-classes must provide type-specific code to extract data from
313 * and write data to an open registry key.
316 virtual void InternalRead (HKEY hKey, T& value) = 0;
317 virtual void InternalWrite (HKEY hKey, const T& value) = 0;
319 public:
322 * Make the value type accessible to others.
325 typedef T ValueT;
328 * Constructor.
329 * We use this instead of a default constructor because not all
330 * data types may provide an adequate default constructor.
332 CRegTypedBase(const T& def);
335 * Constructor.
336 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
337 * \param def the default value used when the key does not exist or a read error occurred
338 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
339 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
341 CRegTypedBase(const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
344 * Constructor.
345 * \param updateInterval time in msec between registry lookups caused by operator const T&
346 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
347 * \param def the default value used when the key does not exist or a read error occurred
348 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
349 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
351 CRegTypedBase(DWORD updateInterval, const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
354 * reads the assigned value from the registry. Use this method only if you think the registry
355 * value could have been altered without using the CRegDWORD object.
356 * \return the read value
358 void read(); ///< reads the value from the registry
359 void write(); ///< writes the value to the registry
361 bool exists(); ///< test whether registry entry exits
362 const T& defaultValue() const; ///< return the default passed to the constructor
365 * Data access.
368 operator const T&();
369 CRegTypedBase<T,Base>& operator=(const T& rhs);
372 // implement CRegTypedBase<> members
374 template<class T, class Base>
375 void CRegTypedBase<T, Base>::HandleAutoRefresh()
377 if (m_read && (lookupInterval != (DWORD)(-1)))
379 DWORD currentTime = GetTickCount();
380 if ( (currentTime < lastRead)
381 || (currentTime > lastRead + lookupInterval))
383 m_read = false;
388 template<class T, class Base>
389 CRegTypedBase<T, Base>::CRegTypedBase (const T& def)
390 : m_value (def)
391 , m_defaultvalue (def)
392 , lastRead (0)
393 , lookupInterval ((DWORD)-1)
397 template<class T, class Base>
398 CRegTypedBase<T, Base>::CRegTypedBase (const typename Base::StringT& key, const T& def, bool force, HKEY base, REGSAM sam)
399 : Base (key, force, base, sam)
400 , m_value (def)
401 , m_defaultvalue (def)
402 , lastRead (0)
403 , lookupInterval ((DWORD)-1)
407 template<class T, class Base>
408 CRegTypedBase<T, Base>::CRegTypedBase (DWORD lookupInterval, const typename Base::StringT& key, const T& def, bool force, HKEY base, REGSAM sam)
409 : Base (key, force, base, sam)
410 , m_value (def)
411 , m_defaultvalue (def)
412 , lastRead (0)
413 , lookupInterval (lookupInterval)
417 template<class T, class Base>
418 void CRegTypedBase<T, Base>::read()
420 m_value = m_defaultvalue;
421 m_exists = false;
423 HKEY hKey = NULL;
424 if ((LastError = RegOpenKeyEx (m_base, GetPlainString (m_path), 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|m_sam, &hKey))==ERROR_SUCCESS)
426 m_read = true;
428 T value = m_defaultvalue;
429 InternalRead (hKey, value);
431 if (LastError ==ERROR_SUCCESS)
433 m_exists = true;
434 m_value = value;
437 LastError = RegCloseKey(hKey);
440 lastRead = GetTickCount();
443 template<class T, class Base>
444 void CRegTypedBase<T, Base>::write()
446 HKEY hKey = NULL;
448 DWORD disp = 0;
449 if ((LastError = RegCreateKeyEx(m_base, GetPlainString (m_path), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE|m_sam, NULL, &hKey, &disp))!=ERROR_SUCCESS)
451 return;
454 InternalWrite (hKey, m_value);
455 if (LastError ==ERROR_SUCCESS)
457 m_read = true;
458 m_exists = true;
460 LastError = RegCloseKey(hKey);
462 lastRead = GetTickCount();
465 template<class T, class Base>
466 bool CRegTypedBase<T, Base>::exists()
468 if (!m_read && (LastError == ERROR_SUCCESS))
469 read();
471 return m_exists;
474 template<class T, class Base>
475 const T& CRegTypedBase<T, Base>::defaultValue() const
477 return m_defaultvalue;
480 template<class T, class Base>
481 CRegTypedBase<T, Base>::operator const T&()
483 HandleAutoRefresh();
484 if ((m_read)&&(!m_force))
486 LastError = ERROR_SUCCESS;
488 else
490 read();
493 return m_value;
496 template<class T, class Base>
497 CRegTypedBase<T, Base>& CRegTypedBase<T, Base>::operator =(const T& d)
499 if (m_read && (d == m_value) && !m_force)
501 //no write to the registry required, its the same value
502 LastError = ERROR_SUCCESS;
503 return *this;
505 m_value = d;
506 write();
507 return *this;
511 * \ingroup Utils
512 * DWORD value in registry. with this class you can use DWORD values in registry
513 * like normal DWORD variables in your program.
514 * Usage:
515 * in your header file, declare your registry DWORD variable:
516 * \code
517 * CRegDWORD regvalue;
518 * \endcode
519 * next initialize the variable e.g. in the constructor of your class:
520 * \code
521 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
522 * \endcode
523 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
524 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
525 * an error occurred during read from the registry, a default
526 * value of 100 is used when accessing the variable.
527 * now the variable can be used like any other DWORD variable:
528 * \code
529 * regvalue = 200; //stores the value 200 in the registry
530 * int temp = regvalue + 300; //temp has value 500 now
531 * regvalue += 300; //now the registry has the value 500 too
532 * \endcode
533 * to avoid too much access to the registry the value is cached inside the object.
534 * once the value is read, no more read accesses to the registry will be made.
535 * this means the variable will contain a wrong value if the corresponding registry
536 * entry is changed by anything else than this variable! If you think that could happen
537 * then use
538 * \code
539 * regvalue.read();
540 * \endcode
541 * to force a refresh of the variable with the registry.
542 * a write to the registry is only made if the new value assigned with the variable
543 * is different than the last assigned value.
544 * to force a write use the method write();
545 * another option to force reads and writes to the registry is to specify TRUE as the
546 * third parameter in the constructor.
548 template<class Base>
549 class CRegDWORDCommon : public CRegTypedBase<DWORD,Base>
551 private:
554 * provide type-specific code to extract data from and write data to an open registry key.
557 virtual void InternalRead (HKEY hKey, DWORD& value);
558 virtual void InternalWrite (HKEY hKey, const DWORD& value);
560 public:
562 CRegDWORDCommon(void);
564 * Constructor.
565 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
566 * \param def the default value used when the key does not exist or a read error occurred
567 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
568 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
570 CRegDWORDCommon(const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
571 CRegDWORDCommon(DWORD lookupInterval, const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
573 CRegDWORDCommon& operator=(DWORD rhs) {CRegTypedBase<DWORD, Base>::operator =(rhs); return *this;}
574 CRegDWORDCommon& operator+=(DWORD d) { return *this = *this + d;}
575 CRegDWORDCommon& operator-=(DWORD d) { return *this = *this - d;}
576 CRegDWORDCommon& operator*=(DWORD d) { return *this = *this * d;}
577 CRegDWORDCommon& operator/=(DWORD d) { return *this = *this / d;}
578 CRegDWORDCommon& operator%=(DWORD d) { return *this = *this % d;}
579 CRegDWORDCommon& operator<<=(DWORD d) { return *this = *this << d;}
580 CRegDWORDCommon& operator>>=(DWORD d) { return *this = *this >> d;}
581 CRegDWORDCommon& operator&=(DWORD d) { return *this = *this & d;}
582 CRegDWORDCommon& operator|=(DWORD d) { return *this = *this | d;}
583 CRegDWORDCommon& operator^=(DWORD d) { return *this = *this ^ d;}
586 // implement CRegDWORDCommon<> methods
588 template<class Base>
589 CRegDWORDCommon<Base>::CRegDWORDCommon(void)
590 : CRegTypedBase<DWORD, Base>(0)
594 template<class Base>
595 CRegDWORDCommon<Base>::CRegDWORDCommon(const typename Base::StringT& key, DWORD def, bool force, HKEY base, REGSAM sam)
596 : CRegTypedBase<DWORD, Base> (key, def, force, base, sam)
600 template<class Base>
601 CRegDWORDCommon<Base>::CRegDWORDCommon(DWORD lookupInterval, const typename Base::StringT& key, DWORD def, bool force, HKEY base, REGSAM sam)
602 : CRegTypedBase<DWORD, Base> (lookupInterval, key, def, force, base, sam)
606 template<class Base>
607 void CRegDWORDCommon<Base>::InternalRead (HKEY hKey, DWORD& value)
609 DWORD size = sizeof(value);
610 DWORD type = 0;
611 if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) &value, &size))==ERROR_SUCCESS)
613 ASSERT(type==REG_DWORD);
617 template<class Base>
618 void CRegDWORDCommon<Base>::InternalWrite (HKEY hKey, const DWORD& value)
620 LastError = RegSetValueEx (hKey, GetPlainString (m_key), 0, REG_DWORD,(const BYTE*) &value, sizeof(value));
624 * \ingroup Utils
625 * CString value in registry. with this class you can use CString values in registry
626 * almost like normal CString variables in your program.
627 * Usage:
628 * in your header file, declare your registry CString variable:
629 * \code
630 * CRegString regvalue;
631 * \endcode
632 * next initialize the variable e.g. in the constructor of your class:
633 * \code
634 * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");
635 * \endcode
636 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
637 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
638 * an error occurred during read from the registry, a default
639 * value of "default" is used when accessing the variable.
640 * now the variable can be used like any other CString variable:
641 * \code
642 * regvalue = "some string"; //stores the value "some string" in the registry
643 * CString temp = regvalue + "!!"; //temp has value "some string!!" now
644 * \endcode
645 * to use the normal methods of the CString class, just typecast the CRegString to a CString
646 * and do whatever you want with the string:
647 * \code
648 * ((CString)regvalue).GetLength();
649 * ((CString)regvalue).Trim();
650 * \endcode
651 * please be aware that in the second line the change in the string won't be written
652 * to the registry! To force a write use the write() method. A write() is only needed
653 * if you change the String with Methods not overloaded by CRegString.
654 * to avoid too much access to the registry the value is cached inside the object.
655 * once the value is read, no more read accesses to the registry will be made.
656 * this means the variable will contain a wrong value if the corresponding registry
657 * entry is changed by anything else than this variable! If you think that could happen
658 * then use
659 * \code
660 * regvalue.read();
661 * \endcode
662 * to force a refresh of the variable with the registry.
663 * a write to the registry is only made if the new value assigned with the variable
664 * is different than the last assigned value.
665 * to force a write use the method write();
666 * another option to force reads and writes to the registry is to specify TRUE as the
667 * third parameter in the constructor.
669 template<class Base>
670 class CRegStringCommon : public CRegTypedBase<typename Base::StringT, Base>
672 private:
675 * provide type-specific code to extract data from and write data to an open registry key.
678 virtual void InternalRead (HKEY hKey, typename Base::StringT& value);
679 virtual void InternalWrite (HKEY hKey, const typename Base::StringT& value);
681 public:
682 CRegStringCommon();
684 * Constructor.
685 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
686 * \param def the default value used when the key does not exist or a read error occurred
687 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
688 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
690 CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def = _T(""), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
691 CRegStringCommon(DWORD lookupInterval, const typename Base::StringT& key, const typename Base::StringT& def = _T(""), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
693 CRegStringCommon& operator=(const typename Base::StringT& rhs) {CRegTypedBase<StringT, Base>::operator =(rhs); return *this;}
694 CRegStringCommon& operator+=(const typename Base::StringT& s) { return *this = (typename Base::StringT)*this + s; }
697 // implement CRegDWORD<> methods
699 template<class Base>
700 CRegStringCommon<Base>::CRegStringCommon(void)
701 : CRegTypedBase<typename Base::StringT, Base>(typename Base::StringT())
705 template<class Base>
706 CRegStringCommon<Base>::CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base, REGSAM sam)
707 : CRegTypedBase<typename Base::StringT, Base> (key, def, force, base, sam)
711 template<class Base>
712 CRegStringCommon<Base>::CRegStringCommon(DWORD lookupInterval, const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base, REGSAM sam)
713 : CRegTypedBase<typename Base::StringT, Base> (lookupInterval, key, def, force, base, sam)
717 template<class Base>
718 void CRegStringCommon<Base>::InternalRead (HKEY hKey, typename Base::StringT& value)
720 DWORD size = 0;
721 DWORD type = 0;
722 LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, NULL, &size);
724 if (LastError == ERROR_SUCCESS)
726 auto_buffer<TCHAR> pStr (size);
727 if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) pStr.get(), &size))==ERROR_SUCCESS)
729 ASSERT(type==REG_SZ || type==REG_EXPAND_SZ);
730 value = StringT (pStr.get());
735 template<class Base>
736 void CRegStringCommon<Base>::InternalWrite (HKEY hKey, const typename Base::StringT& value)
738 LastError = RegSetValueEx(hKey, GetPlainString (m_key), 0, REG_SZ, (BYTE *)GetPlainString (value), (GetLength(value)+1)*sizeof (TCHAR));
742 * \ingroup Utils
743 * CRect value in registry. with this class you can use CRect values in registry
744 * almost like normal CRect variables in your program.
745 * Usage:
746 * in your header file, declare your registry CString variable:
747 * \code
748 * CRegRect regvalue;
749 * \endcode
750 * next initialize the variable e.g. in the constructor of your class:
751 * \code
752 * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));
753 * \endcode
754 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
755 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
756 * an error occurred during read from the registry, a default
757 * value of 100,100,200,200 is used when accessing the variable.
758 * now the variable can be used like any other CRect variable:
759 * \code
760 * regvalue = CRect(40,20,300,500); //stores the value in the registry
761 * CRect temp = regvalue + CPoint(1,1);
762 * temp |= CSize(5,5);
763 * \endcode
764 * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect
765 * and do whatever you want with the rect:
766 * \code
767 * ((CRect)regvalue).MoveToX(100);
768 * ((CRect)regvalue).DeflateRect(10,10);
769 * \endcode
770 * please be aware that in the second line the change in the CRect won't be written
771 * to the registry! To force a write use the write() method. A write() is only needed
772 * if you change the CRect with Methods not overloaded by CRegRect.
773 * to avoid too much access to the registry the value is cached inside the object.
774 * once the value is read, no more read accesses to the registry will be made.
775 * this means the variable will contain a wrong value if the corresponding registry
776 * entry is changed by anything else than this variable! If you think that could happen
777 * then use
778 * \code
779 * regvalue.read();
780 * \endcode
781 * to force a refresh of the variable with the registry.
782 * a write to the registry is only made if the new value assigned with the variable
783 * is different than the last assigned value.
784 * to force a write use the method write();
785 * another option to force reads and writes to the registry is to specify TRUE as the
786 * third parameter in the constructor.
789 #ifdef __ATLTYPES_H__ // defines CRect
790 class CRegRect : public CRegTypedBase<CRect, CRegBase>
792 private:
795 * provide type-specific code to extract data from and write data to an open registry key.
798 virtual void InternalRead (HKEY hKey, CRect& value);
799 virtual void InternalWrite (HKEY hKey, const CRect& value);
801 public:
802 CRegRect();
804 * Constructor.
805 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
806 * \param def the default value used when the key does not exist or a read error occurred
807 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
808 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
810 CRegRect(const CString& key, const CRect& def = CRect(), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
811 ~CRegRect(void);
813 CRegRect& operator=(const CRect& rhs) {CRegTypedBase<CRect, CRegBase>::operator =(rhs); return *this;}
814 operator LPCRECT() { return (LPCRECT)(CRect)*this; }
815 operator LPRECT() { return (LPRECT)(CRect)*this; }
816 CRegRect& operator+=(POINT r) { return *this = (CRect)*this + r;}
817 CRegRect& operator+=(SIZE r) { return *this = (CRect)*this + r;}
818 CRegRect& operator+=(LPCRECT r) { return *this = (CRect)*this + r;}
819 CRegRect& operator-=(POINT r) { return *this = (CRect)*this - r;}
820 CRegRect& operator-=(SIZE r) { return *this = (CRect)*this - r;}
821 CRegRect& operator-=(LPCRECT r) { return *this = (CRect)*this - r;}
823 CRegRect& operator&=(CRect r) { return *this = r & *this;}
824 CRegRect& operator|=(CRect r) { return *this = r | *this;}
826 #endif
829 * \ingroup Utils
830 * CPoint value in registry. with this class you can use CPoint values in registry
831 * almost like normal CPoint variables in your program.
832 * Usage:
833 * in your header file, declare your registry CPoint variable:
834 * \code
835 * CRegPoint regvalue;
836 * \endcode
837 * next initialize the variable e.g. in the constructor of your class:
838 * \code
839 * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));
840 * \endcode
841 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
842 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
843 * an error occurred during read from the registry, a default
844 * value of 100,100 is used when accessing the variable.
845 * now the variable can be used like any other CPoint variable:
846 * \code
847 * regvalue = CPoint(40,20); //stores the value in the registry
848 * CPoint temp = regvalue + CPoint(1,1);
849 * temp += CSize(5,5);
850 * \endcode
851 * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint
852 * and do whatever you want with the point:
853 * \code
854 * ((CRect)regvalue).Offset(100,10);
855 * \endcode
856 * please be aware that in the above example the change in the CPoint won't be written
857 * to the registry! To force a write use the write() method. A write() is only needed
858 * if you change the CPoint with Methods not overloaded by CRegPoint.
859 * to avoid too much access to the registry the value is cached inside the object.
860 * once the value is read, no more read accesses to the registry will be made.
861 * this means the variable will contain a wrong value if the corresponding registry
862 * entry is changed by anything else than this variable! If you think that could happen
863 * then use
864 * \code
865 * regvalue.read();
866 * \endcode
867 * to force a refresh of the variable with the registry.
868 * a write to the registry is only made if the new value assigned with the variable
869 * is different than the last assigned value.
870 * to force a write use the method write();
871 * another option to force reads and writes to the registry is to specify TRUE as the
872 * third parameter in the constructor.
875 #ifdef __ATLTYPES_H__ // defines CPoint
876 class CRegPoint : public CRegTypedBase<CPoint, CRegBase>
878 private:
881 * provide type-specific code to extract data from and write data to an open registry key.
884 virtual void InternalRead (HKEY hKey, CPoint& value);
885 virtual void InternalWrite (HKEY hKey, const CPoint& value);
887 public:
888 CRegPoint();
890 * Constructor.
891 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
892 * \param def the default value used when the key does not exist or a read error occurred
893 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
894 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
896 CRegPoint(const CString& key, const CPoint& def = CPoint(), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
897 ~CRegPoint(void);
899 CRegPoint& operator=(const CPoint& rhs) {CRegTypedBase<CPoint, CRegBase>::operator =(rhs); return *this;}
900 CRegPoint& operator+=(CPoint p) { return *this = p + *this; }
901 CRegPoint& operator-=(CPoint p) { return *this = p - *this; }
903 #endif
906 * \ingroup Utils
907 * Manages a registry key (not a value). Provides methods to create and remove the
908 * key and to query the list of values and sub keys.
911 #ifdef __AFXCOLL_H__ // defines CStringList
912 class CRegistryKey
914 public: //methods
916 * Constructor.
917 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey"
918 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
920 CRegistryKey(const CString& key, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
921 ~CRegistryKey();
924 * Creates the registry key if it does not already exist.
925 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
927 DWORD createKey();
929 * Removes the whole registry key including all values. So if you set the registry
930 * entry to be HKCU\Software\Company\Product\key there will only be
931 * HKCU\Software\Company\Product key in the registry.
932 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
934 DWORD removeKey();
936 bool getValues(CStringList& values); ///< returns the list of values
937 bool getSubKeys(CStringList& subkeys); ///< returns the list of sub keys
939 public: //members
940 HKEY m_base; ///< handle to the registry base
941 HKEY m_hKey; ///< handle to the open registry key
942 REGSAM m_sam; ///< the security attributes to pass to the registry command
943 CString m_path; ///< the path to the key
945 #endif
947 #ifdef _MAP_
948 template<class T>
949 class CKeyList
951 private:
953 /// constructor parameters
955 typename T::StringT key;
956 typename T::ValueT defaultValue;
957 HKEY base;
959 /// per-index defaults
961 typedef std::map<int, typename T::ValueT> TDefaults;
962 TDefaults defaults;
964 /// the indices accessed so far
966 typedef std::map<int, T*> TElements;
967 mutable TElements elements;
969 /// auto-insert
971 const typename T::ValueT& GetDefault (int index) const;
972 T& GetAt (int index) const;
974 public:
976 /// construction
978 CKeyList (const typename T::StringT& key, const typename T::ValueT& defaultValue, HKEY base = HKEY_CURRENT_USER)
979 : key (key)
980 , defaultValue (defaultValue)
981 , base (base)
985 /// destruction: delete all elements
987 ~CKeyList()
989 for ( TElements::iterator iter = elements.begin()
990 , end = elements.end()
991 ; iter != end
992 ; ++iter)
994 delete iter->second;
998 /// data access
1000 const T& operator[] (int index) const
1002 return GetAt (index);
1005 T& operator[] (int index)
1007 return GetAt (index);
1010 const TDefaults& GetDefaults() const
1012 return defaults;
1015 TDefaults& GetDefaults()
1017 return defaults;
1020 const typename T::ValueT& GetDefault() const
1022 return defaultValue;
1026 /// auto-insert
1028 template<class T>
1029 const typename T::ValueT& CKeyList<T>::GetDefault (int index) const
1031 TDefaults::const_iterator iter = defaults.find (index);
1032 return iter == defaults.end() ? defaultValue : iter->second;
1035 template<class T>
1036 T& CKeyList<T>::GetAt (int index) const
1038 TElements::iterator iter = elements.find (index);
1039 if (iter == elements.end())
1041 TCHAR buffer [10];
1042 _itot_s (index, buffer, 10);
1043 typename T::StringT indexKey = key + _T ('\\') + buffer;
1045 T* newElement = new T (indexKey, GetDefault (index), false, base);
1046 iter = elements.insert (std::make_pair (index, newElement)).first;
1049 return *iter->second;
1052 #endif
1055 * Instantiate templates for common (data type, string type) combinations.
1058 #ifdef __CSTRINGT_H__
1059 CRegDWORDCommon<CRegBase>;
1060 typedef CRegDWORDCommon<CRegBase> CRegDWORD;
1061 CRegStringCommon<CRegBase>;
1062 typedef CRegStringCommon<CRegBase> CRegString;
1064 #ifdef _MAP_
1065 CKeyList<CRegDWORD>;
1066 typedef CKeyList<CRegDWORD> CRegDWORDList;
1067 CKeyList<CRegString>;
1068 typedef CKeyList<CRegString> CRegStringList;
1069 #endif
1070 #endif
1072 CRegDWORDCommon<CRegStdBase>;
1073 typedef CRegDWORDCommon<CRegStdBase> CRegStdDWORD;
1074 CRegStringCommon<CRegStdBase>;
1075 typedef CRegStringCommon<CRegStdBase> CRegStdString;
1077 #ifdef _MAP_
1078 CKeyList<CRegStdDWORD>;
1079 typedef CKeyList<CRegStdDWORD> CRegStdDWORDList;
1080 CKeyList<CRegStdString>;
1081 typedef CKeyList<CRegStdString> CRegStdStringList;
1082 #endif