1 //////////////////////////////////////////////////////////////////////////
2 //
3 // pgAdmin III - PostgreSQL Tools
4 // RCS-ID:
5 // Copyright (C) 2002 - 2016, The pgAdmin Development Team
6 // This software is released under the PostgreSQL Licence
7 //
8 // registry.cpp - Windows Registry Reader for both 32 and 64 mode
9 //
10 //////////////////////////////////////////////////////////////////////////
11 #include "pgAdmin3.h"
12
13 #include "utils/registry.h"
14
15 #ifdef __WXMSW__
16
17 #define RESERVED 0
18 #define PGREG_SEPERATOR wxT("\\")
19
20 static struct stdkey
21 {
22 HKEY key;
23 wxString name;
24 }
25 aStdHKeys[] =
26 {
27 {HKEY_CLASSES_ROOT, wxT("HKEY_CLASSES_ROOT")},
28 {HKEY_CURRENT_USER, wxT("HKEY_CURRENT_USER")},
29 {HKEY_LOCAL_MACHINE, wxT("HKEY_LOCAL_MACHINE") },
30 {HKEY_USERS, wxT("HKEY_USERS")},
31 {HKEY_CURRENT_CONFIG, wxT("HKEY_CURRENT_CONFIG")}
32 };
33
34 #define NOS_STD_KEYS (size_t)(sizeof(aStdHKeys)/sizeof(stdkey))
35
pgRegKey(HKEY root,const wxString & subkey,PGREGWOWMODE wowMode,PGREGACCESSMODE accessMode)36 pgRegKey::pgRegKey(HKEY root, const wxString &subkey, PGREGWOWMODE wowMode, PGREGACCESSMODE accessMode)
37 {
38 Init(root, subkey, wowMode, accessMode);
39 }
40
pgRegKey(const pgRegKey & parent,const wxString & key)41 pgRegKey::pgRegKey(const pgRegKey &parent, const wxString &key)
42 {
43 wxString strKey;
44 strKey << parent.m_strName << PGREG_SEPERATOR << key;
45
46 Init(parent.m_hRoot, strKey, PGREG_WOW_DEFAULT, parent.m_accessMode);
47 m_wowMode = parent.m_wowMode;
48 }
49
Init(HKEY root,const wxString & subkey,PGREGWOWMODE wowMode,PGREGACCESSMODE accessMode)50 void pgRegKey::Init(HKEY root, const wxString &subkey, PGREGWOWMODE wowMode, PGREGACCESSMODE accessMode)
51 {
52 m_hRoot = root;
53 m_strName = subkey;
54 m_accessMode = accessMode;
55 m_hKey = NULL;
56 #ifdef __WIN64__
57 m_wowMode = KEY_WOW64_64KEY;
58 #else
59 m_wowMode = KEY_WOW64_32KEY;
60 #endif
61
62 switch (wowMode)
63 {
64 case PGREG_WOW32:
65 #ifdef __WIN64__
66 m_wowMode = KEY_WOW64_32KEY;
67 #endif // __WIN64__
68 break;
69
70 case PGREG_WOW64:
71 #ifndef __WIN64__
72 // we can only access 64 bit registry under 64 bit platforms
73 if (::wxIsPlatform64Bit())
74 m_wowMode = KEY_WOW64_64KEY;
75 #endif // !__WIN64__
76 break;
77 }
78 }
79
OpenRegKey(HKEY root,const wxString & subkey,PGREGACCESSMODE accessmode,PGREGWOWMODE wowMode)80 pgRegKey *pgRegKey::OpenRegKey(HKEY root, const wxString &subkey, PGREGACCESSMODE accessmode, PGREGWOWMODE wowMode)
81 {
82 wxString strKey = subkey;
83
84 !subkey.IsEmpty() && subkey.EndsWith(wxT("\\"), &strKey);
85 pgRegKey *tmpKey = new pgRegKey(root, strKey, wowMode, accessmode);
86
87 HKEY tmpRegKey = 0;
88 long nError = ::RegOpenKeyEx(root, (LPCTSTR)strKey, RESERVED,
89 (accessmode == PGREG_READ ? KEY_READ : KEY_ALL_ACCESS) | tmpKey->m_wowMode,
90 &tmpRegKey);
91
92 if (nError != ERROR_SUCCESS)
93 {
94 delete(tmpKey);
95 tmpKey = NULL;
96 }
97 else
98 tmpKey->m_hKey = tmpRegKey;
99
100 return tmpKey;
101 }
102
Close()103 void pgRegKey::Close()
104 {
105 if (m_hKey)
106 {
107 ::RegCloseKey(m_hKey);
108 m_hKey = NULL;
109 }
110 }
111
~pgRegKey()112 pgRegKey::~pgRegKey()
113 {
114 Close();
115 }
116
KeyExists(HKEY root,const wxString & subkey,PGREGWOWMODE wowMode)117 bool pgRegKey::KeyExists(HKEY root, const wxString &subkey, PGREGWOWMODE wowMode)
118 {
119 if (subkey.IsEmpty())
120 return true;
121
122 #ifdef __WIN64__
123 long keyWowMode = KEY_WOW64_64KEY;
124 #else
125 long keyWowMode = KEY_WOW64_32KEY;
126 #endif
127
128 switch (wowMode)
129 {
130 case PGREG_WOW32:
131 #ifdef __WIN64__
132 keyWowMode = KEY_WOW64_32KEY;
133 #endif // __WIN64__
134 break;
135
136 case PGREG_WOW64:
137 #ifndef __WIN64__
138 // we can only access 64 bit registry under 64 bit platforms
139 if (::wxIsPlatform64Bit())
140 keyWowMode = KEY_WOW64_64KEY;
141 #endif // ! __WIN64__
142 break;
143 }
144
145 HKEY hkeyDummy;
146 if (::RegOpenKeyEx(root, (LPCTSTR)subkey, RESERVED, KEY_READ | keyWowMode, &hkeyDummy) == ERROR_SUCCESS)
147 {
148 ::RegCloseKey(hkeyDummy);
149 return true;
150 }
151 return false;
152 }
153
GetKeyInfo(size_t * pnSubKeys,size_t * pnMaxKeyLen,size_t * pnValues,size_t * pnMaxValueLen) const154 bool pgRegKey::GetKeyInfo(size_t *pnSubKeys, size_t *pnMaxKeyLen, size_t *pnValues, size_t *pnMaxValueLen) const
155 {
156
157 long nError = ::RegQueryInfoKey(m_hKey, NULL, NULL, RESERVED, (LPDWORD)pnSubKeys, (LPDWORD)pnMaxKeyLen, NULL,
158 (LPDWORD)pnValues, (LPDWORD)pnMaxValueLen, NULL, NULL, NULL);
159
160 if (nError != ERROR_SUCCESS)
161 return false;
162 return true;
163 }
164
ToString() const165 wxString pgRegKey::ToString() const
166 {
167 wxString str;
168 size_t index = 0;
169 for (; index < NOS_STD_KEYS; index++)
170 {
171 if (m_hRoot == aStdHKeys[index].key)
172 {
173 str = aStdHKeys[index].name;
174 break;
175 }
176 }
177
178 if (!m_strName.IsEmpty())
179 str << wxT("\\") << m_strName;
180
181 return str;
182 }
183
GetKeyName() const184 wxString pgRegKey::GetKeyName() const
185 {
186 if (!m_strName.IsEmpty())
187 {
188 int index = m_strName.Find(wxT('\\'), true);
189 return m_strName.SubString(index + 1, m_strName.Len());
190 }
191 return wxEmptyString;
192 }
193
QueryValue(const wxString & strkey,LPDWORD pVal) const194 bool pgRegKey::QueryValue(const wxString &strkey, LPDWORD pVal) const
195 {
196 if (strkey.IsEmpty())
197 return false;
198
199 DWORD dwType, dwSize = sizeof(DWORD);
200 unsigned char *pBuf = (unsigned char *)pVal;
201
202 long nError = ::RegQueryValueEx(m_hKey, (LPCTSTR)strkey, RESERVED, &dwType, pBuf, &dwSize);
203
204 if (nError != ERROR_SUCCESS)
205 return false;
206
207 if (dwType != REG_DWORD && dwType != REG_DWORD_BIG_ENDIAN)
208 return false;
209 return true;
210 }
211
QueryValue(const wxString & strVal,wxString & sVal) const212 bool pgRegKey::QueryValue(const wxString &strVal, wxString &sVal) const
213 {
214 DWORD dwType, dwSize;
215
216 long nError = RegQueryValueEx(m_hKey, (LPCTSTR)strVal, RESERVED, &dwType, NULL, &dwSize);
217
218 if (nError == ERROR_SUCCESS)
219 {
220 sVal = wxT("");
221 if (dwSize == 0)
222 return true;
223
224 wxChar *pBuf = (wxChar *)calloc(dwSize, sizeof(wxChar));
225 nError = ::RegQueryValueEx(m_hKey, (LPCTSTR)strVal, RESERVED, &dwType, (LPBYTE)pBuf, &dwSize);
226
227 DWORD index = 0;
228 if (dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ)
229 {
230 wxChar *actualValueStr = (wxChar *)calloc(dwSize, sizeof(wxChar));
231 memcpy(actualValueStr, pBuf, dwSize * sizeof(wxChar));
232
233 wxChar *curr_line;
234 sVal = wxT("");
235 do
236 {
237 DWORD dwExpSize = ::ExpandEnvironmentStrings((actualValueStr + index), NULL, 0);
238 curr_line = (wxChar *)calloc(dwExpSize, sizeof(wxChar));
239
240 ::ExpandEnvironmentStrings(actualValueStr + index, curr_line, dwExpSize);
241
242 if (index != 0)
243 sVal << wxT("\n\r") << curr_line;
244 else
245 sVal << curr_line;
246 index += (DWORD)wxStrlen(actualValueStr + index) + 1;
247 free(curr_line);
248 }
249 while (actualValueStr[index] && dwType == REG_MULTI_SZ);
250
251 free(actualValueStr);
252 }
253 else
254 sVal = pBuf;
255
256 free(pBuf);
257 return true;
258 }
259 return false;
260 }
261
QueryValue(const wxString & strVal,LPBYTE & pVal,DWORD & len) const262 bool pgRegKey::QueryValue(const wxString &strVal, LPBYTE &pVal, DWORD &len) const
263 {
264 DWORD dwType;
265 if(RegQueryValueEx(m_hKey, (LPCTSTR)strVal,
266 RESERVED, &dwType, pVal, &len) == ERROR_SUCCESS)
267 return true;
268 len = 0;
269 return false;
270 }
271
GetFirstValue(wxString & strkey,long & lIndex) const272 bool pgRegKey::GetFirstValue(wxString &strkey, long &lIndex) const
273 {
274 lIndex = 0;
275 return GetNextValue(strkey, lIndex);
276 }
277
GetNextValue(wxString & strval,long & lIndex) const278 bool pgRegKey::GetNextValue(wxString &strval, long &lIndex) const
279 {
280 if (lIndex < 0)
281 return false;
282
283 TCHAR szVal[1024];
284 DWORD dwValLen = 1024;
285
286 long nError = RegEnumValue(m_hKey, lIndex, szVal, &dwValLen, RESERVED, NULL, NULL, NULL);
287
288 if (nError != ERROR_SUCCESS)
289 {
290 if (nError == ERROR_NO_MORE_ITEMS)
291 {
292 nError = ERROR_SUCCESS;
293 lIndex = -1;
294 }
295 return false;
296 }
297 strval = szVal;
298 lIndex++;
299 return true;
300 }
301
HasValue(const wxString & strval)302 bool pgRegKey::HasValue(const wxString &strval)
303 {
304 long nRetVal = ::RegQueryValueEx(m_hKey, (LPCTSTR)strval, RESERVED, NULL, NULL, NULL);
305
306 return nRetVal == ERROR_SUCCESS;
307 }
308
GetFirstKey(pgRegKey * & pkey,long & lIndex) const309 bool pgRegKey::GetFirstKey(pgRegKey *&pkey, long &lIndex) const
310 {
311 lIndex = 0;
312 return GetNextKey(pkey, lIndex);
313 }
314
GetNextKey(pgRegKey * & pKey,long & lIndex) const315 bool pgRegKey::GetNextKey(pgRegKey *&pKey, long &lIndex) const
316 {
317 pKey = NULL;
318
319 if (lIndex < 0)
320 return false;
321
322 TCHAR szKey[1024];
323 DWORD dwKeyLen = 1023;
324 long nError = ::RegEnumKeyEx(m_hKey, lIndex, szKey, &dwKeyLen, NULL, NULL, NULL, NULL);
325
326 if (nError != ERROR_SUCCESS)
327 {
328 lIndex = -1;
329 return false;
330 }
331 lIndex++;
332 wxString strSubKey = m_strName;
333 strSubKey << wxT("\\") << szKey;
334
335 pgRegKey *tmpKey = new pgRegKey(m_hRoot, (LPCTSTR)strSubKey, PGREG_WOW_DEFAULT, m_accessMode);
336 tmpKey->m_wowMode = m_wowMode;
337
338 HKEY tmpRegKey = 0;
339 nError
340 = ::RegOpenKeyEx(m_hRoot, (LPCTSTR)strSubKey, RESERVED, (m_accessMode == PGREG_READ ? KEY_READ : KEY_ALL_ACCESS) | m_wowMode, &tmpRegKey);
341
342 if (nError != ERROR_SUCCESS)
343 {
344 delete(tmpKey);
345 tmpKey = NULL;
346 pKey = NULL;
347
348 return false;
349 }
350 else
351 tmpKey->m_hKey = tmpRegKey;
352
353 pKey = tmpKey;
354
355 return true;
356 }
357
HasKey(const wxString & strKey) const358 bool pgRegKey::HasKey(const wxString &strKey) const
359 {
360 wxString strSubKey = m_strName;
361 strSubKey << wxT("\\") << strKey;
362
363 return pgRegKey::KeyExists(m_hRoot, strSubKey, m_wowMode == KEY_WOW64_64KEY ? PGREG_WOW64 : PGREG_WOW32) ;
364 }
365
GetValueType(const wxString & key) const366 DWORD pgRegKey::GetValueType(const wxString &key) const
367 {
368 DWORD dwType;
369 long nError = RegQueryValueEx((HKEY) m_hKey, (LPCTSTR)key, RESERVED,
370 &dwType, NULL, NULL);
371
372 if (nError != ERROR_SUCCESS)
373 return REG_NONE;
374 return dwType;
375 }
376
377 #endif // __WXMSW__
378