Skip to content

Commit

Permalink
Windows 7 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
NulAsh committed Dec 10, 2020
1 parent 02e23f1 commit 9a5ddee
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 21 deletions.
53 changes: 50 additions & 3 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,13 +249,42 @@ 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))) {
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. */
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))) {
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
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>
54 changes: 42 additions & 12 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");
if (IsWindows8OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows 8 or later");
return;
} else if (IsWindows8Point1OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows 8.1");
} 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 (IsWindows8OrGreater()) {
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows 8");
}
} 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
24 changes: 24 additions & 0 deletions Win7.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
============
Python 3.9.1 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.1-amd64.exe, install it as usual.

0 comments on commit 9a5ddee

Please sign in to comment.