summaryrefslogtreecommitdiffstats
path: root/PC
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-01-24 17:04:00 (GMT)
committerGitHub <noreply@github.com>2023-01-24 17:04:00 (GMT)
commit5a8ed019f9b826d2ba5766688d51005624cd0699 (patch)
tree80b117bb7041c2debe43c60c38c8f5345f09795f /PC
parentbab79942c46436e0034c8a033a3c22974ddf6645 (diff)
downloadcpython-5a8ed019f9b826d2ba5766688d51005624cd0699.zip
cpython-5a8ed019f9b826d2ba5766688d51005624cd0699.tar.gz
cpython-5a8ed019f9b826d2ba5766688d51005624cd0699.tar.bz2
gh-101135: Add backwards compatibility to Windows launcher for older 32-bit versions (GH-101138)
Python 2.x and up to 3.4 did not contain the "-32" in their registry name, so the 32 and 64-bit installs were treated equal. Since 3.5/PEP 514 this is no longer true, but we still want to detect the EOL versions correctly in case people are still using them. Additionally, the code to replace a node with one with a lower sort key was buggy (wrong node chosen, replace never happened since parent was always NULL, replaced node never freed, etc) (cherry picked from commit daec3a463c747c852d7ee91e82770fb1763d7d31) Co-authored-by: Martin Boisvert <martin.boisvert@optelgroup.com>
Diffstat (limited to 'PC')
-rw-r--r--PC/launcher2.c155
1 files changed, 121 insertions, 34 deletions
diff --git a/PC/launcher2.c b/PC/launcher2.c
index 8371c60..4c77ec0 100644
--- a/PC/launcher2.c
+++ b/PC/launcher2.c
@@ -1294,34 +1294,34 @@ _compareTag(const wchar_t *x, const wchar_t *y)
int
-addEnvironmentInfo(EnvironmentInfo **root, EnvironmentInfo *node)
+addEnvironmentInfo(EnvironmentInfo **root, EnvironmentInfo* parent, EnvironmentInfo *node)
{
EnvironmentInfo *r = *root;
if (!r) {
*root = node;
- node->parent = NULL;
+ node->parent = parent;
return 0;
}
// Sort by company name
switch (_compareCompany(node->company, r->company)) {
case -1:
- return addEnvironmentInfo(&r->prev, node);
+ return addEnvironmentInfo(&r->prev, r, node);
case 1:
- return addEnvironmentInfo(&r->next, node);
+ return addEnvironmentInfo(&r->next, r, node);
case 0:
break;
}
// Then by tag (descending)
switch (_compareTag(node->tag, r->tag)) {
case -1:
- return addEnvironmentInfo(&r->next, node);
+ return addEnvironmentInfo(&r->next, r, node);
case 1:
- return addEnvironmentInfo(&r->prev, node);
+ return addEnvironmentInfo(&r->prev, r, node);
case 0:
break;
}
// Then keep the one with the lowest internal sort key
- if (r->internalSortKey < node->internalSortKey) {
+ if (node->internalSortKey < r->internalSortKey) {
// Replace the current node
node->parent = r->parent;
if (node->parent) {
@@ -1334,9 +1334,16 @@ addEnvironmentInfo(EnvironmentInfo **root, EnvironmentInfo *node)
freeEnvironmentInfo(node);
return RC_INTERNAL_ERROR;
}
+ } else {
+ // If node has no parent, then it is the root.
+ *root = node;
}
+
node->next = r->next;
node->prev = r->prev;
+
+ debug(L"# replaced %s/%s/%i in tree\n", node->company, node->tag, node->internalSortKey);
+ freeEnvironmentInfo(r);
} else {
debug(L"# not adding %s/%s/%i to tree\n", node->company, node->tag, node->internalSortKey);
return RC_DUPLICATE_ITEM;
@@ -1392,6 +1399,100 @@ _combineWithInstallDir(const wchar_t **dest, const wchar_t *installDir, const wc
}
+bool
+_isLegacyVersion(EnvironmentInfo *env)
+{
+ // Check if backwards-compatibility is required.
+ // Specifically PythonCore versions 2.X and 3.0 - 3.5 do not implement PEP 514.
+ if (0 != _compare(env->company, -1, L"PythonCore", -1)) {
+ return false;
+ }
+
+ int versionMajor, versionMinor;
+ int n = swscanf_s(env->tag, L"%d.%d", &versionMajor, &versionMinor);
+ if (n != 2) {
+ debug(L"# %s/%s has an invalid version tag\n", env->company, env->tag);
+ return false;
+ }
+
+ return versionMajor == 2
+ || (versionMajor == 3 && versionMinor >= 0 && versionMinor <= 5);
+}
+
+int
+_registryReadLegacyEnvironment(const SearchInfo *search, HKEY root, EnvironmentInfo *env, const wchar_t *fallbackArch)
+{
+ // Backwards-compatibility for PythonCore versions which do not implement PEP 514.
+ int exitCode = _combineWithInstallDir(
+ &env->executablePath,
+ env->installDir,
+ search->executable,
+ search->executableLength
+ );
+ if (exitCode) {
+ return exitCode;
+ }
+
+ if (search->windowed) {
+ exitCode = _registryReadString(&env->executableArgs, root, L"InstallPath", L"WindowedExecutableArguments");
+ }
+ else {
+ exitCode = _registryReadString(&env->executableArgs, root, L"InstallPath", L"ExecutableArguments");
+ }
+ if (exitCode) {
+ return exitCode;
+ }
+
+ if (fallbackArch) {
+ copyWstr(&env->architecture, fallbackArch);
+ } else {
+ DWORD binaryType;
+ BOOL success = GetBinaryTypeW(env->executablePath, &binaryType);
+ if (!success) {
+ return RC_NO_PYTHON;
+ }
+
+ switch (binaryType) {
+ case SCS_32BIT_BINARY:
+ copyWstr(&env->architecture, L"32bit");
+ break;
+ case SCS_64BIT_BINARY:
+ copyWstr(&env->architecture, L"64bit");
+ break;
+ default:
+ return RC_NO_PYTHON;
+ }
+ }
+
+ if (0 == _compare(env->architecture, -1, L"32bit", -1)) {
+ size_t tagLength = wcslen(env->tag);
+ if (tagLength <= 3 || 0 != _compare(&env->tag[tagLength - 3], 3, L"-32", 3)) {
+ const wchar_t *rawTag = env->tag;
+ wchar_t *realTag = (wchar_t*) malloc(sizeof(wchar_t) * (tagLength + 4));
+ if (!realTag) {
+ return RC_NO_MEMORY;
+ }
+
+ int count = swprintf_s(realTag, tagLength + 4, L"%s-32", env->tag);
+ if (count == -1) {
+ free(realTag);
+ return RC_INTERNAL_ERROR;
+ }
+
+ env->tag = realTag;
+ free((void*)rawTag);
+ }
+ }
+
+ wchar_t buffer[MAXLEN];
+ if (swprintf_s(buffer, MAXLEN, L"Python %s", env->tag)) {
+ copyWstr(&env->displayName, buffer);
+ }
+
+ return 0;
+}
+
+
int
_registryReadEnvironment(const SearchInfo *search, HKEY root, EnvironmentInfo *env, const wchar_t *fallbackArch)
{
@@ -1403,6 +1504,10 @@ _registryReadEnvironment(const SearchInfo *search, HKEY root, EnvironmentInfo *e
return RC_NO_PYTHON;
}
+ if (_isLegacyVersion(env)) {
+ return _registryReadLegacyEnvironment(search, root, env, fallbackArch);
+ }
+
// If pythonw.exe requested, check specific value
if (search->windowed) {
exitCode = _registryReadString(&env->executablePath, root, L"InstallPath", L"WindowedExecutablePath");
@@ -1425,6 +1530,11 @@ _registryReadEnvironment(const SearchInfo *search, HKEY root, EnvironmentInfo *e
return exitCode;
}
+ if (!env->executablePath) {
+ debug(L"# %s/%s has no executable path\n", env->company, env->tag);
+ return RC_NO_PYTHON;
+ }
+
exitCode = _registryReadString(&env->architecture, root, NULL, L"SysArchitecture");
if (exitCode) {
return exitCode;
@@ -1435,29 +1545,6 @@ _registryReadEnvironment(const SearchInfo *search, HKEY root, EnvironmentInfo *e
return exitCode;
}
- // Only PythonCore entries will infer executablePath from installDir and architecture from the binary
- if (0 == _compare(env->company, -1, L"PythonCore", -1)) {
- if (!env->executablePath) {
- exitCode = _combineWithInstallDir(
- &env->executablePath,
- env->installDir,
- search->executable,
- search->executableLength
- );
- if (exitCode) {
- return exitCode;
- }
- }
- if (!env->architecture && env->executablePath && fallbackArch) {
- copyWstr(&env->architecture, fallbackArch);
- }
- }
-
- if (!env->executablePath) {
- debug(L"# %s/%s has no executable path\n", env->company, env->tag);
- return RC_NO_PYTHON;
- }
-
return 0;
}
@@ -1486,7 +1573,7 @@ _registrySearchTags(const SearchInfo *search, EnvironmentInfo **result, HKEY roo
freeEnvironmentInfo(env);
exitCode = 0;
} else if (!exitCode) {
- exitCode = addEnvironmentInfo(result, env);
+ exitCode = addEnvironmentInfo(result, NULL, env);
if (exitCode) {
freeEnvironmentInfo(env);
if (exitCode == RC_DUPLICATE_ITEM) {
@@ -1574,7 +1661,7 @@ appxSearch(const SearchInfo *search, EnvironmentInfo **result, const wchar_t *pa
copyWstr(&env->displayName, buffer);
}
- int exitCode = addEnvironmentInfo(result, env);
+ int exitCode = addEnvironmentInfo(result, NULL, env);
if (exitCode) {
freeEnvironmentInfo(env);
if (exitCode == RC_DUPLICATE_ITEM) {
@@ -1612,7 +1699,7 @@ explicitOverrideSearch(const SearchInfo *search, EnvironmentInfo **result)
if (exitCode) {
goto abort;
}
- exitCode = addEnvironmentInfo(result, env);
+ exitCode = addEnvironmentInfo(result, NULL, env);
if (exitCode) {
goto abort;
}
@@ -1661,7 +1748,7 @@ virtualenvSearch(const SearchInfo *search, EnvironmentInfo **result)
if (exitCode) {
goto abort;
}
- exitCode = addEnvironmentInfo(result, env);
+ exitCode = addEnvironmentInfo(result, NULL, env);
if (exitCode) {
goto abort;
}