mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-10 14:57:52 +00:00
Merge pull request #2378 from glassez/python_reg
Improve Windows Registry searching for Python.
This commit is contained in:
commit
aca42b8ccc
@ -1339,145 +1339,150 @@ void Preferences::disableRecursiveDownload(bool disable) {
|
|||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
namespace {
|
namespace {
|
||||||
enum REG_SEARCH_TYPE {USER, SYSTEM_32BIT, SYSTEM_64BIT};
|
enum REG_SEARCH_TYPE
|
||||||
|
{
|
||||||
|
USER,
|
||||||
|
SYSTEM_32BIT,
|
||||||
|
SYSTEM_64BIT
|
||||||
|
};
|
||||||
|
|
||||||
QStringList getRegSubkeys(const HKEY &handle) {
|
QStringList getRegSubkeys(HKEY handle)
|
||||||
QStringList keys;
|
{
|
||||||
DWORD subkeys_count = 0;
|
QStringList keys;
|
||||||
DWORD max_subkey_len = 0;
|
|
||||||
long res = ::RegQueryInfoKey(handle, NULL, NULL, NULL, &subkeys_count, &max_subkey_len, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
if (res == ERROR_SUCCESS) {
|
|
||||||
max_subkey_len++; //For null character
|
|
||||||
LPTSTR key_name = new TCHAR[max_subkey_len];
|
|
||||||
|
|
||||||
for (uint i=0; i<subkeys_count; i++) {
|
DWORD cSubKeys = 0;
|
||||||
res = ::RegEnumKeyEx(handle, 0, key_name, &max_subkey_len, NULL, NULL, NULL, NULL);
|
DWORD cMaxSubKeyLen = 0;
|
||||||
if (res == ERROR_SUCCESS)
|
LONG res = ::RegQueryInfoKeyW(handle, NULL, NULL, NULL, &cSubKeys, &cMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
keys.push_back(QString::fromWCharArray(key_name));
|
|
||||||
}
|
|
||||||
delete[] key_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys;
|
if (res == ERROR_SUCCESS) {
|
||||||
}
|
cMaxSubKeyLen++; // For null character
|
||||||
|
LPWSTR lpName = new WCHAR[cMaxSubKeyLen];
|
||||||
|
DWORD cName;
|
||||||
|
|
||||||
QString getRegValue(const HKEY &handle, const QString &name = QString()) {
|
for (DWORD i = 0; i < cSubKeys; ++i) {
|
||||||
QString end_result;
|
cName = cMaxSubKeyLen;
|
||||||
DWORD type = 0;
|
res = ::RegEnumKeyExW(handle, 0, lpName, &cName, NULL, NULL, NULL, NULL);
|
||||||
DWORD size = 0;
|
if (res == ERROR_SUCCESS)
|
||||||
DWORD array_size = 0;
|
keys.push_back(QString::fromWCharArray(lpName));
|
||||||
|
|
||||||
LPTSTR value_name = NULL;
|
|
||||||
if (!name.isEmpty()) {
|
|
||||||
value_name = new TCHAR[name.size()+1];
|
|
||||||
name.toWCharArray(value_name);
|
|
||||||
value_name[name.size()] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Discover the size of the value
|
|
||||||
::RegQueryValueEx(handle, value_name, NULL, &type, NULL, &size);
|
|
||||||
array_size = size / sizeof(TCHAR);
|
|
||||||
if (size % sizeof(TCHAR))
|
|
||||||
array_size++;
|
|
||||||
array_size++; //For null character
|
|
||||||
LPTSTR value = new TCHAR[array_size];
|
|
||||||
|
|
||||||
long res = ::RegQueryValueEx(handle, value_name, NULL, &type, (LPBYTE)value, &size);
|
|
||||||
if (res == ERROR_SUCCESS) {
|
|
||||||
value[array_size] = '\0';
|
|
||||||
end_result = QString::fromWCharArray(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value_name)
|
|
||||||
delete[] value_name;
|
|
||||||
if (value)
|
|
||||||
delete[] value;
|
|
||||||
|
|
||||||
return end_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString pythonSearchReg(const REG_SEARCH_TYPE type) {
|
|
||||||
HKEY key_handle1;
|
|
||||||
long res = 0;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case USER:
|
|
||||||
res = ::RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Python\\PythonCore"), 0, KEY_READ, &key_handle1);
|
|
||||||
break;
|
|
||||||
case SYSTEM_32BIT:
|
|
||||||
res = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Python\\PythonCore"), 0, KEY_READ|KEY_WOW64_32KEY, &key_handle1);
|
|
||||||
break;
|
|
||||||
case SYSTEM_64BIT:
|
|
||||||
res = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Python\\PythonCore"), 0, KEY_READ|KEY_WOW64_64KEY, &key_handle1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res == ERROR_SUCCESS) {
|
|
||||||
QStringList versions = getRegSubkeys(key_handle1);
|
|
||||||
qDebug("Python versions nb: %d", versions.size());
|
|
||||||
versions.sort();
|
|
||||||
|
|
||||||
while(!versions.empty()) {
|
|
||||||
const QString version = versions.takeLast()+"\\InstallPath";
|
|
||||||
HKEY key_handle2;
|
|
||||||
LPTSTR subkey = new TCHAR[version.size()+1];
|
|
||||||
version.toWCharArray(subkey);
|
|
||||||
subkey[version.size()] = '\0';
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case USER:
|
|
||||||
res = ::RegOpenKeyEx(key_handle1, subkey, 0, KEY_READ, &key_handle2);
|
|
||||||
break;
|
|
||||||
case SYSTEM_32BIT:
|
|
||||||
res = ::RegOpenKeyEx(key_handle1, subkey, 0, KEY_READ|KEY_WOW64_32KEY, &key_handle2);
|
|
||||||
break;
|
|
||||||
case SYSTEM_64BIT:
|
|
||||||
res = ::RegOpenKeyEx(key_handle1, subkey, 0, KEY_READ|KEY_WOW64_64KEY, &key_handle2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] subkey;
|
|
||||||
if (res == ERROR_SUCCESS) {
|
|
||||||
qDebug("Detected possible Python v%s location", qPrintable(version));
|
|
||||||
QString path = getRegValue(key_handle2);
|
|
||||||
::RegCloseKey(key_handle2);
|
|
||||||
if (!path.isEmpty() && QDir(path).exists("python.exe")) {
|
|
||||||
qDebug("Found python.exe at %s", qPrintable(path));
|
|
||||||
::RegCloseKey(key_handle1);
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
delete[] lpName;
|
||||||
::RegCloseKey(key_handle2);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
::RegCloseKey(key_handle1);
|
return keys;
|
||||||
return QString::null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString getRegValue(HKEY handle, const QString &name = QString())
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
DWORD type = 0;
|
||||||
|
DWORD cbData = 0;
|
||||||
|
LPWSTR lpValueName = NULL;
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
lpValueName = new WCHAR[name.size() + 1];
|
||||||
|
name.toWCharArray(lpValueName);
|
||||||
|
lpValueName[name.size()] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discover the size of the value
|
||||||
|
::RegQueryValueExW(handle, lpValueName, NULL, &type, NULL, &cbData);
|
||||||
|
DWORD cBuffer = (cbData / sizeof(WCHAR)) + 1;
|
||||||
|
LPWSTR lpData = new WCHAR[cBuffer];
|
||||||
|
LONG res = ::RegQueryValueExW(handle, lpValueName, NULL, &type, (LPBYTE)lpData, &cbData);
|
||||||
|
if (lpValueName)
|
||||||
|
delete[] lpValueName;
|
||||||
|
|
||||||
|
if (res == ERROR_SUCCESS) {
|
||||||
|
lpData[cBuffer - 1] = 0;
|
||||||
|
result = QString::fromWCharArray(lpData);
|
||||||
|
}
|
||||||
|
delete[] lpData;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Preferences::getPythonPath() {
|
QString pythonSearchReg(const REG_SEARCH_TYPE type)
|
||||||
QString path = pythonSearchReg(USER);
|
{
|
||||||
if (path.isEmpty())
|
HKEY hkRoot;
|
||||||
path = pythonSearchReg(SYSTEM_32BIT);
|
if (type == USER)
|
||||||
else return path;
|
hkRoot = HKEY_CURRENT_USER;
|
||||||
|
else
|
||||||
|
hkRoot = HKEY_LOCAL_MACHINE;
|
||||||
|
|
||||||
if (path.isEmpty())
|
REGSAM samDesired = KEY_READ;
|
||||||
path = pythonSearchReg(SYSTEM_64BIT);
|
if (type == SYSTEM_32BIT)
|
||||||
else return path;
|
samDesired |= KEY_WOW64_32KEY;
|
||||||
|
else if (type == SYSTEM_64BIT)
|
||||||
|
samDesired |= KEY_WOW64_64KEY;
|
||||||
|
|
||||||
|
QString path;
|
||||||
|
LONG res = 0;
|
||||||
|
HKEY hkPythonCore;
|
||||||
|
res = ::RegOpenKeyExW(hkRoot, L"SOFTWARE\\Python\\PythonCore", 0, samDesired, &hkPythonCore);
|
||||||
|
|
||||||
|
if (res == ERROR_SUCCESS) {
|
||||||
|
QStringList versions = getRegSubkeys(hkPythonCore);
|
||||||
|
qDebug("Python versions nb: %d", versions.size());
|
||||||
|
versions.sort();
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
while(!found && !versions.empty()) {
|
||||||
|
const QString version = versions.takeLast() + "\\InstallPath";
|
||||||
|
LPWSTR lpSubkey = new WCHAR[version.size() + 1];
|
||||||
|
version.toWCharArray(lpSubkey);
|
||||||
|
lpSubkey[version.size()] = 0;
|
||||||
|
|
||||||
|
HKEY hkInstallPath;
|
||||||
|
res = ::RegOpenKeyExW(hkPythonCore, lpSubkey, 0, samDesired, &hkInstallPath);
|
||||||
|
delete[] lpSubkey;
|
||||||
|
|
||||||
|
if (res == ERROR_SUCCESS) {
|
||||||
|
qDebug("Detected possible Python v%s location", qPrintable(version));
|
||||||
|
path = getRegValue(hkInstallPath);
|
||||||
|
::RegCloseKey(hkInstallPath);
|
||||||
|
|
||||||
|
if (!path.isEmpty() && QDir(path).exists("python.exe")) {
|
||||||
|
qDebug("Found python.exe at %s", qPrintable(path));
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
path = QString();
|
||||||
|
|
||||||
|
::RegCloseKey(hkPythonCore);
|
||||||
|
}
|
||||||
|
|
||||||
if (!path.isEmpty())
|
|
||||||
return path;
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
// Fallback: Detect python from default locations
|
}
|
||||||
QStringList supported_versions;
|
|
||||||
supported_versions << "32" << "31" << "30" << "27" << "26" << "25";
|
QString Preferences::getPythonPath()
|
||||||
foreach (const QString &v, supported_versions) {
|
{
|
||||||
if (QFile::exists("C:/Python"+v+"/python.exe"))
|
QString path = pythonSearchReg(USER);
|
||||||
return "C:/Python"+v;
|
if (!path.isEmpty())
|
||||||
}
|
return path;
|
||||||
return QString::null;
|
|
||||||
|
path = pythonSearchReg(SYSTEM_32BIT);
|
||||||
|
if (!path.isEmpty())
|
||||||
|
return path;
|
||||||
|
|
||||||
|
path = pythonSearchReg(SYSTEM_64BIT);
|
||||||
|
if (!path.isEmpty())
|
||||||
|
return path;
|
||||||
|
|
||||||
|
// Fallback: Detect python from default locations
|
||||||
|
QStringList supported_versions;
|
||||||
|
supported_versions << "32" << "31" << "30" << "27" << "26" << "25";
|
||||||
|
foreach (const QString &v, supported_versions) {
|
||||||
|
if (QFile::exists("C:/Python" + v + "/python.exe"))
|
||||||
|
return "C:/Python" + v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Preferences::neverCheckFileAssoc() const {
|
bool Preferences::neverCheckFileAssoc() const {
|
||||||
|
Loading…
Reference in New Issue
Block a user