Fixed issue #1737: Make a button to rename remote
[TortoiseGit.git] / src / Utils / registry.h
bloba54ab0ffaf99d9e21b0d44505dbaf50dbae0b594
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2013 - 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 "FormatMessageWrapper.h"
26 #ifndef ASSERT
27 #define ASSERT(x)
28 #endif
30 /**
31 * \ingroup Utils
32 * Base class for the registry classes.
34 * \par requirements
35 * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later
36 * - import library Shlwapi.lib
39 template<class S>
40 class CRegBaseCommon
42 protected:
44 /**
45 * String type specific operations.
48 virtual LPCTSTR GetPlainString (const S& s) const = 0;
49 virtual DWORD GetLength (const S& s) const = 0;
51 public: //methods
53 /** Default constructor.
55 CRegBaseCommon();
56 /**
57 * Constructor.
58 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
59 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
60 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
61 * \param sam
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.
240 * \param sam
242 CRegStdBase(const tstring& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
246 * \ingroup Utils
247 * DWORD value in registry. with this class you can use DWORD values in registry
248 * like normal DWORD variables in your program.
249 * Usage:
250 * in your header file, declare your registry DWORD variable:
251 * \code
252 * CRegDWORD regvalue;
253 * \endcode
254 * next initialize the variable e.g. in the constructor of your class:
255 * \code
256 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
257 * \endcode
258 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
259 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
260 * an error occurred during read from the registry, a default
261 * value of 100 is used when accessing the variable.
262 * now the variable can be used like any other DWORD variable:
263 * \code
264 * regvalue = 200; //stores the value 200 in the registry
265 * int temp = regvalue + 300; //temp has value 500 now
266 * regvalue += 300; //now the registry has the value 500 too
267 * \endcode
268 * to avoid too much access to the registry the value is cached inside the object.
269 * once the value is read, no more read accesses to the registry will be made.
270 * this means the variable will contain a wrong value if the corresponding registry
271 * entry is changed by anything else than this variable! If you think that could happen
272 * then use
273 * \code
274 * regvalue.read();
275 * \endcode
276 * to force a refresh of the variable with the registry.
277 * a write to the registry is only made if the new value assigned with the variable
278 * is different than the last assigned value.
279 * to force a write use the method write();
280 * another option to force reads and writes to the registry is to specify TRUE as the
281 * third parameter in the constructor.
283 template<class T, class Base>
284 class CRegTypedBase : public Base
286 private:
288 T m_value; ///< the cached value of the registry
289 T m_defaultvalue; ///< the default value to use
292 * time stamp of the last registry lookup, i.e \ref read() call
295 DWORD lastRead;
298 * \ref read() will be called, if \ref lastRead differs from the
299 * current time stamp by more than this.
300 * (DWORD)(-1) -> no automatic refresh.
303 DWORD lookupInterval;
306 * Check time stamps etc.
307 * If the current data is out-dated, reset the \ref m_read flag.
310 void HandleAutoRefresh();
313 * sub-classes must provide type-specific code to extract data from
314 * and write data to an open registry key.
317 virtual void InternalRead (HKEY hKey, T& value) = 0;
318 virtual void InternalWrite (HKEY hKey, const T& value) = 0;
320 public:
323 * Make the value type accessible to others.
326 typedef T ValueT;
329 * Constructor.
330 * We use this instead of a default constructor because not all
331 * data types may provide an adequate default constructor.
333 CRegTypedBase(const T& def);
336 * Constructor.
337 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
338 * \param def the default value used when the key does not exist or a read error occurred
339 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
340 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
341 * \param sam
343 CRegTypedBase(const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
346 * Constructor.
347 * \param updateInterval time in msec between registry lookups caused by operator const T&
348 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
349 * \param def the default value used when the key does not exist or a read error occurred
350 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
351 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
352 * \param sam
354 CRegTypedBase(DWORD updateInterval, const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
357 * reads the assigned value from the registry. Use this method only if you think the registry
358 * value could have been altered without using the CRegDWORD object.
359 * \return the read value
361 void read(); ///< reads the value from the registry
362 void write(); ///< writes the value to the registry
364 bool exists(); ///< test whether registry entry exits
365 const T& defaultValue() const; ///< return the default passed to the constructor
368 * Data access.
371 operator const T&();
372 CRegTypedBase<T,Base>& operator=(const T& rhs);
375 // implement CRegTypedBase<> members
377 template<class T, class Base>
378 void CRegTypedBase<T, Base>::HandleAutoRefresh()
380 if (m_read && (lookupInterval != (DWORD)(-1)))
382 DWORD currentTime = GetTickCount();
383 if ( (currentTime < lastRead)
384 || (currentTime > lastRead + lookupInterval))
386 m_read = false;
391 template<class T, class Base>
392 CRegTypedBase<T, Base>::CRegTypedBase (const T& def)
393 : m_value (def)
394 , m_defaultvalue (def)
395 , lastRead (0)
396 , lookupInterval ((DWORD)-1)
400 template<class T, class Base>
401 CRegTypedBase<T, Base>::CRegTypedBase (const typename Base::StringT& key, const T& def, bool force, HKEY base, REGSAM sam)
402 : Base (key, force, base, sam)
403 , m_value (def)
404 , m_defaultvalue (def)
405 , lastRead (0)
406 , lookupInterval ((DWORD)-1)
410 template<class T, class Base>
411 CRegTypedBase<T, Base>::CRegTypedBase (DWORD lookupInterval, const typename Base::StringT& key, const T& def, bool force, HKEY base, REGSAM sam)
412 : Base (key, force, base, sam)
413 , m_value (def)
414 , m_defaultvalue (def)
415 , lastRead (0)
416 , lookupInterval (lookupInterval)
420 template<class T, class Base>
421 void CRegTypedBase<T, Base>::read()
423 m_value = m_defaultvalue;
424 m_exists = false;
426 HKEY hKey = NULL;
427 if ((LastError = RegOpenKeyEx (m_base, GetPlainString (m_path), 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|m_sam, &hKey))==ERROR_SUCCESS)
430 T value = m_defaultvalue;
431 InternalRead (hKey, value);
433 if (LastError ==ERROR_SUCCESS)
435 m_exists = true;
436 m_value = value;
439 LastError = RegCloseKey(hKey);
442 m_read = true;
443 lastRead = GetTickCount();
446 template<class T, class Base>
447 void CRegTypedBase<T, Base>::write()
449 HKEY hKey = NULL;
451 DWORD disp = 0;
452 if ((LastError = RegCreateKeyEx(m_base, GetPlainString (m_path), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE|m_sam, NULL, &hKey, &disp))!=ERROR_SUCCESS)
454 return;
457 InternalWrite (hKey, m_value);
458 if (LastError ==ERROR_SUCCESS)
460 m_read = true;
461 m_exists = true;
463 LastError = RegCloseKey(hKey);
465 lastRead = GetTickCount();
468 template<class T, class Base>
469 bool CRegTypedBase<T, Base>::exists()
471 if (!m_read && (LastError == ERROR_SUCCESS))
472 read();
474 return m_exists;
477 template<class T, class Base>
478 const T& CRegTypedBase<T, Base>::defaultValue() const
480 return m_defaultvalue;
483 template<class T, class Base>
484 CRegTypedBase<T, Base>::operator const T&()
486 HandleAutoRefresh();
487 if ((m_read)&&(!m_force))
489 LastError = ERROR_SUCCESS;
491 else
493 read();
496 return m_value;
499 template<class T, class Base>
500 CRegTypedBase<T, Base>& CRegTypedBase<T, Base>::operator =(const T& d)
502 if (m_read && (d == m_value) && !m_force)
504 //no write to the registry required, its the same value
505 LastError = ERROR_SUCCESS;
506 return *this;
508 m_value = d;
509 write();
510 return *this;
514 * \ingroup Utils
515 * DWORD value in registry. with this class you can use DWORD values in registry
516 * like normal DWORD variables in your program.
517 * Usage:
518 * in your header file, declare your registry DWORD variable:
519 * \code
520 * CRegDWORD regvalue;
521 * \endcode
522 * next initialize the variable e.g. in the constructor of your class:
523 * \code
524 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
525 * \endcode
526 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
527 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
528 * an error occurred during read from the registry, a default
529 * value of 100 is used when accessing the variable.
530 * now the variable can be used like any other DWORD variable:
531 * \code
532 * regvalue = 200; //stores the value 200 in the registry
533 * int temp = regvalue + 300; //temp has value 500 now
534 * regvalue += 300; //now the registry has the value 500 too
535 * \endcode
536 * to avoid too much access to the registry the value is cached inside the object.
537 * once the value is read, no more read accesses to the registry will be made.
538 * this means the variable will contain a wrong value if the corresponding registry
539 * entry is changed by anything else than this variable! If you think that could happen
540 * then use
541 * \code
542 * regvalue.read();
543 * \endcode
544 * to force a refresh of the variable with the registry.
545 * a write to the registry is only made if the new value assigned with the variable
546 * is different than the last assigned value.
547 * to force a write use the method write();
548 * another option to force reads and writes to the registry is to specify TRUE as the
549 * third parameter in the constructor.
551 template<class Base>
552 class CRegDWORDCommon : public CRegTypedBase<DWORD,Base>
554 private:
557 * provide type-specific code to extract data from and write data to an open registry key.
560 virtual void InternalRead (HKEY hKey, DWORD& value);
561 virtual void InternalWrite (HKEY hKey, const DWORD& value);
563 public:
565 CRegDWORDCommon(void);
567 * Constructor.
568 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
569 * \param def the default value used when the key does not exist or a read error occurred
570 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
571 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
572 * \param sam
574 CRegDWORDCommon(const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
575 CRegDWORDCommon(DWORD lookupInterval, const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
577 CRegDWORDCommon& operator=(DWORD rhs) {CRegTypedBase<DWORD, Base>::operator =(rhs); return *this;}
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;}
584 CRegDWORDCommon& operator>>=(DWORD d) { return *this = *this >> d;}
585 CRegDWORDCommon& operator&=(DWORD d) { return *this = *this & d;}
586 CRegDWORDCommon& operator|=(DWORD d) { return *this = *this | d;}
587 CRegDWORDCommon& operator^=(DWORD d) { return *this = *this ^ d;}
590 // implement CRegDWORDCommon<> methods
592 template<class Base>
593 CRegDWORDCommon<Base>::CRegDWORDCommon(void)
594 : CRegTypedBase<DWORD, Base>(0)
598 template<class Base>
599 CRegDWORDCommon<Base>::CRegDWORDCommon(const typename Base::StringT& key, DWORD def, bool force, HKEY base, REGSAM sam)
600 : CRegTypedBase<DWORD, Base> (key, def, force, base, sam)
604 template<class Base>
605 CRegDWORDCommon<Base>::CRegDWORDCommon(DWORD lookupInterval, const typename Base::StringT& key, DWORD def, bool force, HKEY base, REGSAM sam)
606 : CRegTypedBase<DWORD, Base> (lookupInterval, key, def, force, base, sam)
610 template<class Base>
611 void CRegDWORDCommon<Base>::InternalRead (HKEY hKey, DWORD& value)
613 DWORD size = sizeof(value);
614 DWORD type = 0;
615 if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) &value, &size))==ERROR_SUCCESS)
617 ASSERT(type==REG_DWORD);
621 template<class Base>
622 void CRegDWORDCommon<Base>::InternalWrite (HKEY hKey, const DWORD& value)
624 LastError = RegSetValueEx (hKey, GetPlainString (m_key), 0, REG_DWORD,(const BYTE*) &value, sizeof(value));
628 * \ingroup Utils
629 * CString value in registry. with this class you can use CString values in registry
630 * almost like normal CString variables in your program.
631 * Usage:
632 * in your header file, declare your registry CString variable:
633 * \code
634 * CRegString regvalue;
635 * \endcode
636 * next initialize the variable e.g. in the constructor of your class:
637 * \code
638 * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");
639 * \endcode
640 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
641 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
642 * an error occurred during read from the registry, a default
643 * value of "default" is used when accessing the variable.
644 * now the variable can be used like any other CString variable:
645 * \code
646 * regvalue = "some string"; //stores the value "some string" in the registry
647 * CString temp = regvalue + "!!"; //temp has value "some string!!" now
648 * \endcode
649 * to use the normal methods of the CString class, just typecast the CRegString to a CString
650 * and do whatever you want with the string:
651 * \code
652 * ((CString)regvalue).GetLength();
653 * ((CString)regvalue).Trim();
654 * \endcode
655 * please be aware that in the second line the change in the string won't be written
656 * to the registry! To force a write use the write() method. A write() is only needed
657 * if you change the String with Methods not overloaded by CRegString.
658 * to avoid too much access to the registry the value is cached inside the object.
659 * once the value is read, no more read accesses to the registry will be made.
660 * this means the variable will contain a wrong value if the corresponding registry
661 * entry is changed by anything else than this variable! If you think that could happen
662 * then use
663 * \code
664 * regvalue.read();
665 * \endcode
666 * to force a refresh of the variable with the registry.
667 * a write to the registry is only made if the new value assigned with the variable
668 * is different than the last assigned value.
669 * to force a write use the method write();
670 * another option to force reads and writes to the registry is to specify TRUE as the
671 * third parameter in the constructor.
673 template<class Base>
674 class CRegStringCommon : public CRegTypedBase<typename Base::StringT, Base>
676 private:
679 * provide type-specific code to extract data from and write data to an open registry key.
682 virtual void InternalRead (HKEY hKey, typename Base::StringT& value);
683 virtual void InternalWrite (HKEY hKey, const typename Base::StringT& value);
685 public:
686 CRegStringCommon();
688 * Constructor.
689 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
690 * \param def the default value used when the key does not exist or a read error occurred
691 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
692 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
693 * \param sam
695 CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def = _T(""), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
696 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);
698 CRegStringCommon& operator=(const typename Base::StringT& rhs) {CRegTypedBase<StringT, Base>::operator =(rhs); return *this;}
699 CRegStringCommon& operator+=(const typename Base::StringT& s) { return *this = (typename Base::StringT)*this + s; }
702 // implement CRegDWORD<> methods
704 template<class Base>
705 CRegStringCommon<Base>::CRegStringCommon(void)
706 : CRegTypedBase<typename Base::StringT, Base>(typename Base::StringT())
710 template<class Base>
711 CRegStringCommon<Base>::CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base, REGSAM sam)
712 : CRegTypedBase<typename Base::StringT, Base> (key, def, force, base, sam)
716 template<class Base>
717 CRegStringCommon<Base>::CRegStringCommon(DWORD lookupInterval, const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base, REGSAM sam)
718 : CRegTypedBase<typename Base::StringT, Base> (lookupInterval, key, def, force, base, sam)
722 template<class Base>
723 void CRegStringCommon<Base>::InternalRead (HKEY hKey, typename Base::StringT& value)
725 DWORD size = 0;
726 DWORD type = 0;
727 LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, NULL, &size);
729 if (LastError == ERROR_SUCCESS)
731 std::unique_ptr<TCHAR[]> pStr (new TCHAR[size]);
732 if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) pStr.get(), &size))==ERROR_SUCCESS)
734 ASSERT(type==REG_SZ || type==REG_EXPAND_SZ);
735 value = StringT (pStr.get());
740 template<class Base>
741 void CRegStringCommon<Base>::InternalWrite (HKEY hKey, const typename Base::StringT& value)
743 LastError = RegSetValueEx(hKey, GetPlainString (m_key), 0, REG_SZ, (BYTE *)GetPlainString (value), (GetLength(value)+1)*sizeof (TCHAR));
747 * \ingroup Utils
748 * CRect value in registry. with this class you can use CRect values in registry
749 * almost like normal CRect variables in your program.
750 * Usage:
751 * in your header file, declare your registry CString variable:
752 * \code
753 * CRegRect regvalue;
754 * \endcode
755 * next initialize the variable e.g. in the constructor of your class:
756 * \code
757 * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));
758 * \endcode
759 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
760 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
761 * an error occurred during read from the registry, a default
762 * value of 100,100,200,200 is used when accessing the variable.
763 * now the variable can be used like any other CRect variable:
764 * \code
765 * regvalue = CRect(40,20,300,500); //stores the value in the registry
766 * CRect temp = regvalue + CPoint(1,1);
767 * temp |= CSize(5,5);
768 * \endcode
769 * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect
770 * and do whatever you want with the rect:
771 * \code
772 * ((CRect)regvalue).MoveToX(100);
773 * ((CRect)regvalue).DeflateRect(10,10);
774 * \endcode
775 * please be aware that in the second line the change in the CRect won't be written
776 * to the registry! To force a write use the write() method. A write() is only needed
777 * if you change the CRect with Methods not overloaded by CRegRect.
778 * to avoid too much access to the registry the value is cached inside the object.
779 * once the value is read, no more read accesses to the registry will be made.
780 * this means the variable will contain a wrong value if the corresponding registry
781 * entry is changed by anything else than this variable! If you think that could happen
782 * then use
783 * \code
784 * regvalue.read();
785 * \endcode
786 * to force a refresh of the variable with the registry.
787 * a write to the registry is only made if the new value assigned with the variable
788 * is different than the last assigned value.
789 * to force a write use the method write();
790 * another option to force reads and writes to the registry is to specify TRUE as the
791 * third parameter in the constructor.
794 #ifdef __ATLTYPES_H__ // defines CRect
795 class CRegRect : public CRegTypedBase<CRect, CRegBase>
797 private:
800 * provide type-specific code to extract data from and write data to an open registry key.
803 virtual void InternalRead (HKEY hKey, CRect& value);
804 virtual void InternalWrite (HKEY hKey, const CRect& value);
806 public:
807 CRegRect();
809 * Constructor.
810 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
811 * \param def the default value used when the key does not exist or a read error occurred
812 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
813 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
815 CRegRect(const CString& key, const CRect& def = CRect(), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
816 ~CRegRect(void);
818 CRegRect& operator=(const CRect& rhs) {CRegTypedBase<CRect, CRegBase>::operator =(rhs); return *this;}
819 operator LPCRECT() { return (LPCRECT)(CRect)*this; }
820 operator LPRECT() { return (LPRECT)(CRect)*this; }
821 CRegRect& operator+=(POINT r) { return *this = (CRect)*this + r;}
822 CRegRect& operator+=(SIZE r) { return *this = (CRect)*this + r;}
823 CRegRect& operator+=(LPCRECT r) { return *this = (CRect)*this + r;}
824 CRegRect& operator-=(POINT r) { return *this = (CRect)*this - r;}
825 CRegRect& operator-=(SIZE r) { return *this = (CRect)*this - r;}
826 CRegRect& operator-=(LPCRECT r) { return *this = (CRect)*this - r;}
828 CRegRect& operator&=(CRect r) { return *this = r & *this;}
829 CRegRect& operator|=(CRect r) { return *this = r | *this;}
831 #endif
834 * \ingroup Utils
835 * CPoint value in registry. with this class you can use CPoint values in registry
836 * almost like normal CPoint variables in your program.
837 * Usage:
838 * in your header file, declare your registry CPoint variable:
839 * \code
840 * CRegPoint regvalue;
841 * \endcode
842 * next initialize the variable e.g. in the constructor of your class:
843 * \code
844 * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));
845 * \endcode
846 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
847 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
848 * an error occurred during read from the registry, a default
849 * value of 100,100 is used when accessing the variable.
850 * now the variable can be used like any other CPoint variable:
851 * \code
852 * regvalue = CPoint(40,20); //stores the value in the registry
853 * CPoint temp = regvalue + CPoint(1,1);
854 * temp += CSize(5,5);
855 * \endcode
856 * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint
857 * and do whatever you want with the point:
858 * \code
859 * ((CRect)regvalue).Offset(100,10);
860 * \endcode
861 * please be aware that in the above example the change in the CPoint won't be written
862 * to the registry! To force a write use the write() method. A write() is only needed
863 * if you change the CPoint with Methods not overloaded by CRegPoint.
864 * to avoid too much access to the registry the value is cached inside the object.
865 * once the value is read, no more read accesses to the registry will be made.
866 * this means the variable will contain a wrong value if the corresponding registry
867 * entry is changed by anything else than this variable! If you think that could happen
868 * then use
869 * \code
870 * regvalue.read();
871 * \endcode
872 * to force a refresh of the variable with the registry.
873 * a write to the registry is only made if the new value assigned with the variable
874 * is different than the last assigned value.
875 * to force a write use the method write();
876 * another option to force reads and writes to the registry is to specify TRUE as the
877 * third parameter in the constructor.
880 #ifdef __ATLTYPES_H__ // defines CPoint
881 class CRegPoint : public CRegTypedBase<CPoint, CRegBase>
883 private:
886 * provide type-specific code to extract data from and write data to an open registry key.
889 virtual void InternalRead (HKEY hKey, CPoint& value);
890 virtual void InternalWrite (HKEY hKey, const CPoint& value);
892 public:
893 CRegPoint();
895 * Constructor.
896 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
897 * \param def the default value used when the key does not exist or a read error occurred
898 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
899 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
901 CRegPoint(const CString& key, const CPoint& def = CPoint(), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
902 ~CRegPoint(void);
904 CRegPoint& operator=(const CPoint& rhs) {CRegTypedBase<CPoint, CRegBase>::operator =(rhs); return *this;}
905 CRegPoint& operator+=(CPoint p) { return *this = p + *this; }
906 CRegPoint& operator-=(CPoint p) { return *this = p - *this; }
908 #endif
911 * \ingroup Utils
912 * Manages a registry key (not a value). Provides methods to create and remove the
913 * key and to query the list of values and sub keys.
916 #ifdef __AFXCOLL_H__ // defines CStringList
917 class CRegistryKey
919 public: //methods
921 * Constructor.
922 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey"
923 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
925 CRegistryKey(const CString& key, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
926 ~CRegistryKey();
929 * Creates the registry key if it does not already exist.
930 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
932 DWORD createKey();
934 * Removes the whole registry key including all values. So if you set the registry
935 * entry to be HKCU\Software\Company\Product\key there will only be
936 * HKCU\Software\Company\Product key in the registry.
937 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
939 DWORD removeKey();
941 bool getValues(CStringList& values); ///< returns the list of values
942 bool getSubKeys(CStringList& subkeys); ///< returns the list of sub keys
944 public: //members
945 HKEY m_base; ///< handle to the registry base
946 HKEY m_hKey; ///< handle to the open registry key
947 REGSAM m_sam; ///< the security attributes to pass to the registry command
948 CString m_path; ///< the path to the key
950 #endif
952 #ifdef _MAP_
953 template<class T>
954 class CKeyList
956 private:
958 /// constructor parameters
960 typename T::StringT key;
961 typename T::ValueT defaultValue;
962 HKEY base;
964 /// per-index defaults
966 typedef std::map<int, typename T::ValueT> TDefaults;
967 TDefaults defaults;
969 /// the indices accessed so far
971 typedef std::map<int, T*> TElements;
972 mutable TElements elements;
974 /// auto-insert
976 const typename T::ValueT& GetDefault (int index) const;
977 T& GetAt (int index) const;
979 public:
981 /// construction
983 CKeyList (const typename T::StringT& key, const typename T::ValueT& defaultValue, HKEY base = HKEY_CURRENT_USER)
984 : key (key)
985 , defaultValue (defaultValue)
986 , base (base)
990 /// destruction: delete all elements
992 ~CKeyList()
994 for ( TElements::iterator iter = elements.begin()
995 , end = elements.end()
996 ; iter != end
997 ; ++iter)
999 delete iter->second;
1003 /// data access
1005 const T& operator[] (int index) const
1007 return GetAt (index);
1010 T& operator[] (int index)
1012 return GetAt (index);
1015 const TDefaults& GetDefaults() const
1017 return defaults;
1020 TDefaults& GetDefaults()
1022 return defaults;
1025 const typename T::ValueT& GetDefault() const
1027 return defaultValue;
1031 /// auto-insert
1033 template<class T>
1034 const typename T::ValueT& CKeyList<T>::GetDefault (int index) const
1036 TDefaults::const_iterator iter = defaults.find (index);
1037 return iter == defaults.end() ? defaultValue : iter->second;
1040 template<class T>
1041 T& CKeyList<T>::GetAt (int index) const
1043 TElements::iterator iter = elements.find (index);
1044 if (iter == elements.end())
1046 TCHAR buffer [10];
1047 _itot_s (index, buffer, 10);
1048 typename T::StringT indexKey = key + _T ('\\') + buffer;
1050 T* newElement = new T (indexKey, GetDefault (index), false, base);
1051 iter = elements.insert (std::make_pair (index, newElement)).first;
1054 return *iter->second;
1057 #endif
1060 * Instantiate templates for common (data type, string type) combinations.
1063 #ifdef __CSTRINGT_H__
1064 CRegDWORDCommon<CRegBase>;
1065 typedef CRegDWORDCommon<CRegBase> CRegDWORD;
1066 CRegStringCommon<CRegBase>;
1067 typedef CRegStringCommon<CRegBase> CRegString;
1069 #ifdef _MAP_
1070 CKeyList<CRegDWORD>;
1071 typedef CKeyList<CRegDWORD> CRegDWORDList;
1072 CKeyList<CRegString>;
1073 typedef CKeyList<CRegString> CRegStringList;
1074 #endif
1075 #endif
1077 CRegDWORDCommon<CRegStdBase>;
1078 typedef CRegDWORDCommon<CRegStdBase> CRegStdDWORD;
1079 CRegStringCommon<CRegStdBase>;
1080 typedef CRegStringCommon<CRegStdBase> CRegStdString;
1082 #ifdef _MAP_
1083 CKeyList<CRegStdDWORD>;
1084 typedef CKeyList<CRegStdDWORD> CRegStdDWORDList;
1085 CKeyList<CRegStdString>;
1086 typedef CKeyList<CRegStdString> CRegStdStringList;
1087 #endif