OSDN Git Service

Add TortoiseIDiff to project.
[tortoisegit/TortoiseGitJp.git] / src / Utils / registry.h
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #pragma once\r
20 #include <string>\r
21 #include <memory>\r
22 #include "shlwapi.h"\r
23 #include "tstring.h"\r
24 \r
25 #ifndef ASSERT\r
26 #define ASSERT(x)\r
27 #endif\r
28 \r
29 /**\r
30  * \ingroup Utils\r
31  * Base class for the registry classes.\r
32  *\r
33  * \par requirements \r
34  * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later\r
35  * - import library Shlwapi.lib\r
36  */\r
37 \r
38 template<class S>\r
39 class CRegBaseCommon\r
40 {\r
41 protected:\r
42 \r
43     /**\r
44      * String type specific operations.\r
45      */\r
46 \r
47     virtual LPCTSTR GetPlainString (const S& s) const = 0;\r
48     virtual DWORD GetLength (const S& s) const = 0;\r
49 \r
50 public: //methods\r
51 \r
52     /** Default constructor.\r
53      */\r
54     CRegBaseCommon();\r
55         /**\r
56          * Constructor.\r
57          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
58          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
59          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
60          */\r
61         CRegBaseCommon(const S& key, bool force, HKEY base = HKEY_CURRENT_USER);\r
62 \r
63         /**\r
64          * Removes the whole registry key including all values. So if you set the registry\r
65          * entry to be HKCU\Software\Company\Product\key\value there will only be\r
66          * HKCU\Software\Company\Product key in the registry.\r
67          * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.\r
68          */\r
69         DWORD removeKey();\r
70         /**\r
71          * Removes the value of the registry object. If you set the registry entry to\r
72          * be HKCU\Software\Company\Product\key\value there will only be\r
73          * HKCU\Software\Company\Product\key\ in the registry.\r
74          * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.\r
75          */\r
76         LONG removeValue();\r
77 \r
78         /**\r
79          * Returns the string of the last error occurred.\r
80          */\r
81         virtual S getErrorString()\r
82         {\r
83                 LPVOID lpMsgBuf;\r
84 \r
85                 FormatMessage(\r
86                         FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
87                         FORMAT_MESSAGE_FROM_SYSTEM |\r
88                         FORMAT_MESSAGE_IGNORE_INSERTS,\r
89                         NULL,\r
90                         LastError,\r
91                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
92                         (LPTSTR) &lpMsgBuf,\r
93                         0, NULL );\r
94 \r
95                 return (LPCTSTR)lpMsgBuf;\r
96         };\r
97 \r
98 public: \r
99     \r
100     typedef S StringT;  ///< used in subclass templates to specify the correct string type\r
101 \r
102     //members\r
103         HKEY m_base;            ///< handle to the registry base\r
104         S m_key;                    ///< the name of the value\r
105         S m_path;                   ///< the path to the key\r
106         LONG LastError;         ///< the value of the last error occurred\r
107 \r
108         bool m_read;            ///< indicates if the value has already been read from the registry\r
109         bool m_force;           ///< indicates if no cache should be used, i.e. always read and write directly from registry\r
110     bool m_exists;      ///< true, if the registry actually exists\r
111 };\r
112 \r
113 // implement CRegBaseCommon<> members\r
114 \r
115 template<class S>\r
116 CRegBaseCommon<S>::CRegBaseCommon()\r
117     : m_base (HKEY_CURRENT_USER)\r
118     , m_key()\r
119     , m_path()\r
120     , LastError (ERROR_SUCCESS)\r
121     , m_read (false)\r
122     , m_force (false)\r
123     , m_exists (false)\r
124 {\r
125 }\r
126 \r
127 template<class S>\r
128 CRegBaseCommon<S>::CRegBaseCommon (const S& key, bool force, HKEY base)\r
129     : m_base (base)\r
130         , m_key (key)\r
131     , m_path()\r
132     , LastError (ERROR_SUCCESS)\r
133     , m_read (false)\r
134     , m_force (force)\r
135     , m_exists (false)\r
136 {\r
137 }\r
138 \r
139 template<class S>\r
140 DWORD CRegBaseCommon<S>::removeKey() \r
141\r
142     m_exists = false;\r
143     m_read = true;\r
144 \r
145     HKEY hKey = NULL;\r
146     RegOpenKeyEx (m_base, GetPlainString (m_path), 0, KEY_WRITE, &hKey); \r
147     return SHDeleteKey(m_base, GetPlainString (m_path)); \r
148 }\r
149 \r
150 template<class S>\r
151 LONG CRegBaseCommon<S>::removeValue() \r
152\r
153     m_exists = false;\r
154     m_read = true;\r
155 \r
156     HKEY hKey = NULL;\r
157     RegOpenKeyEx(m_base, GetPlainString (m_path), 0, KEY_WRITE, &hKey); \r
158     return RegDeleteValue(hKey, GetPlainString (m_key)); \r
159 }\r
160 \r
161 /**\r
162  * \ingroup Utils\r
163  * Base class for MFC type registry classes.\r
164  */\r
165 \r
166 #ifdef __CSTRINGT_H__\r
167 class CRegBase : public CRegBaseCommon<CString>\r
168 {\r
169 protected:\r
170 \r
171     /**\r
172      * String type specific operations.\r
173      */\r
174 \r
175     virtual LPCTSTR GetPlainString (const CString& s) const {return (LPCTSTR)s;}\r
176     virtual DWORD GetLength (const CString& s) const {return s.GetLength();}\r
177 \r
178 public: //methods\r
179 \r
180     /** Default constructor.\r
181      */\r
182     CRegBase();\r
183         /**\r
184          * Constructor.\r
185          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
186          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
187          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
188          */\r
189         CRegBase(const CString& key, bool force, HKEY base = HKEY_CURRENT_USER);\r
190 \r
191         /**\r
192          * Returns the string of the last error occurred.\r
193          */\r
194         CString getErrorString()\r
195         {\r
196         CString error = CRegBaseCommon<CString>::getErrorString();\r
197 #if defined IDS_REG_ERROR\r
198                 CString sTemp;\r
199                 sTemp.Format(IDS_REG_ERROR, (LPCTSTR)m_key, (LPCTSTR)error);\r
200                 return sTemp;\r
201 #else\r
202                 return error;\r
203 #endif\r
204         };\r
205 };\r
206 #endif\r
207 \r
208 typedef std::wstring wide_string;\r
209 #ifndef stdstring\r
210 #       ifdef UNICODE\r
211 #               define stdstring wide_string\r
212 #       else\r
213 #               define stdstring std::string\r
214 #       endif\r
215 #endif\r
216 \r
217 /**\r
218  * \ingroup Utils\r
219  * Base class for STL string type registry classes.\r
220  */\r
221 \r
222 class CRegStdBase : public CRegBaseCommon<stdstring>\r
223 {\r
224 protected:\r
225 \r
226     /**\r
227      * String type specific operations.\r
228      */\r
229 \r
230     virtual LPCTSTR GetPlainString (const stdstring& s) const {return s.c_str();}\r
231     virtual DWORD GetLength (const stdstring& s) const {return static_cast<DWORD>(s.size());}\r
232 \r
233 public: //methods\r
234 \r
235     /** Default constructor.\r
236      */\r
237     CRegStdBase();\r
238         /**\r
239          * Constructor.\r
240          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
241          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
242          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
243          */\r
244         CRegStdBase(const stdstring& key, bool force, HKEY base = HKEY_CURRENT_USER);\r
245 };\r
246 \r
247 /**\r
248  * \ingroup Utils\r
249  * DWORD value in registry. with this class you can use DWORD values in registry\r
250  * like normal DWORD variables in your program.\r
251  * Usage:\r
252  * in your header file, declare your registry DWORD variable:\r
253  * \code\r
254  * CRegDWORD regvalue;\r
255  * \endcode\r
256  * next initialize the variable e.g. in the constructor of your class:\r
257  * \code\r
258  * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);\r
259  * \endcode\r
260  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
261  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
262  * an error occurred during read from the registry, a default\r
263  * value of 100 is used when accessing the variable.\r
264  * now the variable can be used like any other DWORD variable:\r
265  * \code\r
266  * regvalue = 200;                                              //stores the value 200 in the registry\r
267  * int temp = regvalue + 300;                   //temp has value 500 now\r
268  * regvalue += 300;                                             //now the registry has the value 500 too\r
269  * \endcode\r
270  * to avoid too much access to the registry the value is cached inside the object.\r
271  * once the value is read, no more read accesses to the registry will be made.\r
272  * this means the variable will contain a wrong value if the corresponding registry\r
273  * entry is changed by anything else than this variable! If you think that could happen\r
274  * then use \r
275  * \code\r
276  * regvalue.read();\r
277  * \endcode\r
278  * to force a refresh of the variable with the registry.\r
279  * a write to the registry is only made if the new value assigned with the variable\r
280  * is different than the last assigned value.\r
281  * to force a write use the method write();\r
282  * another option to force reads and writes to the registry is to specify TRUE as the\r
283  * third parameter in the constructor.\r
284  */\r
285 template<class T, class Base>\r
286 class CRegTypedBase : public Base\r
287 {\r
288 private:\r
289 \r
290         T m_value;                                      ///< the cached value of the registry\r
291         T m_defaultvalue;                       ///< the default value to use\r
292 \r
293     /**\r
294      * sub-classes must provide type-specific code to extract data from\r
295      * and write data to an open registry key.\r
296      */\r
297 \r
298     virtual void InternalRead (HKEY hKey, T& value) = 0;\r
299     virtual void InternalWrite (HKEY hKey, const T& value) = 0;\r
300 \r
301 public:\r
302 \r
303     /**\r
304      * We use this instead of a default constructor because not all \r
305      * data types may provide an adequate default constructor.\r
306      */\r
307         CRegTypedBase(const T& def);\r
308 \r
309         /**\r
310          * Constructor.\r
311          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
312          * \param def the default value used when the key does not exist or a read error occurred\r
313          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
314          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
315          */\r
316     CRegTypedBase(const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER);\r
317 \r
318         /**\r
319          * reads the assigned value from the registry. Use this method only if you think the registry\r
320          * value could have been altered without using the CRegDWORD object.\r
321          * \return the read value\r
322          */\r
323         void    read();                                         ///< reads the value from the registry\r
324         void    write();                                        ///< writes the value to the registry\r
325 \r
326     /**\r
327      * Data access.\r
328      */\r
329 \r
330     operator const T&();\r
331         CRegTypedBase<T,Base>& operator=(const T& rhs);\r
332 };\r
333 \r
334 // implement CRegTypedBase<> members\r
335 \r
336 template<class T, class Base>\r
337 CRegTypedBase<T, Base>::CRegTypedBase (const T& def)\r
338     : m_value (def)\r
339     , m_defaultvalue (def)\r
340 {\r
341 }\r
342 \r
343 template<class T, class Base>\r
344 CRegTypedBase<T, Base>::CRegTypedBase (const typename Base::StringT& key, const T& def, bool force, HKEY base)\r
345     : Base (key, force, base)\r
346     , m_value (def)\r
347     , m_defaultvalue (def)\r
348 {\r
349 }\r
350 \r
351 template<class T, class Base>\r
352 void CRegTypedBase<T, Base>::read()\r
353 {\r
354         m_value = m_defaultvalue;\r
355     m_exists = false;\r
356 \r
357     HKEY hKey = NULL;\r
358         if ((LastError = RegOpenKeyEx (m_base, GetPlainString (m_path), 0, KEY_EXECUTE, &hKey))==ERROR_SUCCESS)\r
359         {\r
360                 m_read = true;\r
361 \r
362         T value = m_defaultvalue;\r
363         InternalRead (hKey, value);\r
364 \r
365                 if (LastError ==ERROR_SUCCESS)\r
366                 {\r
367             m_exists = true;\r
368                         m_value = value;\r
369                 }\r
370 \r
371         LastError = RegCloseKey(hKey);\r
372         }\r
373 }\r
374 \r
375 template<class T, class Base>\r
376 void CRegTypedBase<T, Base>::write()\r
377 {\r
378     HKEY hKey = NULL;\r
379 \r
380     DWORD disp = 0;\r
381         if ((LastError = RegCreateKeyEx(m_base, GetPlainString (m_path), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &disp))!=ERROR_SUCCESS)\r
382         {\r
383                 return;\r
384         }\r
385 \r
386     InternalWrite (hKey, m_value);\r
387         if (LastError ==ERROR_SUCCESS)\r
388         {\r
389                 m_read = true;\r
390         m_exists = true;\r
391         }\r
392         LastError = RegCloseKey(hKey);\r
393 }\r
394 \r
395 \r
396 template<class T, class Base>\r
397 CRegTypedBase<T, Base>::operator const T&()\r
398 {\r
399         if ((m_read)&&(!m_force))\r
400         {\r
401                 LastError = 0;\r
402         }\r
403         else\r
404         {\r
405                 read();\r
406         }\r
407 \r
408         return m_value;\r
409 }\r
410 \r
411 template<class T, class Base>\r
412 CRegTypedBase<T, Base>& CRegTypedBase<T, Base>::operator =(const T& d)\r
413 {\r
414         if ((d==m_value)&&(!m_force))\r
415         {\r
416                 //no write to the registry required, its the same value\r
417                 LastError = 0;\r
418                 return *this;\r
419         }\r
420         m_value = d;\r
421         write();\r
422         return *this;\r
423 }\r
424 \r
425 /**\r
426  * \ingroup Utils\r
427  * DWORD value in registry. with this class you can use DWORD values in registry\r
428  * like normal DWORD variables in your program.\r
429  * Usage:\r
430  * in your header file, declare your registry DWORD variable:\r
431  * \code\r
432  * CRegDWORD regvalue;\r
433  * \endcode\r
434  * next initialize the variable e.g. in the constructor of your class:\r
435  * \code\r
436  * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);\r
437  * \endcode\r
438  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
439  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
440  * an error occurred during read from the registry, a default\r
441  * value of 100 is used when accessing the variable.\r
442  * now the variable can be used like any other DWORD variable:\r
443  * \code\r
444  * regvalue = 200;                                              //stores the value 200 in the registry\r
445  * int temp = regvalue + 300;                   //temp has value 500 now\r
446  * regvalue += 300;                                             //now the registry has the value 500 too\r
447  * \endcode\r
448  * to avoid too much access to the registry the value is cached inside the object.\r
449  * once the value is read, no more read accesses to the registry will be made.\r
450  * this means the variable will contain a wrong value if the corresponding registry\r
451  * entry is changed by anything else than this variable! If you think that could happen\r
452  * then use \r
453  * \code\r
454  * regvalue.read();\r
455  * \endcode\r
456  * to force a refresh of the variable with the registry.\r
457  * a write to the registry is only made if the new value assigned with the variable\r
458  * is different than the last assigned value.\r
459  * to force a write use the method write();\r
460  * another option to force reads and writes to the registry is to specify TRUE as the\r
461  * third parameter in the constructor.\r
462  */\r
463 template<class Base>\r
464 class CRegDWORDCommon : public CRegTypedBase<DWORD,Base>\r
465 {\r
466 private:\r
467 \r
468     /**\r
469      * provide type-specific code to extract data from and write data to an open registry key.\r
470      */\r
471 \r
472     virtual void InternalRead (HKEY hKey, DWORD& value);\r
473     virtual void InternalWrite (HKEY hKey, const DWORD& value);\r
474 \r
475 public:\r
476 \r
477         CRegDWORDCommon(void);\r
478         /**\r
479          * Constructor.\r
480          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
481          * \param def the default value used when the key does not exist or a read error occurred\r
482          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
483          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
484          */\r
485     CRegDWORDCommon(const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER);\r
486 \r
487     CRegDWORDCommon& operator=(DWORD rhs) {CRegTypedBase<DWORD, Base>::operator =(rhs); return *this;}\r
488         CRegDWORDCommon& operator+=(DWORD d) { return *this = *this + d;}\r
489         CRegDWORDCommon& operator-=(DWORD d) { return *this = *this - d;}\r
490         CRegDWORDCommon& operator*=(DWORD d) { return *this = *this * d;}\r
491         CRegDWORDCommon& operator/=(DWORD d) { return *this = *this / d;}\r
492         CRegDWORDCommon& operator%=(DWORD d) { return *this = *this % d;}\r
493         CRegDWORDCommon& operator<<=(DWORD d) { return *this = *this << d;}\r
494         CRegDWORDCommon& operator>>=(DWORD d) { return *this = *this >> d;}\r
495         CRegDWORDCommon& operator&=(DWORD d) { return *this = *this & d;}\r
496         CRegDWORDCommon& operator|=(DWORD d) { return *this = *this | d;}\r
497         CRegDWORDCommon& operator^=(DWORD d) { return *this = *this ^ d;}\r
498 };\r
499 \r
500 // implement CRegDWORDCommon<> methods\r
501 \r
502 template<class Base>\r
503 CRegDWORDCommon<Base>::CRegDWORDCommon(void)\r
504     : CRegTypedBase<DWORD, Base>(0)\r
505 {\r
506 }\r
507 \r
508 template<class Base>\r
509 CRegDWORDCommon<Base>::CRegDWORDCommon(const typename Base::StringT& key, DWORD def, bool force, HKEY base)\r
510     : CRegTypedBase<DWORD, Base> (key, def, force, base)\r
511 {\r
512         read();\r
513 }\r
514 \r
515 template<class Base>\r
516 void CRegDWORDCommon<Base>::InternalRead (HKEY hKey, DWORD& value)\r
517 {\r
518     DWORD size = sizeof(value);\r
519         DWORD type = 0;\r
520         if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) &value, &size))==ERROR_SUCCESS)\r
521     {\r
522                 ASSERT(type==REG_DWORD);\r
523     }\r
524 }\r
525 \r
526 template<class Base>\r
527 void CRegDWORDCommon<Base>::InternalWrite (HKEY hKey, const DWORD& value)\r
528 {\r
529         LastError = RegSetValueEx (hKey, GetPlainString (m_key), 0, REG_DWORD,(const BYTE*) &value, sizeof(value));\r
530 }\r
531 \r
532 /**\r
533  * \ingroup Utils\r
534  * CString value in registry. with this class you can use CString values in registry\r
535  * almost like normal CString variables in your program.\r
536  * Usage:\r
537  * in your header file, declare your registry CString variable:\r
538  * \code\r
539  * CRegString regvalue;\r
540  * \endcode\r
541  * next initialize the variable e.g. in the constructor of your class:\r
542  * \code\r
543  * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");\r
544  * \endcode\r
545  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
546  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
547  * an error occurred during read from the registry, a default\r
548  * value of "default" is used when accessing the variable.\r
549  * now the variable can be used like any other CString variable:\r
550  * \code\r
551  * regvalue = "some string";                    //stores the value "some string" in the registry\r
552  * CString temp = regvalue + "!!";              //temp has value "some string!!" now\r
553  * \endcode\r
554  * to use the normal methods of the CString class, just typecast the CRegString to a CString\r
555  * and do whatever you want with the string:\r
556  * \code\r
557  * ((CString)regvalue).GetLength();\r
558  * ((CString)regvalue).Trim();\r
559  * \endcode\r
560  * please be aware that in the second line the change in the string won't be written\r
561  * to the registry! To force a write use the write() method. A write() is only needed\r
562  * if you change the String with Methods not overloaded by CRegString.\r
563  * to avoid too much access to the registry the value is cached inside the object.\r
564  * once the value is read, no more read accesses to the registry will be made.\r
565  * this means the variable will contain a wrong value if the corresponding registry\r
566  * entry is changed by anything else than this variable! If you think that could happen\r
567  * then use \r
568  * \code\r
569  * regvalue.read();\r
570  * \endcode\r
571  * to force a refresh of the variable with the registry.\r
572  * a write to the registry is only made if the new value assigned with the variable\r
573  * is different than the last assigned value.\r
574  * to force a write use the method write();\r
575  * another option to force reads and writes to the registry is to specify TRUE as the\r
576  * third parameter in the constructor.\r
577  */\r
578 template<class Base>\r
579 class CRegStringCommon : public CRegTypedBase<typename Base::StringT, Base>\r
580 {\r
581 private:\r
582 \r
583     /**\r
584      * provide type-specific code to extract data from and write data to an open registry key.\r
585      */\r
586 \r
587     virtual void InternalRead (HKEY hKey, typename Base::StringT& value);\r
588     virtual void InternalWrite (HKEY hKey, const typename Base::StringT& value);\r
589 \r
590 public:\r
591         CRegStringCommon();\r
592         /**\r
593          * Constructor.\r
594          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
595          * \param def the default value used when the key does not exist or a read error occurred\r
596          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
597          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
598          */\r
599     CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def = _T(""), bool force = false, HKEY base = HKEY_CURRENT_USER);\r
600         \r
601     CRegStringCommon& operator=(const typename Base::StringT& rhs) {CRegTypedBase<StringT, Base>::operator =(rhs); return *this;}\r
602         CRegStringCommon& operator+=(const typename Base::StringT& s) { return *this = (typename Base::StringT)*this + s; }\r
603 };\r
604 \r
605 // implement CRegDWORD<> methods\r
606 \r
607 template<class Base>\r
608 CRegStringCommon<Base>::CRegStringCommon(void)\r
609     : CRegTypedBase<typename Base::StringT, Base>(typename Base::StringT())\r
610 {\r
611 }\r
612 \r
613 template<class Base>\r
614 CRegStringCommon<Base>::CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base)\r
615     : CRegTypedBase<typename Base::StringT, Base> (key, def, force, base)\r
616 {\r
617         read();\r
618 }\r
619 \r
620 template<class Base>\r
621 void CRegStringCommon<Base>::InternalRead (HKEY hKey, typename Base::StringT& value)\r
622 {\r
623         DWORD size = 0;\r
624         DWORD type = 0;\r
625         LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, NULL, &size);\r
626 \r
627     std::auto_ptr<TCHAR> pStr (new TCHAR[size]);\r
628         if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) pStr.get(), &size))==ERROR_SUCCESS)\r
629     {\r
630         ASSERT(type==REG_SZ || type==REG_EXPAND_SZ);\r
631         value = StringT (pStr.get());\r
632     }\r
633 }\r
634 \r
635 template<class Base>\r
636 void CRegStringCommon<Base>::InternalWrite (HKEY hKey, const typename Base::StringT& value)\r
637 {\r
638         LastError = RegSetValueEx(hKey, GetPlainString (m_key), 0, REG_SZ, (BYTE *)GetPlainString (value), (GetLength(value)+1)*sizeof (TCHAR));\r
639 }\r
640 \r
641 /**\r
642  * \ingroup Utils\r
643  * CRect value in registry. with this class you can use CRect values in registry\r
644  * almost like normal CRect variables in your program.\r
645  * Usage:\r
646  * in your header file, declare your registry CString variable:\r
647  * \code\r
648  * CRegRect regvalue;\r
649  * \endcode\r
650  * next initialize the variable e.g. in the constructor of your class:\r
651  * \code\r
652  * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));\r
653  * \endcode\r
654  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
655  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
656  * an error occurred during read from the registry, a default\r
657  * value of 100,100,200,200 is used when accessing the variable.\r
658  * now the variable can be used like any other CRect variable:\r
659  * \code\r
660  * regvalue = CRect(40,20,300,500);                             //stores the value in the registry\r
661  * CRect temp = regvalue + CPoint(1,1);\r
662  * temp |= CSize(5,5);\r
663  * \endcode\r
664  * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect\r
665  * and do whatever you want with the rect:\r
666  * \code\r
667  * ((CRect)regvalue).MoveToX(100);\r
668  * ((CRect)regvalue).DeflateRect(10,10);\r
669  * \endcode\r
670  * please be aware that in the second line the change in the CRect won't be written\r
671  * to the registry! To force a write use the write() method. A write() is only needed\r
672  * if you change the CRect with Methods not overloaded by CRegRect.\r
673  * to avoid too much access to the registry the value is cached inside the object.\r
674  * once the value is read, no more read accesses to the registry will be made.\r
675  * this means the variable will contain a wrong value if the corresponding registry\r
676  * entry is changed by anything else than this variable! If you think that could happen\r
677  * then use \r
678  * \code\r
679  * regvalue.read();\r
680  * \endcode\r
681  * to force a refresh of the variable with the registry.\r
682  * a write to the registry is only made if the new value assigned with the variable\r
683  * is different than the last assigned value.\r
684  * to force a write use the method write();\r
685  * another option to force reads and writes to the registry is to specify TRUE as the\r
686  * third parameter in the constructor.\r
687  */\r
688 \r
689 #ifdef __ATLTYPES_H__   // defines CRect \r
690 class CRegRect : public CRegTypedBase<CRect, CRegBase>\r
691 {\r
692 private:\r
693 \r
694     /**\r
695      * provide type-specific code to extract data from and write data to an open registry key.\r
696      */\r
697 \r
698     virtual void InternalRead (HKEY hKey, CRect& value);\r
699     virtual void InternalWrite (HKEY hKey, const CRect& value);\r
700 \r
701 public:\r
702         CRegRect();\r
703         /**\r
704          * Constructor.\r
705          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
706          * \param def the default value used when the key does not exist or a read error occurred\r
707          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
708          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
709          */\r
710         CRegRect(const CString& key, const CRect& def = CRect(), bool force = false, HKEY base = HKEY_CURRENT_USER);\r
711         ~CRegRect(void);\r
712         \r
713     CRegRect& operator=(const CRect& rhs) {CRegTypedBase<CRect, CRegBase>::operator =(rhs); return *this;}\r
714         operator LPCRECT() { return (LPCRECT)(CRect)*this; }\r
715         operator LPRECT() { return (LPRECT)(CRect)*this; }\r
716         CRegRect& operator+=(POINT r) { return *this = (CRect)*this + r;}\r
717         CRegRect& operator+=(SIZE r) { return *this = (CRect)*this + r;}\r
718         CRegRect& operator+=(LPCRECT  r) { return *this = (CRect)*this + r;}\r
719         CRegRect& operator-=(POINT r) { return *this = (CRect)*this - r;}\r
720         CRegRect& operator-=(SIZE r) { return *this = (CRect)*this - r;}\r
721         CRegRect& operator-=(LPCRECT  r) { return *this = (CRect)*this - r;}\r
722         \r
723         CRegRect& operator&=(CRect r) { return *this = r & *this;}\r
724         CRegRect& operator|=(CRect r) { return *this = r | *this;}\r
725 };\r
726 #endif\r
727 \r
728 /**\r
729  * \ingroup Utils\r
730  * CPoint value in registry. with this class you can use CPoint values in registry\r
731  * almost like normal CPoint variables in your program.\r
732  * Usage:\r
733  * in your header file, declare your registry CPoint variable:\r
734  * \code\r
735  * CRegPoint regvalue;\r
736  * \endcode\r
737  * next initialize the variable e.g. in the constructor of your class:\r
738  * \code\r
739  * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));\r
740  * \endcode\r
741  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
742  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
743  * an error occurred during read from the registry, a default\r
744  * value of 100,100 is used when accessing the variable.\r
745  * now the variable can be used like any other CPoint variable:\r
746  * \code\r
747  * regvalue = CPoint(40,20);                                    //stores the value in the registry\r
748  * CPoint temp = regvalue + CPoint(1,1);\r
749  * temp += CSize(5,5);\r
750  * \endcode\r
751  * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint\r
752  * and do whatever you want with the point:\r
753  * \code\r
754  * ((CRect)regvalue).Offset(100,10);\r
755  * \endcode\r
756  * please be aware that in the above example the change in the CPoint won't be written\r
757  * to the registry! To force a write use the write() method. A write() is only needed\r
758  * if you change the CPoint with Methods not overloaded by CRegPoint.\r
759  * to avoid too much access to the registry the value is cached inside the object.\r
760  * once the value is read, no more read accesses to the registry will be made.\r
761  * this means the variable will contain a wrong value if the corresponding registry\r
762  * entry is changed by anything else than this variable! If you think that could happen\r
763  * then use \r
764  * \code\r
765  * regvalue.read();\r
766  * \endcode\r
767  * to force a refresh of the variable with the registry.\r
768  * a write to the registry is only made if the new value assigned with the variable\r
769  * is different than the last assigned value.\r
770  * to force a write use the method write();\r
771  * another option to force reads and writes to the registry is to specify TRUE as the\r
772  * third parameter in the constructor.\r
773  */\r
774 \r
775 #ifdef __ATLTYPES_H__   // defines CPoint \r
776 class CRegPoint : public CRegTypedBase<CPoint, CRegBase>\r
777 {\r
778 private:\r
779 \r
780     /**\r
781      * provide type-specific code to extract data from and write data to an open registry key.\r
782      */\r
783 \r
784     virtual void InternalRead (HKEY hKey, CPoint& value);\r
785     virtual void InternalWrite (HKEY hKey, const CPoint& value);\r
786 \r
787 public:\r
788         CRegPoint();\r
789         /**\r
790          * Constructor.\r
791          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
792          * \param def the default value used when the key does not exist or a read error occurred\r
793          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
794          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
795          */\r
796         CRegPoint(const CString& key, const CPoint& def = CPoint(), bool force = false, HKEY base = HKEY_CURRENT_USER);\r
797         ~CRegPoint(void);\r
798         \r
799     CRegPoint& operator=(const CPoint& rhs) {CRegTypedBase<CPoint, CRegBase>::operator =(rhs); return *this;}\r
800         CRegPoint& operator+=(CPoint p) { return *this = p + *this; }\r
801         CRegPoint& operator-=(CPoint p) { return *this = p - *this; }\r
802 };\r
803 #endif\r
804 \r
805 /**\r
806  * \ingroup Utils\r
807  * Manages a registry key (not a value). Provides methods to create and remove the\r
808  * key and to query the list of values and sub keys.\r
809  */\r
810 \r
811 #ifdef __AFXCOLL_H__   // defines CStringList \r
812 class CRegistryKey\r
813 {\r
814 public: //methods\r
815         /**\r
816          * Constructor.\r
817          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey"\r
818          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
819          */\r
820         CRegistryKey(const CString& key, HKEY base = HKEY_CURRENT_USER);\r
821         ~CRegistryKey();\r
822 \r
823         /**\r
824          * Creates the registry key if it does not already exist.\r
825          * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.\r
826          */\r
827         DWORD createKey();\r
828         /**\r
829          * Removes the whole registry key including all values. So if you set the registry\r
830          * entry to be HKCU\Software\Company\Product\key there will only be\r
831          * HKCU\Software\Company\Product key in the registry.\r
832          * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.\r
833          */\r
834         DWORD removeKey();\r
835 \r
836         bool getValues(CStringList& values);            ///< returns the list of values\r
837         bool getSubKeys(CStringList& subkeys);          ///< returns the list of sub keys\r
838 \r
839 public: //members\r
840         HKEY m_base;            ///< handle to the registry base\r
841         HKEY m_hKey;            ///< handle to the open registry key\r
842         CString m_path;         ///< the path to the key\r
843 };\r
844 #endif\r
845 \r
846 /**\r
847  * Instantiate templates for common (data type, string type) combinations.\r
848  */\r
849 \r
850 #ifdef __CSTRINGT_H__\r
851 CRegDWORDCommon<CRegBase>;\r
852 typedef CRegDWORDCommon<CRegBase> CRegDWORD;\r
853 CRegStringCommon<CRegBase>;\r
854 typedef CRegStringCommon<CRegBase> CRegString;\r
855 #endif\r
856 \r
857 CRegDWORDCommon<CRegStdBase>;\r
858 typedef CRegDWORDCommon<CRegStdBase> CRegStdWORD;\r
859 typedef CRegDWORDCommon<CRegStdBase> CRegStdDWORD;\r
860 CRegStringCommon<CRegStdBase>;\r
861 typedef CRegStringCommon<CRegStdBase> CRegStdString;\r
862 \r
863 \r