Index: include/utils/module.mk =================================================================== --- include/utils/module.mk (revision 8382) +++ include/utils/module.mk (working copy) @@ -18,6 +18,7 @@ $(srcdir)/include/utils/pgfeatures.h \ $(srcdir)/include/utils/pgDefs.h \ $(srcdir)/include/utils/pgconfig.h \ + $(srcdir)/include/utils/registry.h \ $(srcdir)/include/utils/sysLogger.h \ $(srcdir)/include/utils/sysProcess.h \ $(srcdir)/include/utils/sysSettings.h \ Index: include/utils/registry.h =================================================================== --- include/utils/registry.h (revision 0) +++ include/utils/registry.h (revision 0) @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// RCS-ID: +// Copyright (C) 2002 - 2010, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +// registry.h - Windows Registry Reader for both 32 and 64 mode +// +////////////////////////////////////////////////////////////////////////// + +#ifndef __PGREG_WINREGISTRY_H__ +#define __PGREG_WINREGISTRY_H__ + +#ifdef __WXMSW__ + +#include + +class pgRegKey +{ + +public: + enum PGREGWOWMODE + { + /* + * Read/Write 32 bit registry for 32 bit applications, + * Read/Write 64 bit registry for 64 bit applications + */ + PGREG_WOW_DEFAULT, + /* Read/Write 32 bit registry */ + PGREG_WOW32, + /* Read/Write 64 bit registry on 64 bit windows */ + PGREG_WOW64 + }; + + enum PGREGACCESSMODE + { + /* READ ONLY */ + PGREG_READ, + /* READ & Write */ + PGREG_WRITE + }; + +public: + static pgRegKey* OpenRegKey(HKEY root, const wxString& subkey, PGREGACCESSMODE accessmode = PGREG_READ, PGREGWOWMODE wowMode = PGREG_WOW_DEFAULT); + ~pgRegKey(); + + static bool KeyExists(HKEY root, const wxString& subKey, PGREGWOWMODE wowMode = PGREG_WOW_DEFAULT); + + bool GetKeyInfo(size_t *pnSubKeys, // number of subkeys + size_t *pnMaxKeyLen, // max len of subkey name + size_t *pnValues, // number of values + size_t *pnMaxValueLen) const; + + bool QueryValue(const wxString& strVal, LPDWORD pVal) const; + bool QueryValue(const wxString& strVal, wxString& pVal) const; + bool QueryValue(const wxString& strVal, LPBYTE& pVal, DWORD& len) const; + + bool GetFirstValue(wxString& strVal, long &lindex) const; + bool GetNextValue(wxString& strVal, long &lindex) const; + bool HasValue(const wxString& strVal); + + bool GetFirstKey(pgRegKey*& pkey, long &lindex) const; + bool GetNextKey(pgRegKey*& pkey, long &lindex) const; + bool HasKey(const wxString& strKey) const; + + DWORD GetValueType(const wxString& strVal) const; + + wxString ToString() const; + wxString GetKeyName() const; + +private: + pgRegKey(HKEY root, const wxString& subkey, PGREGWOWMODE wowMode, PGREGACCESSMODE accessMode); + pgRegKey(const pgRegKey& keyParent, const wxString& strKey); + + void Init(HKEY root, const wxString& subkey, PGREGWOWMODE wowMode, PGREGACCESSMODE accessMode); + void Close(); + + HKEY m_hRoot; + HKEY m_hKey; + wxString m_strName; + DWORD m_wowMode; + PGREGACCESSMODE m_accessMode; + +}; + +#endif // __WXMSW__ +#endif // __PGREG_WINREGISTRY_H__ + Index: pgAdmin3.vcproj =================================================================== --- pgAdmin3.vcproj (revision 8382) +++ pgAdmin3.vcproj (working copy) @@ -11,6 +11,9 @@ + @@ -226,6 +229,217 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -255,6 +469,24 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3793,6 +4175,22 @@ UsePrecompiledHeader="0" /> + + + + + + + + @@ -3865,6 +4267,22 @@ UsePrecompiledHeader="0" /> + + + + + + + + + + + + + + + + + + = BETA3 // of the Win32 PostgreSQL installer. wxLogInfo(wxT("Loading servers registered on the local machine")); - wxRegKey *pgKey = new wxRegKey(wxT("HKEY_LOCAL_MACHINE\\Software\\PostgreSQL\\Services")); - if (pgKey->Exists()) + wxString strPgArch = ::wxIsPlatform64Bit() == true ? wxT("(x86)") : wxEmptyString; + pgRegKey *pgKey = pgRegKey::OpenRegKey(HKEY_LOCAL_MACHINE, wxT("Software\\PostgreSQL\\Services"), pgRegKey::PGREG_READ, pgRegKey::PGREG_WOW32); + + if (pgKey == NULL) { + strPgArch = wxT("(x64)"); + pgKey = pgRegKey::OpenRegKey(HKEY_LOCAL_MACHINE, wxT("Software\\PostgreSQL\\Services"), pgRegKey::PGREG_READ, pgRegKey::PGREG_WOW64); + } + while (pgKey != NULL) + { + pgRegKey *svcKey = NULL; wxString svcName, temp; long cookie = 0; - long *tmpport = 0; + DWORD tmpport = 0; bool flag = false; - flag = pgKey->GetFirstKey(svcName, cookie); + flag = pgKey->GetFirstKey(svcKey, cookie); while (flag != false) { + svcName = svcKey->GetKeyName(); // On Windows, the discovery ID is always the service name. // Only load the server if we didn't load it with all the others. if (discoveredServers.Index(svcName, false) < 0) { - key.Printf(wxT("HKEY_LOCAL_MACHINE\\Software\\PostgreSQL\\Services\\%s"), svcName); - wxRegKey *svcKey = new wxRegKey(key); - servername = wxT("localhost"); database = wxEmptyString; svcKey->QueryValue(wxT("Display Name"), description); svcKey->QueryValue(wxT("Database Superuser"), username); - svcKey->QueryValue(wxT("Port"), &port); + svcKey->QueryValue(wxT("Port"), &tmpport); // Add the Server node - server = new pgServer(servername, description, database, username, port, false, 0); + server = new pgServer(servername, description + strPgArch, database, username, (long)tmpport, false, 0); server->iSetDiscoveryID(svcName); server->iSetDiscovered(true); server->iSetServiceID(svcName); server->iSetGroup(group); - found = false; + found = false; - if (browser->ItemHasChildren(browser->GetRootItem())) - { - groupitem = browser->GetFirstChild(browser->GetRootItem(), groupcookie); - while (!found && groupitem) - { - if (browser->GetItemText(groupitem).StartsWith(group)) - found = true; - else - groupitem = browser->GetNextChild(browser->GetRootItem(), groupcookie); - } - } + if (browser->ItemHasChildren(browser->GetRootItem())) + { + groupitem = browser->GetFirstChild(browser->GetRootItem(), groupcookie); + while (!found && groupitem) + { + if (browser->GetItemText(groupitem).StartsWith(group)) + found = true; + else + groupitem = browser->GetNextChild(browser->GetRootItem(), groupcookie); + } + } - if (!found) - { - groupitem = browser->AppendItem(browser->GetRootItem(), group, obj->GetIconId()); - browser->SortChildren(browser->GetRootItem()); - } + if (!found) + { + groupitem = browser->AppendItem(browser->GetRootItem(), group, obj->GetIconId()); + browser->SortChildren(browser->GetRootItem()); + } - browser->AppendItem(groupitem, server->GetFullName(), server->GetIconId(), -1, server); + browser->AppendItem(groupitem, server->GetFullName(), server->GetIconId(), -1, server); browser->SortChildren(groupitem); } + // Release the current registry key + delete svcKey; + // Get the next one... - flag = pgKey->GetNextKey(svcName, cookie); + flag = pgKey->GetNextKey(svcKey, cookie); } + + /* Release current registry key */ + delete pgKey; + pgKey = NULL; + /* + * Value of strPgArch is '(x86)', that means this is a 64 bit machine + * We need to read now 64 bit registry. + */ + if (strPgArch.IsSameAs(wxT("(x86)"))) + { + strPgArch = wxT("(x64)"); + pgKey = pgRegKey::OpenRegKey(HKEY_LOCAL_MACHINE, wxT("Software\\PostgreSQL\\Services"), pgRegKey::PGREG_READ, pgRegKey::PGREG_WOW64); + } } #endif // WIN32 Index: utils/module.mk =================================================================== --- utils/module.mk (revision 8382) +++ utils/module.mk (working copy) @@ -16,6 +16,7 @@ $(srcdir)/utils/md5.cpp \ $(srcdir)/utils/misc.cpp \ $(srcdir)/utils/pgconfig.cpp \ + $(srcdir)/utils/registry.cpp \ $(srcdir)/utils/sysLogger.cpp \ $(srcdir)/utils/sysProcess.cpp \ $(srcdir)/utils/sysSettings.cpp \ Index: utils/registry.cpp =================================================================== --- utils/registry.cpp (revision 0) +++ utils/registry.cpp (revision 0) @@ -0,0 +1,372 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin III - PostgreSQL Tools +// RCS-ID: +// Copyright (C) 2002 - 2010, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +// registry.cpp - Windows Registry Reader for both 32 and 64 mode +// +////////////////////////////////////////////////////////////////////////// +#include "pgAdmin3.h" + +#include "utils/registry.h" + +#ifdef __WXMSW__ + +#define RESERVED 0 +#define PGREG_SEPERATOR wxT("\\") + +static struct stdkey { + HKEY key; + wxString name; +} +aStdHKeys[] = { + {HKEY_CLASSES_ROOT, wxT("HKEY_CLASSES_ROOT")}, + {HKEY_CURRENT_USER, wxT("HKEY_CURRENT_USER")}, + {HKEY_LOCAL_MACHINE, wxT("HKEY_LOCAL_MACHINE") }, + {HKEY_USERS, wxT("HKEY_USERS")}, + {HKEY_CURRENT_CONFIG, wxT("HKEY_CURRENT_CONFIG")} +}; + +#define NOS_STD_KEYS (size_t)(sizeof(aStdHKeys)/sizeof(stdkey)) + +pgRegKey::pgRegKey(HKEY root, const wxString& subkey, PGREGWOWMODE wowMode, PGREGACCESSMODE accessMode) +{ + Init(root, subkey, wowMode, accessMode); +} + +pgRegKey::pgRegKey(const pgRegKey& parent, const wxString& key) +{ + wxString strKey; + strKey << parent.m_strName << PGREG_SEPERATOR << key; + + Init(parent.m_hRoot, strKey, PGREG_WOW_DEFAULT, parent.m_accessMode); + m_wowMode = parent.m_wowMode; +} + +void pgRegKey::Init(HKEY root, const wxString& subkey, PGREGWOWMODE wowMode, PGREGACCESSMODE accessMode) +{ + m_hRoot = root; + m_strName = subkey; + m_accessMode = accessMode; + m_hKey = NULL; +#ifdef __WIN64__ + m_wowMode = KEY_WOW64_64KEY; +#else + m_wowMode = KEY_WOW64_32KEY; +#endif + + switch (wowMode) + { + case PGREG_WOW32: +#ifdef __WIN64__ + m_wowMode = KEY_WOW64_32KEY; +#endif // __WIN64__ + break; + + case PGREG_WOW64: +#ifndef __WIN64__ + // we can only access 64 bit registry under 64 bit platforms + if (::wxIsPlatform64Bit()) + m_wowMode = KEY_WOW64_64KEY; +#endif // !__WIN64__ + break; + } +} + +pgRegKey *pgRegKey::OpenRegKey(HKEY root, const wxString& subkey, PGREGACCESSMODE accessmode, PGREGWOWMODE wowMode) +{ + wxString strKey = subkey; + + !subkey.IsEmpty() && subkey.EndsWith(wxT("\\"), &strKey); + pgRegKey *tmpKey = new pgRegKey(root, strKey, wowMode, accessmode); + + HKEY tmpRegKey = 0; + long nError = ::RegOpenKeyEx(root, (LPCTSTR)strKey, RESERVED, + (accessmode == PGREG_READ ? KEY_READ : KEY_ALL_ACCESS) | tmpKey->m_wowMode, + &tmpRegKey); + + if (nError != ERROR_SUCCESS) + { + delete(tmpKey); + tmpKey = NULL; + } + else + tmpKey->m_hKey = tmpRegKey; + + return tmpKey; +} + +void pgRegKey::Close() +{ + if (m_hKey) + { + ::RegCloseKey(m_hKey); + m_hKey = NULL; + } +} + +pgRegKey::~pgRegKey() +{ + Close(); +} + +bool pgRegKey::KeyExists(HKEY root, const wxString& subkey, PGREGWOWMODE wowMode) +{ + if (subkey.IsEmpty()) + return true; + +#ifdef __WIN64__ + long keyWowMode = KEY_WOW64_64KEY; +#else + long keyWowMode = KEY_WOW64_32KEY; +#endif + + switch (wowMode) + { + case PGREG_WOW32: +#ifdef __WIN64__ + keyWowMode = KEY_WOW64_32KEY; +#endif // __WIN64__ + break; + + case PGREG_WOW64: +#ifndef __WIN64__ + // we can only access 64 bit registry under 64 bit platforms + if (::wxIsPlatform64Bit()) + keyWowMode = KEY_WOW64_64KEY; +#endif // ! __WIN64__ + break; + } + + HKEY hkeyDummy; + if (::RegOpenKeyEx(root, (LPCTSTR)subkey, RESERVED, KEY_READ | keyWowMode, &hkeyDummy) == ERROR_SUCCESS) + { + ::RegCloseKey(hkeyDummy); + return true; + } + return false; +} + +bool pgRegKey::GetKeyInfo(size_t *pnSubKeys, size_t *pnMaxKeyLen, size_t *pnValues, size_t *pnMaxValueLen) const +{ + + long nError = ::RegQueryInfoKey(m_hKey, NULL, NULL, RESERVED, (LPDWORD)pnSubKeys, (LPDWORD)pnMaxKeyLen, NULL, + (LPDWORD)pnValues, (LPDWORD)pnMaxValueLen, NULL, NULL, NULL); + + if (nError != ERROR_SUCCESS) + return false; + return true; +} + +wxString pgRegKey::ToString() const +{ + wxString str; + size_t index = 0; + for (; index < NOS_STD_KEYS; index++) + { + if (m_hRoot == aStdHKeys[index].key) + { + str = aStdHKeys[index].name; + break; + } + } + + if (!m_strName.IsEmpty()) + str << wxT("\\") << m_strName; + + return str; +} + +wxString pgRegKey::GetKeyName() const +{ + if (!m_strName.IsEmpty()) + { + int index = m_strName.Find(wxT('\\'), true); + return m_strName.SubString(index + 1, m_strName.Len()); + } + return wxEmptyString; +} + +bool pgRegKey::QueryValue(const wxString& strkey, LPDWORD pVal) const +{ + if (strkey.IsEmpty()) + return false; + + DWORD dwType, dwSize = sizeof(DWORD); + unsigned char * pBuf = (unsigned char *)pVal; + + long nError = ::RegQueryValueEx(m_hKey, (LPCTSTR)strkey, RESERVED, &dwType, pBuf, &dwSize); + + if (nError != ERROR_SUCCESS) + return false; + + if (dwType != REG_DWORD && dwType != REG_DWORD_BIG_ENDIAN) + return false; + return true; +} + +bool pgRegKey::QueryValue(const wxString& strVal, wxString& sVal) const +{ + DWORD dwType, dwSize; + + long nError = RegQueryValueEx(m_hKey, (LPCTSTR)strVal, RESERVED, &dwType, NULL, &dwSize); + + if (nError == ERROR_SUCCESS) + { + sVal = wxT(""); + if (dwSize == 0) + return true; + + wxChar *pBuf = (wxChar *)calloc(dwSize, sizeof(wxChar)); + nError = ::RegQueryValueEx(m_hKey, (LPCTSTR)strVal, RESERVED, &dwType, (LPBYTE)pBuf, &dwSize); + + DWORD index = 0; + if (dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ) + { + wxChar *actualValueStr = (wxChar *)calloc(dwSize, sizeof(wxChar)); + memcpy(actualValueStr, pBuf, dwSize * sizeof(wxChar)); + + wxChar *curr_line; + sVal = wxT(""); + do + { + DWORD dwExpSize = ::ExpandEnvironmentStrings((actualValueStr + index), NULL, 0); + curr_line = (wxChar *)calloc(dwExpSize, sizeof(wxChar)); + + ::ExpandEnvironmentStrings(actualValueStr + index, curr_line, dwExpSize); + + if (index != 0) + sVal << wxT("\n\r") << curr_line; + else + sVal << curr_line; + index += (DWORD)wxStrlen(actualValueStr + index) + 1; + free(curr_line); + } while (actualValueStr[index] && dwType == REG_MULTI_SZ); + + free(actualValueStr); + } + else + sVal = pBuf; + return true; + } + return false; +} + +bool pgRegKey::QueryValue(const wxString& strVal, LPBYTE& pVal, DWORD& len) const +{ + DWORD dwType; + if(RegQueryValueEx(m_hKey, (LPCTSTR)strVal, + RESERVED, &dwType, pVal, &len) == ERROR_SUCCESS) + return true; + len = 0; + return false; +} + +bool pgRegKey::GetFirstValue(wxString& strkey, long &lIndex) const +{ + lIndex = 0; + return GetNextValue(strkey, lIndex); +} + +bool pgRegKey::GetNextValue(wxString& strval, long &lIndex) const +{ + if (lIndex < 0) + return false; + + TCHAR szVal[1024]; + DWORD dwValLen = 1024; + + long nError = RegEnumValue(m_hKey, lIndex, szVal, &dwValLen, RESERVED, NULL, NULL, NULL); + + if (nError != ERROR_SUCCESS) + { + if (nError == ERROR_NO_MORE_ITEMS) + { + nError = ERROR_SUCCESS; + lIndex = -1; + } + return false; + } + strval = szVal; + lIndex++; + return true; +} + +bool pgRegKey::HasValue(const wxString& strval) +{ + long nRetVal = ::RegQueryValueEx(m_hKey, (LPCTSTR)strval, RESERVED, NULL, NULL, NULL); + + return nRetVal == ERROR_SUCCESS; +} + +bool pgRegKey::GetFirstKey(pgRegKey*& pkey, long &lIndex) const +{ + lIndex = 0; + return GetNextKey(pkey, lIndex); +} + +bool pgRegKey::GetNextKey(pgRegKey*& pKey, long &lIndex) const +{ + pKey = NULL; + + if (lIndex < 0) + return false; + + TCHAR szKey[1024]; + DWORD dwKeyLen = 1023; + long nError = ::RegEnumKeyEx(m_hKey, lIndex, szKey, &dwKeyLen, NULL, NULL, NULL, NULL); + + if (nError != ERROR_SUCCESS) + { + lIndex = -1; + return false; + } + lIndex++; + wxString strSubKey = m_strName; + strSubKey << wxT("\\") << szKey; + + pgRegKey *tmpKey = new pgRegKey(m_hRoot, (LPCTSTR)strSubKey, PGREG_WOW_DEFAULT, m_accessMode); + tmpKey->m_wowMode = m_wowMode; + + HKEY tmpRegKey = 0; + nError + = ::RegOpenKeyEx(m_hRoot, (LPCTSTR)strSubKey, RESERVED, (m_accessMode == PGREG_READ ? KEY_READ : KEY_ALL_ACCESS) | m_wowMode, &tmpRegKey); + + if (nError != ERROR_SUCCESS) + { + delete(tmpKey); + tmpKey = NULL; + pKey = NULL; + + return false; + } + else + tmpKey->m_hKey = tmpRegKey; + + pKey = tmpKey; + + return true; +} + +bool pgRegKey::HasKey(const wxString& strKey) const +{ + wxString strSubKey = m_strName; + strSubKey << wxT("\\") << strKey; + + return pgRegKey::KeyExists(m_hRoot, strSubKey, m_wowMode == KEY_WOW64_64KEY ? PGREG_WOW64 : PGREG_WOW32) ; +} + +DWORD pgRegKey::GetValueType(const wxString& key) const +{ + DWORD dwType; + long nError = RegQueryValueEx((HKEY) m_hKey, (LPCTSTR)key, RESERVED, + &dwType, NULL, NULL); + + if (nError != ERROR_SUCCESS) + return REG_NONE; + return dwType; +} + +#endif // __WXMSW__