1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2014, 2017 - TortoiseGit
4 // Copyright (C) 2003-2014 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "FormatMessageWrapper.h"
33 * Base class for the registry classes.
36 * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later
37 * - import library Shlwapi.lib
46 * String type specific operations.
49 virtual LPCTSTR
GetPlainString (const S
& s
) const = 0;
50 virtual DWORD
GetLength (const S
& s
) const = 0;
54 /** Default 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.
64 CRegBaseCommon(const S
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
67 * Removes the whole registry key including all values. So if you set the registry
68 * entry to be HKCU\Software\Company\Product\key\value there will only be
69 * HKCU\Software\Company\Product key in the registry.
70 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
74 * Removes the value of the registry object. If you set the registry entry to
75 * be HKCU\Software\Company\Product\key\value there will only be
76 * HKCU\Software\Company\Product\key\ in the registry.
77 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
82 * Returns the string of the last error occurred.
84 virtual S
getErrorString()
86 CFormatMessageWrapper
errorMessage(LastError
);
87 S
result ((LPCTSTR
)errorMessage
);
91 /// get failure info for last operation
93 LONG
GetLastError() const
98 /// used in subclass templates to specify the correct string type
105 HKEY m_base
; ///< handle to the registry base
106 S m_key
; ///< the name of the value
107 S m_path
; ///< the path to the key
108 LONG LastError
; ///< the value of the last error occurred
109 REGSAM m_sam
; ///< the security attributes to pass to the registry command
111 bool m_read
; ///< indicates if the value has already been attempted read from the registry
112 bool m_force
; ///< indicates if no cache should be used, i.e. always read and write directly from registry
113 bool m_exists
; ///< true, if the registry value actually exists
116 // implement CRegBaseCommon<> members
119 CRegBaseCommon
<S
>::CRegBaseCommon()
120 : m_base (HKEY_CURRENT_USER
)
123 , LastError (ERROR_SUCCESS
)
132 CRegBaseCommon
<S
>::CRegBaseCommon (const S
& key
, bool force
, HKEY base
, REGSAM sam
)
136 , LastError (ERROR_SUCCESS
)
145 DWORD CRegBaseCommon
<S
>::removeKey()
151 RegOpenKeyEx (m_base
, GetPlainString (m_path
), 0, KEY_WRITE
|m_sam
, &hKey
);
152 return SHDeleteKey(m_base
, GetPlainString (m_path
));
156 LONG CRegBaseCommon
<S
>::removeValue()
162 RegOpenKeyEx(m_base
, GetPlainString (m_path
), 0, KEY_WRITE
|m_sam
, &hKey
);
163 return RegDeleteValue(hKey
, GetPlainString (m_key
));
168 * Base class for MFC type registry classes.
171 #ifdef __CSTRINGT_H__
172 class CRegBase
: public CRegBaseCommon
<CString
>
177 * String type specific operations.
180 virtual LPCTSTR
GetPlainString (const CString
& s
) const {return (LPCTSTR
)s
;}
181 virtual DWORD
GetLength (const CString
& s
) const {return s
.GetLength();}
185 /** Default constructor.
190 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
191 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
192 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
194 CRegBase(const CString
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
197 * Returns the string of the last error occurred.
199 CString
getErrorString()
201 CString error
= CRegBaseCommon
<CString
>::getErrorString();
202 #if defined IDS_REG_ERROR
204 sTemp
.FormatMessage(IDS_REG_ERROR
, (LPCTSTR
)m_key
, (LPCTSTR
)error
);
217 * Base class for STL string type registry classes.
220 class CRegStdBase
: public CRegBaseCommon
<tstring
>
225 * String type specific operations.
228 virtual LPCTSTR
GetPlainString (const tstring
& s
) const {return s
.c_str();}
229 virtual DWORD
GetLength (const tstring
& s
) const {return static_cast<DWORD
>(s
.size());}
233 /** Default constructor.
238 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
239 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
240 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
243 CRegStdBase(const tstring
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
248 * DWORD value in registry. with this class you can use DWORD values in registry
249 * like normal DWORD variables in your program.
251 * in your header file, declare your registry DWORD variable:
253 * CRegDWORD regvalue;
255 * next initialize the variable e.g. in the constructor of your class:
257 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
259 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
260 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
261 * an error occurred during read from the registry, a default
262 * value of 100 is used when accessing the variable.
263 * now the variable can be used like any other DWORD variable:
265 * regvalue = 200; //stores the value 200 in the registry
266 * int temp = regvalue + 300; //temp has value 500 now
267 * regvalue += 300; //now the registry has the value 500 too
269 * to avoid too much access to the registry the value is cached inside the object.
270 * once the value is read, no more read accesses to the registry will be made.
271 * this means the variable will contain a wrong value if the corresponding registry
272 * entry is changed by anything else than this variable! If you think that could happen
277 * to force a refresh of the variable with the registry.
278 * a write to the registry is only made if the new value assigned with the variable
279 * is different than the last assigned value.
280 * to force a write use the method write();
281 * another option to force reads and writes to the registry is to specify TRUE as the
282 * third parameter in the constructor.
284 template<class T
, class Base
>
285 class CRegTypedBase
: public Base
289 T m_value
; ///< the cached value of the registry
290 T m_defaultvalue
; ///< the default value to use
293 * time stamp of the last registry lookup, i.e \ref read() call
299 * \ref read() will be called, if \ref lastRead differs from the
300 * current time stamp by more than this.
301 * (ULONGLONG)(-1) -> no automatic refresh.
304 ULONGLONG lookupInterval
;
307 * Check time stamps etc.
308 * If the current data is out-dated, reset the \ref m_read flag.
311 void HandleAutoRefresh();
314 * sub-classes must provide type-specific code to extract data from
315 * and write data to an open registry key.
318 virtual void InternalRead (HKEY hKey
, T
& value
) = 0;
319 virtual void InternalWrite (HKEY hKey
, const T
& value
) = 0;
324 * Make the value type accessible to others.
331 * We use this instead of a default constructor because not all
332 * data types may provide an adequate default constructor.
334 CRegTypedBase(const T
& def
);
338 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
339 * \param def the default value used when the key does not exist or a read error occurred
340 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
341 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
344 CRegTypedBase(const typename
Base::StringT
& key
, const T
& def
, bool force
= FALSE
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
348 * \param updateInterval time in msec between registry lookups caused by operator const T&
349 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
350 * \param def the default value used when the key does not exist or a read error occurred
351 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
352 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
355 CRegTypedBase(DWORD updateInterval
, const typename
Base::StringT
& key
, const T
& def
, bool force
= FALSE
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
358 * reads the assigned value from the registry. Use this method only if you think the registry
359 * value could have been altered without using the CRegDWORD object.
360 * \return the read value
362 void read(); ///< reads the value from the registry
363 void write(); ///< writes the value to the registry
365 bool exists(); ///< test whether registry entry exits
366 const T
& defaultValue() const; ///< return the default passed to the constructor
373 CRegTypedBase
<T
,Base
>& operator=(const T
& rhs
);
376 // implement CRegTypedBase<> members
378 template<class T
, class Base
>
379 void CRegTypedBase
<T
, Base
>::HandleAutoRefresh()
381 if (m_read
&& (lookupInterval
!= (DWORD
)(-1)))
383 ULONGLONG currentTime
= GetTickCount64();
384 if ( (currentTime
< lastRead
)
385 || (currentTime
> lastRead
+ lookupInterval
))
392 template<class T
, class Base
>
393 CRegTypedBase
<T
, Base
>::CRegTypedBase (const T
& def
)
395 , m_defaultvalue (def
)
397 , lookupInterval((ULONGLONG
)-1)
401 template<class T
, class Base
>
402 CRegTypedBase
<T
, Base
>::CRegTypedBase (const typename
Base::StringT
& key
, const T
& def
, bool force
, HKEY base
, REGSAM sam
)
403 : Base (key
, force
, base
, sam
)
405 , m_defaultvalue (def
)
407 , lookupInterval ((DWORD
)-1)
411 template<class T
, class Base
>
412 CRegTypedBase
<T
, Base
>::CRegTypedBase (DWORD lookupInterval
, const typename
Base::StringT
& key
, const T
& def
, bool force
, HKEY base
, REGSAM sam
)
413 : Base (key
, force
, base
, sam
)
415 , m_defaultvalue (def
)
417 , lookupInterval (lookupInterval
)
421 template<class T
, class Base
>
422 void CRegTypedBase
<T
, Base
>::read()
424 m_value
= m_defaultvalue
;
428 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
)
439 LastError
= RegCloseKey(hKey
);
443 lastRead
= GetTickCount64();
446 template<class T
, class Base
>
447 void CRegTypedBase
<T
, Base
>::write()
452 if ((LastError
= RegCreateKeyEx(m_base
, GetPlainString(m_path
), 0, L
"", REG_OPTION_NON_VOLATILE
, KEY_WRITE
| m_sam
, nullptr, &hKey
, &disp
)) != ERROR_SUCCESS
)
457 InternalWrite (hKey
, m_value
);
458 if (LastError
==ERROR_SUCCESS
)
463 LastError
= RegCloseKey(hKey
);
465 lastRead
= GetTickCount64();
468 template<class T
, class Base
>
469 bool CRegTypedBase
<T
, Base
>::exists()
471 if (!m_read
&& (LastError
== ERROR_SUCCESS
))
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
&()
487 if ((m_read
)&&(!m_force
))
489 LastError
= ERROR_SUCCESS
;
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
;
515 * DWORD value in registry. with this class you can use DWORD values in registry
516 * like normal DWORD variables in your program.
518 * in your header file, declare your registry DWORD variable:
520 * CRegDWORD regvalue;
522 * next initialize the variable e.g. in the constructor of your class:
524 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
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:
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
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
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.
552 class CRegDWORDCommon
: public CRegTypedBase
<DWORD
,Base
>
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
);
565 CRegDWORDCommon(void);
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.
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
593 CRegDWORDCommon
<Base
>::CRegDWORDCommon(void)
594 : CRegTypedBase
<DWORD
, Base
>(0)
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
)
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
)
611 void CRegDWORDCommon
<Base
>::InternalRead (HKEY hKey
, DWORD
& value
)
613 DWORD size
= sizeof(value
);
615 if ((LastError
= RegQueryValueEx(hKey
, GetPlainString(m_key
), nullptr, &type
, (BYTE
*)&value
, &size
)) == ERROR_SUCCESS
)
617 ASSERT(type
==REG_DWORD
);
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
));
629 * CString value in registry. with this class you can use CString values in registry
630 * almost like normal CString variables in your program.
632 * in your header file, declare your registry CString variable:
634 * CRegString regvalue;
636 * next initialize the variable e.g. in the constructor of your class:
638 * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");
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:
646 * regvalue = "some string"; //stores the value "some string" in the registry
647 * CString temp = regvalue + "!!"; //temp has value "some string!!" now
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:
652 * ((CString)regvalue).GetLength();
653 * ((CString)regvalue).Trim();
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
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.
674 class CRegStringCommon
: public CRegTypedBase
<typename
Base::StringT
, Base
>
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
);
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.
695 CRegStringCommon(const typename
Base::StringT
& key
, const typename
Base::StringT
& def
= L
"", 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
= L
"", 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
705 CRegStringCommon
<Base
>::CRegStringCommon(void)
706 : CRegTypedBase
<typename
Base::StringT
, Base
>(typename
Base::StringT())
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
)
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
)
723 void CRegStringCommon
<Base
>::InternalRead (HKEY hKey
, typename
Base::StringT
& value
)
727 LastError
= RegQueryValueEx(hKey
, GetPlainString(m_key
), nullptr, &type
, nullptr, &size
);
729 if (LastError
== ERROR_SUCCESS
)
731 auto pStr
= std::make_unique
<TCHAR
[]>(size
);
732 if ((LastError
= RegQueryValueEx(hKey
, GetPlainString(m_key
), nullptr, &type
, (BYTE
*)pStr
.get(), &size
)) == ERROR_SUCCESS
)
734 ASSERT(type
==REG_SZ
|| type
==REG_EXPAND_SZ
);
735 value
= StringT (pStr
.get());
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
));
748 * CRect value in registry. with this class you can use CRect values in registry
749 * almost like normal CRect variables in your program.
751 * in your header file, declare your registry CString variable:
755 * next initialize the variable e.g. in the constructor of your class:
757 * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));
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:
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);
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:
772 * ((CRect)regvalue).MoveToX(100);
773 * ((CRect)regvalue).DeflateRect(10,10);
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
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
>
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
);
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);
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&=(const CRect
& r
) { return *this = r
& *this;}
829 CRegRect
& operator|=(const CRect
& r
) { return *this = r
| *this;}
835 * CPoint value in registry. with this class you can use CPoint values in registry
836 * almost like normal CPoint variables in your program.
838 * in your header file, declare your registry CPoint variable:
840 * CRegPoint regvalue;
842 * next initialize the variable e.g. in the constructor of your class:
844 * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));
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:
852 * regvalue = CPoint(40,20); //stores the value in the registry
853 * CPoint temp = regvalue + CPoint(1,1);
854 * temp += CSize(5,5);
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:
859 * ((CRect)regvalue).Offset(100,10);
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
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
>
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
);
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);
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; }
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
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);
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.
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.
941 bool getValues(CStringList
& values
); ///< returns the list of values
942 bool getSubKeys(CStringList
& subkeys
); ///< returns the list of sub keys
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
958 /// constructor parameters
960 typename
T::StringT key
;
961 typename
T::ValueT defaultValue
;
964 /// per-index defaults
966 typedef std::map
<int, typename
T::ValueT
> TDefaults
;
969 /// the indices accessed so far
971 typedef std::map
<int, T
*> TElements
;
972 mutable TElements elements
;
976 const typename
T::ValueT
& GetDefault (int index
) const;
977 T
& GetAt (int index
) const;
983 CKeyList (const typename
T::StringT
& key
, const typename
T::ValueT
& defaultValue
, HKEY base
= HKEY_CURRENT_USER
)
985 , defaultValue (defaultValue
)
990 /// destruction: delete all elements
994 for ( TElements::iterator iter
= elements
.begin()
995 , end
= elements
.end()
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
1020 TDefaults
& GetDefaults()
1025 const typename
T::ValueT
& GetDefault() const
1027 return defaultValue
;
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
;
1041 T
& CKeyList
<T
>::GetAt (int index
) const
1043 TElements::iterator iter
= elements
.find (index
);
1044 if (iter
== elements
.end())
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
.emplace(index
, newElement
).first
;
1054 return *iter
->second
;
1060 * Instantiate templates for common (data type, string type) combinations.
1063 #ifdef __CSTRINGT_H__
1064 typedef CRegDWORDCommon
<CRegBase
> CRegDWORD
;
1065 typedef CRegStringCommon
<CRegBase
> CRegString
;
1068 typedef CKeyList
<CRegDWORD
> CRegDWORDList
;
1069 typedef CKeyList
<CRegString
> CRegStringList
;
1073 typedef CRegDWORDCommon
<CRegStdBase
> CRegStdDWORD
;
1074 typedef CRegStringCommon
<CRegStdBase
> CRegStdString
;
1077 typedef CKeyList
<CRegStdDWORD
> CRegStdDWORDList
;
1078 typedef CKeyList
<CRegStdString
> CRegStdStringList
;