Dropped auto_buffer
[TortoiseGit.git] / src / Utils / registry.h
blobce166576643a49f1fb140ec990aad2808205029e
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 "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.
62 CRegBaseCommon(const S& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
64 /**
65 * Removes the whole registry key including all values. So if you set the registry
66 * entry to be HKCU\Software\Company\Product\key\value there will only be
67 * HKCU\Software\Company\Product key in the registry.
68 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
70 DWORD removeKey();
71 /**
72 * Removes the value of the registry object. If you set the registry entry to
73 * be HKCU\Software\Company\Product\key\value there will only be
74 * HKCU\Software\Company\Product\key\ in the registry.
75 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
77 LONG removeValue();
79 /**
80 * Returns the string of the last error occurred.
82 virtual S getErrorString()
84 CFormatMessageWrapper errorMessage(LastError);
85 S result ((LPCTSTR)errorMessage);
86 return result;
89 /// get failure info for last operation
91 LONG GetLastError() const
93 return LastError;
96 /// used in subclass templates to specify the correct string type
98 typedef S StringT;
100 protected:
102 //members
103 HKEY m_base; ///< handle to the registry base
104 S m_key; ///< the name of the value
105 S m_path; ///< the path to the key
106 LONG LastError; ///< the value of the last error occurred
107 REGSAM m_sam; ///< the security attributes to pass to the registry command
109 bool m_read; ///< indicates if the value has already been read from the registry
110 bool m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry
111 bool m_exists; ///< true, if the registry actually exists
114 // implement CRegBaseCommon<> members
116 template<class S>
117 CRegBaseCommon<S>::CRegBaseCommon()
118 : m_base (HKEY_CURRENT_USER)
119 , m_key()
120 , m_path()
121 , LastError (ERROR_SUCCESS)
122 , m_sam (0)
123 , m_read (false)
124 , m_force (false)
125 , m_exists (false)
129 template<class S>
130 CRegBaseCommon<S>::CRegBaseCommon (const S& key, bool force, HKEY base, REGSAM sam)
131 : m_base (base)
132 , m_key (key)
133 , m_path()
134 , LastError (ERROR_SUCCESS)
135 , m_sam (sam)
136 , m_read (false)
137 , m_force (force)
138 , m_exists (false)
142 template<class S>
143 DWORD CRegBaseCommon<S>::removeKey()
145 m_exists = false;
146 m_read = true;
148 HKEY hKey = NULL;
149 RegOpenKeyEx (m_base, GetPlainString (m_path), 0, KEY_WRITE|m_sam, &hKey);
150 return SHDeleteKey(m_base, GetPlainString (m_path));
153 template<class S>
154 LONG CRegBaseCommon<S>::removeValue()
156 m_exists = false;
157 m_read = true;
159 HKEY hKey = NULL;
160 RegOpenKeyEx(m_base, GetPlainString (m_path), 0, KEY_WRITE|m_sam, &hKey);
161 return RegDeleteValue(hKey, GetPlainString (m_key));
165 * \ingroup Utils
166 * Base class for MFC type registry classes.
169 #ifdef __CSTRINGT_H__
170 class CRegBase : public CRegBaseCommon<CString>
172 protected:
175 * String type specific operations.
178 virtual LPCTSTR GetPlainString (const CString& s) const {return (LPCTSTR)s;}
179 virtual DWORD GetLength (const CString& s) const {return s.GetLength();}
181 public: //methods
183 /** Default constructor.
185 CRegBase();
187 * Constructor.
188 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
189 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
190 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
192 CRegBase(const CString& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
195 * Returns the string of the last error occurred.
197 CString getErrorString()
199 CString error = CRegBaseCommon<CString>::getErrorString();
200 #if defined IDS_REG_ERROR
201 CString sTemp;
202 sTemp.FormatMessage(IDS_REG_ERROR, (LPCTSTR)m_key, (LPCTSTR)error);
203 return sTemp;
204 #else
205 return error;
206 #endif
209 #endif
214 * \ingroup Utils
215 * Base class for STL string type registry classes.
218 class CRegStdBase : public CRegBaseCommon<tstring>
220 protected:
223 * String type specific operations.
226 virtual LPCTSTR GetPlainString (const tstring& s) const {return s.c_str();}
227 virtual DWORD GetLength (const tstring& s) const {return static_cast<DWORD>(s.size());}
229 public: //methods
231 /** Default constructor.
233 CRegStdBase();
235 * Constructor.
236 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
237 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
238 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
240 CRegStdBase(const tstring& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
244 * \ingroup Utils
245 * DWORD value in registry. with this class you can use DWORD values in registry
246 * like normal DWORD variables in your program.
247 * Usage:
248 * in your header file, declare your registry DWORD variable:
249 * \code
250 * CRegDWORD regvalue;
251 * \endcode
252 * next initialize the variable e.g. in the constructor of your class:
253 * \code
254 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
255 * \endcode
256 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
257 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
258 * an error occurred during read from the registry, a default
259 * value of 100 is used when accessing the variable.
260 * now the variable can be used like any other DWORD variable:
261 * \code
262 * regvalue = 200; //stores the value 200 in the registry
263 * int temp = regvalue + 300; //temp has value 500 now
264 * regvalue += 300; //now the registry has the value 500 too
265 * \endcode
266 * to avoid too much access to the registry the value is cached inside the object.
267 * once the value is read, no more read accesses to the registry will be made.
268 * this means the variable will contain a wrong value if the corresponding registry
269 * entry is changed by anything else than this variable! If you think that could happen
270 * then use
271 * \code
272 * regvalue.read();
273 * \endcode
274 * to force a refresh of the variable with the registry.
275 * a write to the registry is only made if the new value assigned with the variable
276 * is different than the last assigned value.
277 * to force a write use the method write();
278 * another option to force reads and writes to the registry is to specify TRUE as the
279 * third parameter in the constructor.
281 template<class T, class Base>
282 class CRegTypedBase : public Base
284 private:
286 T m_value; ///< the cached value of the registry
287 T m_defaultvalue; ///< the default value to use
290 * time stamp of the last registry lookup, i.e \ref read() call
293 DWORD lastRead;
296 * \ref read() will be called, if \ref lastRead differs from the
297 * current time stamp by more than this.
298 * (DWORD)(-1) -> no automatic refresh.
301 DWORD lookupInterval;
304 * Check time stamps etc.
305 * If the current data is out-dated, reset the \ref m_read flag.
308 void HandleAutoRefresh();
311 * sub-classes must provide type-specific code to extract data from
312 * and write data to an open registry key.
315 virtual void InternalRead (HKEY hKey, T& value) = 0;
316 virtual void InternalWrite (HKEY hKey, const T& value) = 0;
318 public:
321 * Make the value type accessible to others.
324 typedef T ValueT;
327 * Constructor.
328 * We use this instead of a default constructor because not all
329 * data types may provide an adequate default constructor.
331 CRegTypedBase(const T& def);
334 * Constructor.
335 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
336 * \param def the default value used when the key does not exist or a read error occurred
337 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
338 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
340 CRegTypedBase(const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
343 * Constructor.
344 * \param updateInterval time in msec between registry lookups caused by operator const T&
345 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
346 * \param def the default value used when the key does not exist or a read error occurred
347 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
348 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
350 CRegTypedBase(DWORD updateInterval, const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
353 * reads the assigned value from the registry. Use this method only if you think the registry
354 * value could have been altered without using the CRegDWORD object.
355 * \return the read value
357 void read(); ///< reads the value from the registry
358 void write(); ///< writes the value to the registry
360 bool exists(); ///< test whether registry entry exits
361 const T& defaultValue() const; ///< return the default passed to the constructor
364 * Data access.
367 operator const T&();
368 CRegTypedBase<T,Base>& operator=(const T& rhs);
371 // implement CRegTypedBase<> members
373 template<class T, class Base>
374 void CRegTypedBase<T, Base>::HandleAutoRefresh()
376 if (m_read && (lookupInterval != (DWORD)(-1)))
378 DWORD currentTime = GetTickCount();
379 if ( (currentTime < lastRead)
380 || (currentTime > lastRead + lookupInterval))
382 m_read = false;
387 template<class T, class Base>
388 CRegTypedBase<T, Base>::CRegTypedBase (const T& def)
389 : m_value (def)
390 , m_defaultvalue (def)
391 , lastRead (0)
392 , lookupInterval ((DWORD)-1)
396 template<class T, class Base>
397 CRegTypedBase<T, Base>::CRegTypedBase (const typename Base::StringT& key, const T& def, bool force, HKEY base, REGSAM sam)
398 : Base (key, force, base, sam)
399 , m_value (def)
400 , m_defaultvalue (def)
401 , lastRead (0)
402 , lookupInterval ((DWORD)-1)
406 template<class T, class Base>
407 CRegTypedBase<T, Base>::CRegTypedBase (DWORD lookupInterval, const typename Base::StringT& key, const T& def, bool force, HKEY base, REGSAM sam)
408 : Base (key, force, base, sam)
409 , m_value (def)
410 , m_defaultvalue (def)
411 , lastRead (0)
412 , lookupInterval (lookupInterval)
416 template<class T, class Base>
417 void CRegTypedBase<T, Base>::read()
419 m_value = m_defaultvalue;
420 m_exists = false;
422 HKEY hKey = NULL;
423 if ((LastError = RegOpenKeyEx (m_base, GetPlainString (m_path), 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|m_sam, &hKey))==ERROR_SUCCESS)
426 T value = m_defaultvalue;
427 InternalRead (hKey, value);
429 if (LastError ==ERROR_SUCCESS)
431 m_exists = true;
432 m_value = value;
435 LastError = RegCloseKey(hKey);
438 m_read = true;
439 lastRead = GetTickCount();
442 template<class T, class Base>
443 void CRegTypedBase<T, Base>::write()
445 HKEY hKey = NULL;
447 DWORD disp = 0;
448 if ((LastError = RegCreateKeyEx(m_base, GetPlainString (m_path), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE|m_sam, NULL, &hKey, &disp))!=ERROR_SUCCESS)
450 return;
453 InternalWrite (hKey, m_value);
454 if (LastError ==ERROR_SUCCESS)
456 m_read = true;
457 m_exists = true;
459 LastError = RegCloseKey(hKey);
461 lastRead = GetTickCount();
464 template<class T, class Base>
465 bool CRegTypedBase<T, Base>::exists()
467 if (!m_read && (LastError == ERROR_SUCCESS))
468 read();
470 return m_exists;
473 template<class T, class Base>
474 const T& CRegTypedBase<T, Base>::defaultValue() const
476 return m_defaultvalue;
479 template<class T, class Base>
480 CRegTypedBase<T, Base>::operator const T&()
482 HandleAutoRefresh();
483 if ((m_read)&&(!m_force))
485 LastError = ERROR_SUCCESS;
487 else
489 read();
492 return m_value;
495 template<class T, class Base>
496 CRegTypedBase<T, Base>& CRegTypedBase<T, Base>::operator =(const T& d)
498 if (m_read && (d == m_value) && !m_force)
500 //no write to the registry required, its the same value
501 LastError = ERROR_SUCCESS;
502 return *this;
504 m_value = d;
505 write();
506 return *this;
510 * \ingroup Utils
511 * DWORD value in registry. with this class you can use DWORD values in registry
512 * like normal DWORD variables in your program.
513 * Usage:
514 * in your header file, declare your registry DWORD variable:
515 * \code
516 * CRegDWORD regvalue;
517 * \endcode
518 * next initialize the variable e.g. in the constructor of your class:
519 * \code
520 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
521 * \endcode
522 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
523 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
524 * an error occurred during read from the registry, a default
525 * value of 100 is used when accessing the variable.
526 * now the variable can be used like any other DWORD variable:
527 * \code
528 * regvalue = 200; //stores the value 200 in the registry
529 * int temp = regvalue + 300; //temp has value 500 now
530 * regvalue += 300; //now the registry has the value 500 too
531 * \endcode
532 * to avoid too much access to the registry the value is cached inside the object.
533 * once the value is read, no more read accesses to the registry will be made.
534 * this means the variable will contain a wrong value if the corresponding registry
535 * entry is changed by anything else than this variable! If you think that could happen
536 * then use
537 * \code
538 * regvalue.read();
539 * \endcode
540 * to force a refresh of the variable with the registry.
541 * a write to the registry is only made if the new value assigned with the variable
542 * is different than the last assigned value.
543 * to force a write use the method write();
544 * another option to force reads and writes to the registry is to specify TRUE as the
545 * third parameter in the constructor.
547 template<class Base>
548 class CRegDWORDCommon : public CRegTypedBase<DWORD,Base>
550 private:
553 * provide type-specific code to extract data from and write data to an open registry key.
556 virtual void InternalRead (HKEY hKey, DWORD& value);
557 virtual void InternalWrite (HKEY hKey, const DWORD& value);
559 public:
561 CRegDWORDCommon(void);
563 * Constructor.
564 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
565 * \param def the default value used when the key does not exist or a read error occurred
566 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
567 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
569 CRegDWORDCommon(const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
570 CRegDWORDCommon(DWORD lookupInterval, const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
572 CRegDWORDCommon& operator=(DWORD rhs) {CRegTypedBase<DWORD, Base>::operator =(rhs); return *this;}
573 CRegDWORDCommon& operator+=(DWORD d) { return *this = *this + d;}
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;}
585 // implement CRegDWORDCommon<> methods
587 template<class Base>
588 CRegDWORDCommon<Base>::CRegDWORDCommon(void)
589 : CRegTypedBase<DWORD, Base>(0)
593 template<class Base>
594 CRegDWORDCommon<Base>::CRegDWORDCommon(const typename Base::StringT& key, DWORD def, bool force, HKEY base, REGSAM sam)
595 : CRegTypedBase<DWORD, Base> (key, def, force, base, sam)
599 template<class Base>
600 CRegDWORDCommon<Base>::CRegDWORDCommon(DWORD lookupInterval, const typename Base::StringT& key, DWORD def, bool force, HKEY base, REGSAM sam)
601 : CRegTypedBase<DWORD, Base> (lookupInterval, key, def, force, base, sam)
605 template<class Base>
606 void CRegDWORDCommon<Base>::InternalRead (HKEY hKey, DWORD& value)
608 DWORD size = sizeof(value);
609 DWORD type = 0;
610 if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) &value, &size))==ERROR_SUCCESS)
612 ASSERT(type==REG_DWORD);
616 template<class Base>
617 void CRegDWORDCommon<Base>::InternalWrite (HKEY hKey, const DWORD& value)
619 LastError = RegSetValueEx (hKey, GetPlainString (m_key), 0, REG_DWORD,(const BYTE*) &value, sizeof(value));
623 * \ingroup Utils
624 * CString value in registry. with this class you can use CString values in registry
625 * almost like normal CString variables in your program.
626 * Usage:
627 * in your header file, declare your registry CString variable:
628 * \code
629 * CRegString regvalue;
630 * \endcode
631 * next initialize the variable e.g. in the constructor of your class:
632 * \code
633 * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");
634 * \endcode
635 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
636 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
637 * an error occurred during read from the registry, a default
638 * value of "default" is used when accessing the variable.
639 * now the variable can be used like any other CString variable:
640 * \code
641 * regvalue = "some string"; //stores the value "some string" in the registry
642 * CString temp = regvalue + "!!"; //temp has value "some string!!" now
643 * \endcode
644 * to use the normal methods of the CString class, just typecast the CRegString to a CString
645 * and do whatever you want with the string:
646 * \code
647 * ((CString)regvalue).GetLength();
648 * ((CString)regvalue).Trim();
649 * \endcode
650 * please be aware that in the second line the change in the string won't be written
651 * to the registry! To force a write use the write() method. A write() is only needed
652 * if you change the String with Methods not overloaded by CRegString.
653 * to avoid too much access to the registry the value is cached inside the object.
654 * once the value is read, no more read accesses to the registry will be made.
655 * this means the variable will contain a wrong value if the corresponding registry
656 * entry is changed by anything else than this variable! If you think that could happen
657 * then use
658 * \code
659 * regvalue.read();
660 * \endcode
661 * to force a refresh of the variable with the registry.
662 * a write to the registry is only made if the new value assigned with the variable
663 * is different than the last assigned value.
664 * to force a write use the method write();
665 * another option to force reads and writes to the registry is to specify TRUE as the
666 * third parameter in the constructor.
668 template<class Base>
669 class CRegStringCommon : public CRegTypedBase<typename Base::StringT, Base>
671 private:
674 * provide type-specific code to extract data from and write data to an open registry key.
677 virtual void InternalRead (HKEY hKey, typename Base::StringT& value);
678 virtual void InternalWrite (HKEY hKey, const typename Base::StringT& value);
680 public:
681 CRegStringCommon();
683 * Constructor.
684 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
685 * \param def the default value used when the key does not exist or a read error occurred
686 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
687 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
689 CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def = _T(""), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
690 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);
692 CRegStringCommon& operator=(const typename Base::StringT& rhs) {CRegTypedBase<StringT, Base>::operator =(rhs); return *this;}
693 CRegStringCommon& operator+=(const typename Base::StringT& s) { return *this = (typename Base::StringT)*this + s; }
696 // implement CRegDWORD<> methods
698 template<class Base>
699 CRegStringCommon<Base>::CRegStringCommon(void)
700 : CRegTypedBase<typename Base::StringT, Base>(typename Base::StringT())
704 template<class Base>
705 CRegStringCommon<Base>::CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base, REGSAM sam)
706 : CRegTypedBase<typename Base::StringT, Base> (key, def, force, base, sam)
710 template<class Base>
711 CRegStringCommon<Base>::CRegStringCommon(DWORD lookupInterval, const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base, REGSAM sam)
712 : CRegTypedBase<typename Base::StringT, Base> (lookupInterval, key, def, force, base, sam)
716 template<class Base>
717 void CRegStringCommon<Base>::InternalRead (HKEY hKey, typename Base::StringT& value)
719 DWORD size = 0;
720 DWORD type = 0;
721 LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, NULL, &size);
723 if (LastError == ERROR_SUCCESS)
725 std::unique_ptr<TCHAR[]> pStr (new TCHAR[size]);
726 if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) pStr.get(), &size))==ERROR_SUCCESS)
728 ASSERT(type==REG_SZ || type==REG_EXPAND_SZ);
729 value = StringT (pStr.get());
734 template<class Base>
735 void CRegStringCommon<Base>::InternalWrite (HKEY hKey, const typename Base::StringT& value)
737 LastError = RegSetValueEx(hKey, GetPlainString (m_key), 0, REG_SZ, (BYTE *)GetPlainString (value), (GetLength(value)+1)*sizeof (TCHAR));
741 * \ingroup Utils
742 * CRect value in registry. with this class you can use CRect values in registry
743 * almost like normal CRect variables in your program.
744 * Usage:
745 * in your header file, declare your registry CString variable:
746 * \code
747 * CRegRect regvalue;
748 * \endcode
749 * next initialize the variable e.g. in the constructor of your class:
750 * \code
751 * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));
752 * \endcode
753 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
754 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
755 * an error occurred during read from the registry, a default
756 * value of 100,100,200,200 is used when accessing the variable.
757 * now the variable can be used like any other CRect variable:
758 * \code
759 * regvalue = CRect(40,20,300,500); //stores the value in the registry
760 * CRect temp = regvalue + CPoint(1,1);
761 * temp |= CSize(5,5);
762 * \endcode
763 * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect
764 * and do whatever you want with the rect:
765 * \code
766 * ((CRect)regvalue).MoveToX(100);
767 * ((CRect)regvalue).DeflateRect(10,10);
768 * \endcode
769 * please be aware that in the second line the change in the CRect won't be written
770 * to the registry! To force a write use the write() method. A write() is only needed
771 * if you change the CRect with Methods not overloaded by CRegRect.
772 * to avoid too much access to the registry the value is cached inside the object.
773 * once the value is read, no more read accesses to the registry will be made.
774 * this means the variable will contain a wrong value if the corresponding registry
775 * entry is changed by anything else than this variable! If you think that could happen
776 * then use
777 * \code
778 * regvalue.read();
779 * \endcode
780 * to force a refresh of the variable with the registry.
781 * a write to the registry is only made if the new value assigned with the variable
782 * is different than the last assigned value.
783 * to force a write use the method write();
784 * another option to force reads and writes to the registry is to specify TRUE as the
785 * third parameter in the constructor.
788 #ifdef __ATLTYPES_H__ // defines CRect
789 class CRegRect : public CRegTypedBase<CRect, CRegBase>
791 private:
794 * provide type-specific code to extract data from and write data to an open registry key.
797 virtual void InternalRead (HKEY hKey, CRect& value);
798 virtual void InternalWrite (HKEY hKey, const CRect& value);
800 public:
801 CRegRect();
803 * Constructor.
804 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
805 * \param def the default value used when the key does not exist or a read error occurred
806 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
807 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
809 CRegRect(const CString& key, const CRect& def = CRect(), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
810 ~CRegRect(void);
812 CRegRect& operator=(const CRect& rhs) {CRegTypedBase<CRect, CRegBase>::operator =(rhs); return *this;}
813 operator LPCRECT() { return (LPCRECT)(CRect)*this; }
814 operator LPRECT() { return (LPRECT)(CRect)*this; }
815 CRegRect& operator+=(POINT r) { return *this = (CRect)*this + r;}
816 CRegRect& operator+=(SIZE r) { return *this = (CRect)*this + r;}
817 CRegRect& operator+=(LPCRECT r) { return *this = (CRect)*this + r;}
818 CRegRect& operator-=(POINT r) { return *this = (CRect)*this - r;}
819 CRegRect& operator-=(SIZE r) { return *this = (CRect)*this - r;}
820 CRegRect& operator-=(LPCRECT r) { return *this = (CRect)*this - r;}
822 CRegRect& operator&=(CRect r) { return *this = r & *this;}
823 CRegRect& operator|=(CRect r) { return *this = r | *this;}
825 #endif
828 * \ingroup Utils
829 * CPoint value in registry. with this class you can use CPoint values in registry
830 * almost like normal CPoint variables in your program.
831 * Usage:
832 * in your header file, declare your registry CPoint variable:
833 * \code
834 * CRegPoint regvalue;
835 * \endcode
836 * next initialize the variable e.g. in the constructor of your class:
837 * \code
838 * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));
839 * \endcode
840 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
841 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
842 * an error occurred during read from the registry, a default
843 * value of 100,100 is used when accessing the variable.
844 * now the variable can be used like any other CPoint variable:
845 * \code
846 * regvalue = CPoint(40,20); //stores the value in the registry
847 * CPoint temp = regvalue + CPoint(1,1);
848 * temp += CSize(5,5);
849 * \endcode
850 * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint
851 * and do whatever you want with the point:
852 * \code
853 * ((CRect)regvalue).Offset(100,10);
854 * \endcode
855 * please be aware that in the above example the change in the CPoint won't be written
856 * to the registry! To force a write use the write() method. A write() is only needed
857 * if you change the CPoint with Methods not overloaded by CRegPoint.
858 * to avoid too much access to the registry the value is cached inside the object.
859 * once the value is read, no more read accesses to the registry will be made.
860 * this means the variable will contain a wrong value if the corresponding registry
861 * entry is changed by anything else than this variable! If you think that could happen
862 * then use
863 * \code
864 * regvalue.read();
865 * \endcode
866 * to force a refresh of the variable with the registry.
867 * a write to the registry is only made if the new value assigned with the variable
868 * is different than the last assigned value.
869 * to force a write use the method write();
870 * another option to force reads and writes to the registry is to specify TRUE as the
871 * third parameter in the constructor.
874 #ifdef __ATLTYPES_H__ // defines CPoint
875 class CRegPoint : public CRegTypedBase<CPoint, CRegBase>
877 private:
880 * provide type-specific code to extract data from and write data to an open registry key.
883 virtual void InternalRead (HKEY hKey, CPoint& value);
884 virtual void InternalWrite (HKEY hKey, const CPoint& value);
886 public:
887 CRegPoint();
889 * Constructor.
890 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
891 * \param def the default value used when the key does not exist or a read error occurred
892 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
893 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
895 CRegPoint(const CString& key, const CPoint& def = CPoint(), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
896 ~CRegPoint(void);
898 CRegPoint& operator=(const CPoint& rhs) {CRegTypedBase<CPoint, CRegBase>::operator =(rhs); return *this;}
899 CRegPoint& operator+=(CPoint p) { return *this = p + *this; }
900 CRegPoint& operator-=(CPoint p) { return *this = p - *this; }
902 #endif
905 * \ingroup Utils
906 * Manages a registry key (not a value). Provides methods to create and remove the
907 * key and to query the list of values and sub keys.
910 #ifdef __AFXCOLL_H__ // defines CStringList
911 class CRegistryKey
913 public: //methods
915 * Constructor.
916 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey"
917 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
919 CRegistryKey(const CString& key, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
920 ~CRegistryKey();
923 * Creates the registry key if it does not already exist.
924 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
926 DWORD createKey();
928 * Removes the whole registry key including all values. So if you set the registry
929 * entry to be HKCU\Software\Company\Product\key there will only be
930 * HKCU\Software\Company\Product key in the registry.
931 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
933 DWORD removeKey();
935 bool getValues(CStringList& values); ///< returns the list of values
936 bool getSubKeys(CStringList& subkeys); ///< returns the list of sub keys
938 public: //members
939 HKEY m_base; ///< handle to the registry base
940 HKEY m_hKey; ///< handle to the open registry key
941 REGSAM m_sam; ///< the security attributes to pass to the registry command
942 CString m_path; ///< the path to the key
944 #endif
946 #ifdef _MAP_
947 template<class T>
948 class CKeyList
950 private:
952 /// constructor parameters
954 typename T::StringT key;
955 typename T::ValueT defaultValue;
956 HKEY base;
958 /// per-index defaults
960 typedef std::map<int, typename T::ValueT> TDefaults;
961 TDefaults defaults;
963 /// the indices accessed so far
965 typedef std::map<int, T*> TElements;
966 mutable TElements elements;
968 /// auto-insert
970 const typename T::ValueT& GetDefault (int index) const;
971 T& GetAt (int index) const;
973 public:
975 /// construction
977 CKeyList (const typename T::StringT& key, const typename T::ValueT& defaultValue, HKEY base = HKEY_CURRENT_USER)
978 : key (key)
979 , defaultValue (defaultValue)
980 , base (base)
984 /// destruction: delete all elements
986 ~CKeyList()
988 for ( TElements::iterator iter = elements.begin()
989 , end = elements.end()
990 ; iter != end
991 ; ++iter)
993 delete iter->second;
997 /// data access
999 const T& operator[] (int index) const
1001 return GetAt (index);
1004 T& operator[] (int index)
1006 return GetAt (index);
1009 const TDefaults& GetDefaults() const
1011 return defaults;
1014 TDefaults& GetDefaults()
1016 return defaults;
1019 const typename T::ValueT& GetDefault() const
1021 return defaultValue;
1025 /// auto-insert
1027 template<class T>
1028 const typename T::ValueT& CKeyList<T>::GetDefault (int index) const
1030 TDefaults::const_iterator iter = defaults.find (index);
1031 return iter == defaults.end() ? defaultValue : iter->second;
1034 template<class T>
1035 T& CKeyList<T>::GetAt (int index) const
1037 TElements::iterator iter = elements.find (index);
1038 if (iter == elements.end())
1040 TCHAR buffer [10];
1041 _itot_s (index, buffer, 10);
1042 typename T::StringT indexKey = key + _T ('\\') + buffer;
1044 T* newElement = new T (indexKey, GetDefault (index), false, base);
1045 iter = elements.insert (std::make_pair (index, newElement)).first;
1048 return *iter->second;
1051 #endif
1054 * Instantiate templates for common (data type, string type) combinations.
1057 #ifdef __CSTRINGT_H__
1058 CRegDWORDCommon<CRegBase>;
1059 typedef CRegDWORDCommon<CRegBase> CRegDWORD;
1060 CRegStringCommon<CRegBase>;
1061 typedef CRegStringCommon<CRegBase> CRegString;
1063 #ifdef _MAP_
1064 CKeyList<CRegDWORD>;
1065 typedef CKeyList<CRegDWORD> CRegDWORDList;
1066 CKeyList<CRegString>;
1067 typedef CKeyList<CRegString> CRegStringList;
1068 #endif
1069 #endif
1071 CRegDWORDCommon<CRegStdBase>;
1072 typedef CRegDWORDCommon<CRegStdBase> CRegStdDWORD;
1073 CRegStringCommon<CRegStdBase>;
1074 typedef CRegStringCommon<CRegStdBase> CRegStdString;
1076 #ifdef _MAP_
1077 CKeyList<CRegStdDWORD>;
1078 typedef CKeyList<CRegStdDWORD> CRegStdDWORDList;
1079 CKeyList<CRegStdString>;
1080 typedef CKeyList<CRegStdString> CRegStdStringList;
1081 #endif