Skip to content

Commit f86d440

Browse files
committed
Fixes #51: Enable pyshellext to search all registered runtimes
1 parent 92124bf commit f86d440

File tree

1 file changed

+51
-21
lines changed

1 file changed

+51
-21
lines changed

src/pyshellext/shellext.cpp

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -59,26 +59,26 @@ static LRESULT RegReadStr(HKEY key, LPCWSTR valueName, std::wstring& result)
5959
}
6060

6161

62-
static HRESULT ReadIdleInstalls(std::vector<IdleData> &idles, HKEY hive, REGSAM flags)
62+
static HRESULT ReadIdleInstalls(std::vector<IdleData> &idles, HKEY hkPython, LPCWSTR company, REGSAM flags)
6363
{
64-
HKEY hkPythonCore = NULL, hkTag = NULL, hkInstall = NULL;
64+
HKEY hkCompany = NULL, hkTag = NULL, hkInstall = NULL;
6565
LSTATUS err = RegOpenKeyExW(
66-
hive,
67-
L"Software\\Python\\PythonCore",
66+
hkPython,
67+
company,
6868
0,
6969
KEY_READ | flags,
70-
&hkPythonCore
70+
&hkCompany
7171
);
7272

7373
for (DWORD i = 0; !err && i < 64; ++i) {
74-
wchar_t name[128];
74+
wchar_t name[512];
7575
DWORD cchName = sizeof(name) / sizeof(name[0]);
76-
err = RegEnumKeyExW(hkPythonCore, i, name, &cchName, NULL, NULL, NULL, NULL);
76+
err = RegEnumKeyExW(hkCompany, i, name, &cchName, NULL, NULL, NULL, NULL);
7777
if (!err) {
78-
err = RegOpenKeyExW(hkPythonCore, name, 0, KEY_READ, &hkTag);
78+
err = RegOpenKeyExW(hkCompany, name, 0, KEY_READ | flags, &hkTag);
7979
}
8080
if (!err) {
81-
err = RegOpenKeyExW(hkTag, L"InstallPath", 0, KEY_READ, &hkInstall);
81+
err = RegOpenKeyExW(hkTag, L"InstallPath", 0, KEY_READ | flags, &hkInstall);
8282
}
8383
if (err) {
8484
break;
@@ -111,12 +111,15 @@ static HRESULT ReadIdleInstalls(std::vector<IdleData> &idles, HKEY hive, REGSAM
111111

112112
err = RegReadStr(hkInstall, L"IdlePath", data.idle);
113113
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_INVALID_DATA) {
114-
err = RegReadStr(hkInstall, NULL, data.idle);
115-
if (!err) {
116-
if (data.idle.back() != L'\\') {
117-
data.idle += L"\\Lib\\idlelib\\idle.pyw";
118-
} else {
119-
data.idle += L"Lib\\idlelib\\idle.pyw";
114+
if (0 == wcsicmp(company, L"PythonCore")) {
115+
// Only use fallback logic for PythonCore
116+
err = RegReadStr(hkInstall, NULL, data.idle);
117+
if (!err) {
118+
if (data.idle.back() != L'\\') {
119+
data.idle += L"\\Lib\\idlelib\\idle.pyw";
120+
} else {
121+
data.idle += L"Lib\\idlelib\\idle.pyw";
122+
}
120123
}
121124
}
122125
}
@@ -129,7 +132,9 @@ static HRESULT ReadIdleInstalls(std::vector<IdleData> &idles, HKEY hive, REGSAM
129132
RegCloseKey(hkTag);
130133
hkTag = NULL;
131134

132-
if (GetFileAttributesW(data.exe.c_str()) != INVALID_FILE_ATTRIBUTES
135+
if (!data.exe.empty()
136+
&& !data.idle.empty()
137+
&& GetFileAttributesW(data.exe.c_str()) != INVALID_FILE_ATTRIBUTES
133138
&& GetFileAttributesW(data.idle.c_str()) != INVALID_FILE_ATTRIBUTES) {
134139
idles.push_back(data);
135140
}
@@ -140,15 +145,40 @@ static HRESULT ReadIdleInstalls(std::vector<IdleData> &idles, HKEY hive, REGSAM
140145
if (hkTag) {
141146
RegCloseKey(hkTag);
142147
}
143-
if (hkPythonCore) {
144-
RegCloseKey(hkPythonCore);
148+
if (hkCompany) {
149+
RegCloseKey(hkCompany);
145150
}
146151
if (err && err != ERROR_NO_MORE_ITEMS && err != ERROR_FILE_NOT_FOUND) {
147152
return HRESULT_FROM_WIN32(err);
148153
}
149154
return S_OK;
150155
}
151156

157+
static HRESULT ReadAllIdleInstalls(std::vector<IdleData> &idles, HKEY hive, REGSAM flags)
158+
{
159+
HKEY hkPython = NULL;
160+
HRESULT hr = S_OK;
161+
LSTATUS err = RegOpenKeyExW(hive, L"Software\\Python", 0, KEY_READ | flags, &hkPython);
162+
163+
for (DWORD i = 0; !err && hr == S_OK && i < 64; ++i) {
164+
wchar_t name[512];
165+
DWORD cchName = sizeof(name) / sizeof(name[0]);
166+
err = RegEnumKeyExW(hkPython, i, name, &cchName, NULL, NULL, NULL, NULL);
167+
if (!err) {
168+
hr = ReadIdleInstalls(idles, hkPython, name, flags);
169+
}
170+
}
171+
172+
if (hkPython) {
173+
RegCloseKey(hkPython);
174+
}
175+
176+
if (err && err != ERROR_NO_MORE_ITEMS && err != ERROR_FILE_NOT_FOUND) {
177+
return HRESULT_FROM_WIN32(err);
178+
}
179+
return hr;
180+
}
181+
152182
class DECLSPEC_UUID(CLSID_LAUNCH_COMMAND) LaunchCommand
153183
: public RuntimeClass<RuntimeClassFlags<ClassicCom>, IExplorerCommand>
154184
{
@@ -319,12 +349,12 @@ class DECLSPEC_UUID(CLSID_IDLE_COMMAND) IdleCommand
319349
iconPath += L",-4";
320350
}
321351

322-
hr = ReadIdleInstalls(idles, HKEY_LOCAL_MACHINE, KEY_WOW64_32KEY);
352+
hr = ReadAllIdleInstalls(idles, HKEY_LOCAL_MACHINE, KEY_WOW64_32KEY);
323353
if (SUCCEEDED(hr)) {
324-
hr = ReadIdleInstalls(idles, HKEY_LOCAL_MACHINE, KEY_WOW64_64KEY);
354+
hr = ReadAllIdleInstalls(idles, HKEY_LOCAL_MACHINE, KEY_WOW64_64KEY);
325355
}
326356
if (SUCCEEDED(hr)) {
327-
hr = ReadIdleInstalls(idles, HKEY_CURRENT_USER, 0);
357+
hr = ReadAllIdleInstalls(idles, HKEY_CURRENT_USER, 0);
328358
}
329359

330360
if (FAILED(hr)) {

0 commit comments

Comments
 (0)