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