Skip to content

Commit

Permalink
Windows 7 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
NulAsh committed Feb 21, 2021
1 parent 1a79785 commit af74a64
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 26 deletions.
57 changes: 52 additions & 5 deletions PC/getpathp.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@
#endif

#include <windows.h>
#include <pathcch.h>
#include <shlwapi.h>

#ifdef HAVE_SYS_TYPES_H
Expand Down Expand Up @@ -250,14 +249,43 @@ ismodule(wchar_t *filename, int update_filename)
stuff as fits will be appended.
*/

static int _PathCchCombineEx_Initialized = 0;
typedef HRESULT(__stdcall *PPathCchCombineEx) (PWSTR pszPathOut, size_t cchPathOut,
PCWSTR pszPathIn, PCWSTR pszMore,
unsigned long dwFlags);
static PPathCchCombineEx _PathCchCombineEx;

static void
join(wchar_t *buffer, const wchar_t *stuff)
{
if (FAILED(PathCchCombineEx(buffer, MAXPATHLEN+1, buffer, stuff, 0))) {
Py_FatalError("buffer overflow in getpathp.c's join()");
if (_PathCchCombineEx_Initialized == 0) {
HMODULE pathapi = LoadLibraryExW(L"api-ms-win-core-path-l1-1-0.dll", NULL,
LOAD_LIBRARY_SEARCH_SYSTEM32);
if (pathapi) {
_PathCchCombineEx = (PPathCchCombineEx)GetProcAddress(pathapi, "PathCchCombineEx");
}
else {
_PathCchCombineEx = NULL;
}
_PathCchCombineEx_Initialized = 1;
}

if (_PathCchCombineEx) {
if (FAILED(_PathCchCombineEx(buffer, MAXPATHLEN+1, buffer, stuff, 0))) {
Py_FatalError("buffer overflow in getpathp.c's join()");
}
} else {
if (!PathCombineW(buffer, buffer, stuff)) {
Py_FatalError("buffer overflow in getpathp.c's join()");
}
}
}

static int _PathCchCanonicalizeEx_Initialized = 0;
typedef HRESULT(__stdcall *PPathCchCanonicalizeEx) (PWSTR pszPathOut, size_t cchPathOut,
PCWSTR pszPathIn, unsigned long dwFlags);
static PPathCchCanonicalizeEx _PathCchCanonicalizeEx;

/* Call PathCchCanonicalizeEx(path): remove navigation elements such as "."
and ".." to produce a direct, well-formed path. */
static PyStatus
Expand All @@ -267,8 +295,27 @@ canonicalize(wchar_t *buffer, const wchar_t *path)
return _PyStatus_NO_MEMORY();
}

if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) {
return INIT_ERR_BUFFER_OVERFLOW();
if (_PathCchCanonicalizeEx_Initialized == 0) {
HMODULE pathapi = LoadLibraryExW(L"api-ms-win-core-path-l1-1-0.dll", NULL,
LOAD_LIBRARY_SEARCH_SYSTEM32);
if (pathapi) {
_PathCchCanonicalizeEx = (PPathCchCanonicalizeEx)GetProcAddress(pathapi, "PathCchCanonicalizeEx");
}
else {
_PathCchCanonicalizeEx = NULL;
}
_PathCchCanonicalizeEx_Initialized = 1;
}

if (_PathCchCanonicalizeEx) {
if (FAILED(_PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) {
return INIT_ERR_BUFFER_OVERFLOW();
}
}
else {
if (!PathCanonicalizeW(buffer, path)) {
return INIT_ERR_BUFFER_OVERFLOW();
}
}
return _PyStatus_OK();
}
Expand Down
6 changes: 3 additions & 3 deletions PC/pyconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ WIN32 is still required for the locale module.
#endif /* MS_WIN64 */

/* set the version macros for the windows headers */
/* Python 3.9+ requires Windows 8 or greater */
#define Py_WINVER 0x0602 /* _WIN32_WINNT_WIN8 */
#define Py_NTDDI NTDDI_WIN8
/* Python 3.5+ requires Windows Vista or greater */
#define Py_WINVER 0x0600 /* _WIN32_WINNT_VISTA */
#define Py_NTDDI NTDDI_VISTA

/* We only set these values when building Python - we don't want to force
these values on extensions, as that will affect the prototypes and
Expand Down
2 changes: 1 addition & 1 deletion PCbuild/pythoncore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
<PreprocessorDefinitions Condition="$(IncludeExternals)">_Py_HAVE_ZLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>version.lib;shlwapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
This is Python version 3.9.2
============================

This is a fork, intended to run on Windows 7, for details look at `Win7.rst
<https://github.com/NulAsh/cpython/blob/3.9.2-win7/Win7.rst>`_.

.. image:: https://travis-ci.org/python/cpython.svg?branch=3.9
:alt: CPython build status on Travis CI
:target: https://travis-ci.org/python/cpython
Expand Down
4 changes: 2 additions & 2 deletions Tools/msi/buildrelease.bat
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ if "%OUTDIR_PLAT%" EQU "win32" (

set BUILDOPTS=/p:Platform=%1 /p:BuildForRelease=true /p:DownloadUrl=%DOWNLOAD_URL% /p:DownloadUrlBase=%DOWNLOAD_URL_BASE% /p:ReleaseUri=%RELEASE_URI%
if defined BUILDMSI (
%MSBUILD% "%D%bundle\releaselocal.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=true
%MSBUILD% "%D%bundle\full.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=true
if errorlevel 1 exit /B
%MSBUILD% "%D%bundle\releaseweb.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=false
%MSBUILD% "%D%bundle\releaselocal.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=false
if errorlevel 1 exit /B
)

Expand Down
21 changes: 19 additions & 2 deletions Tools/msi/bundle/Default.wxl
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,26 @@ Feel free to email &lt;a href="mailto:python-list@python.org"&gt;python-list@pyt
<String Id="FailureRestartButton">&amp;Restart</String>
<String Id="FailureExistingInstall">Unable to install [WixBundleName] due to an existing install. Use Programs and Features to modify, repair or remove [WixBundleName].</String>

<String Id="FailureOldOS">At least Windows 8.1 or Windows Server 2012 are required to install [WixBundleName]
<String Id="FailureWin7MissingSP1">Windows 7 Service Pack 1 and all applicable updates are required to install [WixBundleName].

Please &lt;a href="https://www.bing.com/search?q=how%20to%20install%20windows%207%20service%20pack%201"&gt;update your machine&lt;/a&gt; and then restart the installation.</String>
<String Id="FailureVistaMissingSP2">Windows Vista Service Pack 2 and all applicable updates are required to install [WixBundleName].

Please &lt;a href="https://www.bing.com/search?q=how%20to%20install%20windows%20vista%20service%20pack%202"&gt;update your machine&lt;/a&gt; and then restart the installation.</String>
<String Id="FailureXPOrEarlier">Windows Vista or later is required to install and use [WixBundleName].

Visit &lt;a href="https://www.python.org/"&gt;python.org&lt;/a&gt; to download Python 3.4.</String>

<String Id="FailureWS2K8R2MissingSP1">Windows Server 2008 R2 Service Pack 1 and all applicable updates are required to install [WixBundleName].

Please &lt;a href="https://www.bing.com/search?q=how%20to%20install%20windows%20server%202008%20r2%20service%20pack%201"&gt;update your machine&lt;/a&gt; and then restart the installation.</String>
<String Id="FailureWS2K8MissingSP2">Windows Server 2008 Service Pack 2 and all applicable updates are required to install [WixBundleName].

Please &lt;a href="https://www.bing.com/search?q=how%20to%20install%20windows%20server%202008%20service%20pack%202"&gt;update your machine&lt;/a&gt; and then restart the installation.</String>
<String Id="FailureWS2K3OrEarlier">Windows Server 2008 SP2 or later is required to install and use [WixBundleName].

Visit &lt;a href="https://www.python.org/"&gt;python.org&lt;/a&gt; to download Python 3.4.</String>

Visit &lt;a href="https://www.python.org/"&gt;python.org&lt;/a&gt; to download an earlier version of Python.</String>
<String Id="SuccessMaxPathButton">Disable path length limit</String>
<String Id="SuccessMaxPathButtonNote">Changes your machine configuration to allow programs, including Python, to bypass the 260 character "MAX_PATH" limitation.</String>
</WixLocalization>
56 changes: 43 additions & 13 deletions Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3011,35 +3011,65 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows Server 2012 or later");
return;
} else if (IsWindowsVersionOrGreater(6, 1, 1)) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Detected Windows Server 2008 R2");
HMODULE hKernel32 = GetModuleHandleW(L"kernel32");
if (hKernel32 && !GetProcAddress(hKernel32, "AddDllDirectory")) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows Server 2008 R2 without KB2533623");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "KB2533623 update is required to continue.");
/* The "MissingSP1" error also specifies updates are required */
LocGetString(_wixLoc, L"#(loc.FailureWS2K8R2MissingSP1)", &pLocString);
} else {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows Server 2008 R2 or later");
return;
}
} else if (IsWindowsVersionOrGreater(6, 1, 0)) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows Server 2008 R2");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Service Pack 1 is required to continue installation");
LocGetString(_wixLoc, L"#(loc.FailureWS2K8R2MissingSP1)", &pLocString);
} else if (IsWindowsVersionOrGreater(6, 0, 2)) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Target OS is Windows Server 2008 SP2 or later");
return;
} else if (IsWindowsVersionOrGreater(6, 0, 0)) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows Server 2008");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Service Pack 2 is required to continue installation");
LocGetString(_wixLoc, L"#(loc.FailureWS2K8MissingSP2)", &pLocString);
} else {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows Server 2003 or earlier");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Windows Server 2008 SP2 or later is required to continue installation");
LocGetString(_wixLoc, L"#(loc.FailureWS2K3OrEarlier)", &pLocString);
}
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Windows Server 2012 or later is required to continue installation");
} else {
if (IsWindows10OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows 10 or later");
return;
} else if (IsWindows8Point1OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows 8.1");
if (IsWindows8OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows 8 or later");
return;
} else if (IsWindows8OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows 8");
} else if (IsWindows7SP1OrGreater()) {
HMODULE hKernel32 = GetModuleHandleW(L"kernel32");
if (hKernel32 && !GetProcAddress(hKernel32, "AddDllDirectory")) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows 7 SP1 without KB2533623");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "KB2533623 update is required to continue.");
/* The "MissingSP1" error also specifies updates are required */
LocGetString(_wixLoc, L"#(loc.FailureWin7MissingSP1)", &pLocString);
} else {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows 7 SP1 or later");
return;
}
} else if (IsWindows7OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows 7");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows 7 RTM");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Service Pack 1 is required to continue installation");
LocGetString(_wixLoc, L"#(loc.FailureWin7MissingSP1)", &pLocString);
} else if (IsWindowsVistaSP2OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Target OS is Windows Vista SP2");
return;
} else if (IsWindowsVistaOrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows Vista");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows Vista RTM or SP1");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Service Pack 2 is required to continue installation");
LocGetString(_wixLoc, L"#(loc.FailureVistaMissingSP2)", &pLocString);
} else {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows XP or earlier");
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Windows Vista SP2 or later is required to continue installation");
LocGetString(_wixLoc, L"#(loc.FailureXPOrEarlier)", &pLocString);
}
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Windows 8.1 or later is required to continue installation");
}

LocGetString(_wixLoc, L"#(loc.FailureOldOS)", &pLocString);
if (pLocString && pLocString->wzText) {
BalFormatString(pLocString->wzText, &_failedMessage);
}
Expand Down
33 changes: 33 additions & 0 deletions Win7.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
============
Python 3.9.2 fork for Windows 7 support
============

A lot of people still use Windows 7. End date of ESU support - 2023-01-10.

***************
Build instructions:
***************

You need Visual Studio 2017 and Python 3.8. Switch off vcpkg if it's installed
(vcpkg integrate remove). Install everything related to Python in Visual Studio Installer.

1. Start your "x64 Native Tools Command Prompt for VS 2017"
2. Change current directory to the place with enough free space.
3. pip install -U sphinx
4. set PYTHON="C:\\Program Files\\Python38\\python.exe"
5. set SPHINXBUILD="C:\\Program Files\\Python38\\Scripts\\sphinx-build.exe"
6. git clone https://github.com/NulAsh/cpython.git
7. cd cpython\\Tools\\msi
8. buildrelease.bat -x64
9. cd ..\\..\\PCbuild\\amd64\\en-us

And in this folder we can see installer python-3.9.2-amd64.exe, install it as usual.

If you need debugging symbols and/or debug binaries, you need to use python-3.9.2-amd64-full.exe

Usually Python is distributed in two forms:
- web-based installer (internally called "releaseweb") - very small executable that downloads everything before installation, will not work if you have no internet connection
- executable installer (internally called "releaselocal") - have standard Python distribution inside, but without debugging symbols (*.pdb) and debug binaries,
so if you need them, you still have to download them separately (installer will do this for you if you select appropriate checkboxes)
But in case of my fork, if you need them, you have to download full release, it have them inside

0 comments on commit af74a64

Please sign in to comment.