3 /////////////////////////////////////////////////////////////////////////////
5 // Copyright (c) 2002 Iain Murray, Inference Group, Cavendish, Cambridge.
7 /////////////////////////////////////////////////////////////////////////////
11 #include "WinOptions.h"
13 using namespace WinUTF8
;
15 // Track memory leaks on Windows to the line that new'd the memory
18 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
21 static char THIS_FILE
[] = __FILE__
;
25 /* TODO: Consider using Template functions to make this neater. */
27 CWinOptions::CWinOptions(const std::string
&Group
, const std::string
&Product
, Dasher::CEventHandler
*pEventHandler
):CSettingsStore(pEventHandler
) {
28 // Windows requires strings as Tstring
29 Tstring TGroup
, TProduct
;
30 UTF8string_to_wstring(Group
, TGroup
);
31 UTF8string_to_wstring(Product
, TProduct
);
33 // Get hold of HKEY_CURRENT_USER\Software
35 if(GetOrCreate(HKEY_CURRENT_USER
, TEXT("Software"), KEY_WRITE
, &SoftwareKey
) != 0) {
36 // Can't open or create key - do something...
37 // Probably flag registry as failed and just return default options
38 exit(1); // give up for now.
41 // Then HKEY_CURRENT_USER\Software\<Group>
43 if(GetOrCreate(SoftwareKey
, TGroup
.c_str(), KEY_WRITE
, &GroupKey
) != 0) {
46 RegCloseKey(SoftwareKey
);
48 // Then HKEY_CURRENT_USER\Software\<Group>\<Product>
49 if(GetOrCreate(GroupKey
, TProduct
.c_str(), KEY_ALL_ACCESS
, &ProductKey
) != 0) {
52 RegCloseKey(GroupKey
);
57 CWinOptions::~CWinOptions() {
58 RegCloseKey(ProductKey
);
61 /* Private functions -- Used to load and save to the Windows Registry
62 --------------------------------------------------------------------------*/
64 bool CWinOptions::LoadSetting(const std::string
&Key
, bool *Value
) {
66 UTF8string_to_wstring(Key
, TKey
);
69 if(!GetlpByte(TKey
, &Data
)) {
74 if((DWORD
) * Data
== 0)
83 /////////////////////////////////////////////////////////////////////////////
85 bool CWinOptions::LoadSetting(const std::string
&Key
, long *Value
) {
87 UTF8string_to_wstring(Key
, TKey
);
90 if(!GetlpByte(TKey
, &Data
)) {
95 // Evil casting to make sure I can retrieve signed longs, even
96 // though windows registry only stores +ve values.
97 *Value
= *((long *)Data
);
102 /////////////////////////////////////////////////////////////////////////////
104 bool CWinOptions::LoadSettingT(const std::string
&Key
, Tstring
*TValue
) {
106 UTF8string_to_wstring(Key
, TKey
);
109 if(!GetlpByte(TKey
, &Data
)) {
114 *TValue
= (TCHAR
*) Data
;
120 /////////////////////////////////////////////////////////////////////////////
122 bool CWinOptions::LoadSetting(const std::string
&Key
, std::string
*Value
) {
125 if(LoadSettingT(Key
, &str
)) {
126 wstring_to_UTF8string(str
, *Value
);
134 /////////////////////////////////////////////////////////////////////////////
136 static TCHAR FormatWindowPlacement
[] = TEXT("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d");
138 /////////////////////////////////////////////////////////////////////////////
141 void CWinOptions::SaveSetting(const std::string
&Key
, const LPWINDOWPLACEMENT pwp
) {
142 DASHER_ASSERT(pwp
!= NULL
);
145 _stprintf(t
, FormatWindowPlacement
, pwp
->flags
, pwp
->showCmd
, pwp
->ptMinPosition
.x
, pwp
->ptMinPosition
.y
, pwp
->ptMaxPosition
.x
, pwp
->ptMaxPosition
.y
, pwp
->rcNormalPosition
.left
, pwp
->rcNormalPosition
.top
, pwp
->rcNormalPosition
.right
, pwp
->rcNormalPosition
.bottom
);
148 SaveSettingT(Key
, ts
);
152 /////////////////////////////////////////////////////////////////////////////
154 bool CWinOptions::LoadSetting(const std::string
&Key
, LPWINDOWPLACEMENT pwp
) {
155 DASHER_ASSERT(pwp
!= NULL
);
159 if(!LoadSettingT(Key
, &str
))
163 int nRead
= _stscanf(str
.c_str(), FormatWindowPlacement
,
164 &wp
.flags
, &wp
.showCmd
,
165 &wp
.ptMinPosition
.x
, &wp
.ptMinPosition
.y
,
166 &wp
.ptMaxPosition
.x
, &wp
.ptMaxPosition
.y
,
167 &wp
.rcNormalPosition
.left
, &wp
.rcNormalPosition
.top
,
168 &wp
.rcNormalPosition
.right
, &wp
.rcNormalPosition
.bottom
);
172 wp
.length
= sizeof(wp
);
180 /////////////////////////////////////////////////////////////////////////////
182 void CWinOptions::SaveSetting(const std::string
&Key
, bool Value
) {
184 SaveSetting(Key
, 1l);
186 SaveSetting(Key
, 0l);
189 /////////////////////////////////////////////////////////////////////////////
191 void CWinOptions::SaveSetting(const std::string
&Key
, long Value
) {
193 UTF8string_to_wstring(Key
, TKey
);
194 // Evil casting. Registry stores DWORD's (unsigned longs)
195 // I'm forcing in signed longs and if I force them out again in the same
196 // way I should get a sensible result.
197 DWORD
*RegValue
= (DWORD
*) & Value
;
198 DWORD MemAllow
= sizeof(DWORD
);
199 LONG ErrVal
= RegSetValueEx(ProductKey
, TKey
.c_str(), 0,
200 REG_DWORD
, (const unsigned char *)RegValue
, MemAllow
);
203 /////////////////////////////////////////////////////////////////////////////
205 void CWinOptions::SaveSettingT(const std::string
&Key
, const Tstring
&TValue
) {
207 UTF8string_to_wstring(Key
, TKey
);
209 DWORD MemAllow
= (TValue
.size() + 1) * sizeof(TCHAR
);
211 //const unsigned char* StrInput = (const unsigned char*) Value.c_str();
212 //LONG ErrVal = RegSetValueEx(ProductKey, TKey.c_str(), 0,
213 // REG_SZ, StrInput, MemAllow);
215 LONG ErrVal
= RegSetValueEx(ProductKey
, TKey
.c_str(), 0,
216 REG_SZ
, (CONST BYTE
*) TValue
.c_str(), MemAllow
);
220 /////////////////////////////////////////////////////////////////////////////
222 void CWinOptions::SaveSetting(const std::string
&Key
, const std::string
&Value
) {
224 // DJW20031107 - i think Values should also be converted to Tstring
226 UTF8string_to_wstring(Value
, TValue
);
228 SaveSettingT(Key
, TValue
);
231 // Used for getting a handle on the Dasher key in the constructor.
232 int CWinOptions::GetOrCreate(HKEY hKey
, LPCTSTR lpSubKey
, REGSAM samDesired
, HKEY
*lpNewKey
) {
233 if(!(RegOpenKeyEx(hKey
, lpSubKey
, 0, samDesired
, lpNewKey
) == ERROR_SUCCESS
)) {
235 if(!(RegCreateKeyEx(hKey
, lpSubKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
, samDesired
, NULL
, lpNewKey
, NULL
) == ERROR_SUCCESS
)) {
243 bool CWinOptions::GetlpByte(const Tstring
&Key
, BYTE
**Data
) const {
245 unsigned long datasize
= sizeof(BYTE
[1]);
248 LONG ErrVal
= RegQueryValueEx(ProductKey
, Key
.c_str(), 0, &Type
, *Data
, &datasize
);
249 while(ErrVal
== ERROR_MORE_DATA
) {
251 *Data
= new BYTE
[datasize
];
252 ErrVal
= RegQueryValueEx(ProductKey
, Key
.c_str(), 0, &Type
, *Data
, &datasize
);
255 // Perhaps I should spend lots of time working out why the registry doesn't work.
256 // when this fails. Would probably just confuse users though. Users with a broken
257 // registry can live with defaults :)
258 if((ErrVal
== ERROR_SUCCESS
) && (*Data
!= 0))