From 638b8cbd66efd4824db5bcab4378ff0a319b54f5 Mon Sep 17 00:00:00 2001
From: Naveen M K <naveen521kk@gmail.com>
Date: Sun, 25 Jun 2023 17:26:55 +0530
Subject: [PATCH 092/N] Build venvlauncher.exe from PC/launcher.c

- Use function available in original msvcrt.dll
  _wdupenv_s -> _wgetenv_s
  fread_s -> fread
- Add a test for checking the new launchers
---
 Makefile.pre.in     | 20 ++++++++++++--------
 PC/launcher.c       | 29 +++++++++++++++++------------
 PC/pylauncher.rc    | 20 ++++++++++----------
 mingw_smoketests.py | 12 ++++++++++++
 4 files changed, 51 insertions(+), 30 deletions(-)

diff --git a/Makefile.pre.in b/Makefile.pre.in
index 66dcebc..d81352e 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -899,6 +899,12 @@ pythonw_exe.o: $(srcdir)/PC/pythonw_exe.rc
 python_nt.o: $(srcdir)/PC/python_nt.rc
 	$(WINDRES) $(RCFLAGS) -DORIGINAL_FILENAME=\\\"$(DLLLIBRARY)\\\" -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/python_nt.rc $@
 
+venvlauncher.o: $(srcdir)/PC/pylauncher.rc
+	$(WINDRES) $(RCFLAGS) -DPY_ICON -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/pylauncher.rc $@
+
+venvwlauncher.o: $(srcdir)/PC/pylauncher.rc
+	$(WINDRES) $(RCFLAGS) -DPYW_ICON -I$(srcdir)/Include -I$(srcdir)/PC -I. $(srcdir)/PC/pylauncher.rc $@
+
 $(BUILDPYTHONW): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) pythonw_exe.o
 	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -municode -mwindows -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) pythonw_exe.o
 
@@ -906,13 +912,11 @@ $(BUILDPYTHONW): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) pythonw
 $(BUILDPYTHON):	Programs/python.o $(LINK_PYTHON_DEPS) python_exe.o
 	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -municode -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS) python_exe.o
 
-# FIXME: build these from PC/launcher.c instead
-$(BUILDVENVLAUNCHER): $(BUILDPYTHON)
-	cp $(BUILDPYTHON) $(BUILDVENVLAUNCHER)
+$(BUILDVENVLAUNCHER): $(BUILDPYTHON) venvlauncher.o  $(srcdir)/PC/launcher.c
+	$(LINKCC) -D_CONSOLE -DVENV_REDIRECT $(PY_STDMODULE_CFLAGS) -municode -static -static-libgcc -static-libstdc++ venvlauncher.o $(srcdir)/PC/launcher.c -o $@ -lversion
 
-# FIXME: build these from PC/launcher.c instead
-$(BUILDVENVWLAUNCHER): $(BUILDPYTHONW)
-	cp $(BUILDPYTHONW) $(BUILDVENVWLAUNCHER)
+$(BUILDVENVWLAUNCHER): $(BUILDPYTHONW) venvwlauncher.o  $(srcdir)/PC/launcher.c
+	$(LINKCC) -D_WINDOWS -DVENV_REDIRECT $(PY_STDMODULE_CFLAGS) -mwindows -municode -static -static-libgcc -static-libstdc++ venvwlauncher.o $(srcdir)/PC/launcher.c -o $@ -lversion
 
 platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt
 	$(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform
@@ -2237,8 +2241,8 @@ altbininstall: $(BUILDPYTHON) @FRAMEWORKPYTHONW@
 	if test "$(PYTHONFRAMEWORKDIR)" = "no-framework" ; then \
 		$(INSTALL_PROGRAM) $(BUILDPYTHON) $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \
 		$(INSTALL_PROGRAM) $(BUILDPYTHONW) $(DESTDIR)$(BINDIR)/python3w$(EXE); \
-		$(INSTALL_PROGRAM) $(BUILDPYTHON) $(DESTDIR)$(VENVLAUNCHERDIR)/python$(EXE); \
-		$(INSTALL_PROGRAM) $(BUILDPYTHONW) $(DESTDIR)$(VENVLAUNCHERDIR)/pythonw$(EXE); \
+		$(INSTALL_PROGRAM) $(BUILDVENVLAUNCHER) $(DESTDIR)$(VENVLAUNCHERDIR)/python$(EXE); \
+		$(INSTALL_PROGRAM) $(BUILDVENVWLAUNCHER) $(DESTDIR)$(VENVLAUNCHERDIR)/pythonw$(EXE); \
 	else \
 		$(INSTALL_PROGRAM) $(STRIPFLAG) Mac/pythonw $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \
 	fi
diff --git a/PC/launcher.c b/PC/launcher.c
index 8e60ab9..796bf73 100644
--- a/PC/launcher.c
+++ b/PC/launcher.c
@@ -924,7 +924,7 @@ static COMMAND path_command;
 static COMMAND * find_on_path(wchar_t * name)
 {
     wchar_t * pathext;
-    size_t    varsize;
+    size_t    requiredSize;
     wchar_t * context = NULL;
     wchar_t * extension;
     COMMAND * result = NULL;
@@ -941,18 +941,23 @@ static COMMAND * find_on_path(wchar_t * name)
     }
     else {
         /* No extension - search using registered extensions. */
-        rc = _wdupenv_s(&pathext, &varsize, L"PATHEXT");
-        if (rc == 0) {
-            extension = wcstok_s(pathext, L";", &context);
-            while (extension) {
-                len = SearchPathW(NULL, name, extension, MSGSIZE, path_command.value, NULL);
-                if (len) {
-                    result = &path_command;
-                    break;
+        _wgetenv_s(&requiredSize, NULL, 0, L"PATHEXT");
+        if (requiredSize > 0) {
+            pathext = (wchar_t *)malloc(requiredSize * sizeof(wchar_t));
+            /* No extension - search using registered extensions. */
+            rc = _wgetenv_s(&requiredSize, pathext, requiredSize, L"PATHEXT");
+            if (rc == 0) {
+                extension = wcstok_s(pathext, L";", &context);
+                while (extension) {
+                    len = SearchPathW(NULL, name, extension, MSGSIZE, path_command.value, NULL);
+                    if (len) {
+                        result = &path_command;
+                        break;
+                    }
+                    extension = wcstok_s(NULL, L";", &context);
                 }
-                extension = wcstok_s(NULL, L";", &context);
+                free(pathext);
             }
-            free(pathext);
         }
     }
     return result;
@@ -1913,7 +1918,7 @@ process(int argc, wchar_t ** argv)
         if (_wfopen_s(&f, venv_cfg_path, L"r")) {
             error(RC_BAD_VENV_CFG, L"Cannot read '%ls'", venv_cfg_path);
         }
-        cb = fread_s(buffer, sizeof(buffer), sizeof(buffer[0]),
+        cb = fread(buffer, sizeof(buffer[0]),
                      sizeof(buffer) / sizeof(buffer[0]), f);
         fclose(f);
 
diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc
index 1186264..84b2917 100644
--- a/PC/pylauncher.rc
+++ b/PC/pylauncher.rc
@@ -12,17 +12,17 @@
 1 RT_MANIFEST "python.manifest"
 
 #if defined(PY_ICON)
-1 ICON DISCARDABLE "icons\python.ico"
+1 ICON DISCARDABLE "icons/python.ico"
 #elif defined(PYW_ICON)
-1 ICON DISCARDABLE "icons\pythonw.ico"
+1 ICON DISCARDABLE "icons/pythonw.ico"
 #else
-1 ICON DISCARDABLE "icons\launcher.ico" 
-2 ICON DISCARDABLE "icons\py.ico" 
-3 ICON DISCARDABLE "icons\pyc.ico" 
-4 ICON DISCARDABLE "icons\pyd.ico" 
-5 ICON DISCARDABLE "icons\python.ico"
-6 ICON DISCARDABLE "icons\pythonw.ico"
-7 ICON DISCARDABLE "icons\setup.ico" 
+1 ICON DISCARDABLE "icons/launcher.ico"
+2 ICON DISCARDABLE "icons/py.ico" 
+3 ICON DISCARDABLE "icons/pyc.ico" 
+4 ICON DISCARDABLE "icons/pyd.ico" 
+5 ICON DISCARDABLE "icons/python.ico"
+6 ICON DISCARDABLE "icons/pythonw.ico"
+7 ICON DISCARDABLE "icons/setup.ico" 
 #endif
 
 1 USAGE "launcher-usage.txt"
@@ -64,4 +64,4 @@ BEGIN
     BEGIN
         VALUE "Translation", 0x0, 1200
     END
-END
\ No newline at end of file
+END
diff --git a/mingw_smoketests.py b/mingw_smoketests.py
index 2a8bd16..00601f9 100644
--- a/mingw_smoketests.py
+++ b/mingw_smoketests.py
@@ -194,6 +194,18 @@ class Tests(unittest.TestCase):
             assert os.path.exists(os.path.join(tmp, "bin", "python3.exe"))
             subprocess.check_call([shutil.which("bash.exe"), os.path.join(tmp, "bin", "activate")])
 
+            # This will not work in in-tree build
+            if not sysconfig.is_python_build():
+                op = subprocess.check_output(
+                    [
+                        os.path.join(tmp, "bin", "python.exe"),
+                        "-c",
+                        "print('Hello World')"
+                    ],
+                    cwd=tmp,
+                )
+                assert op.decode().strip() == "Hello World"
+
     def test_has_mktime(self):
         from time import mktime, gmtime
         mktime(gmtime())
