diff options
author | 2021-01-09 00:35:01 +0100 | |
---|---|---|
committer | 2021-01-09 00:35:01 +0100 | |
commit | 0e2a0f72cc9af0899eacb5604e44a563c0b06110 (patch) | |
tree | 73587df57200aa0b1c7d4c4ce476a07dbea8d6e6 /PC | |
parent | Fix a typo in docs for typing.Concatenate (#24169) (diff) | |
download | cpython-0e2a0f72cc9af0899eacb5604e44a563c0b06110.tar.gz cpython-0e2a0f72cc9af0899eacb5604e44a563c0b06110.tar.bz2 cpython-0e2a0f72cc9af0899eacb5604e44a563c0b06110.zip |
bpo-42802: Remove distutils bdist_wininst command (GH-24043)
The distutils bdist_wininst command deprecated in Python 3.8 has been
removed. The distutils bidst_wheel command is now recommended to
distribute binary packages on Windows.
* Remove Lib/distutils/command/bdist_wininst.py
* Remove PC/bdist_wininst/ project
* Remove Lib/distutils/command/wininst-*.exe programs
* Remove all references to bdist_wininst
Diffstat (limited to 'PC')
-rw-r--r-- | PC/bdist_wininst/PythonPowered.bmp | bin | 2582 -> 0 bytes | |||
-rw-r--r-- | PC/bdist_wininst/README.txt | 5 | ||||
-rw-r--r-- | PC/bdist_wininst/archive.h | 104 | ||||
-rw-r--r-- | PC/bdist_wininst/bdist_wininst.vcxproj | 125 | ||||
-rw-r--r-- | PC/bdist_wininst/bdist_wininst.vcxproj.filters | 67 | ||||
-rw-r--r-- | PC/bdist_wininst/build.bat | 19 | ||||
-rw-r--r-- | PC/bdist_wininst/extract.c | 320 | ||||
-rw-r--r-- | PC/bdist_wininst/install.c | 2700 | ||||
-rw-r--r-- | PC/bdist_wininst/install.rc | 77 | ||||
-rw-r--r-- | PC/bdist_wininst/resource.h | 31 | ||||
-rw-r--r-- | PC/layout/main.py | 9 | ||||
-rw-r--r-- | PC/layout/support/distutils.command.bdist_wininst.py | 25 | ||||
-rw-r--r-- | PC/layout/support/options.py | 2 |
13 files changed, 0 insertions, 3484 deletions
diff --git a/PC/bdist_wininst/PythonPowered.bmp b/PC/bdist_wininst/PythonPowered.bmp Binary files differdeleted file mode 100644 index dd70709da6..0000000000 --- a/PC/bdist_wininst/PythonPowered.bmp +++ /dev/null diff --git a/PC/bdist_wininst/README.txt b/PC/bdist_wininst/README.txt deleted file mode 100644 index 7c29be7c20..0000000000 --- a/PC/bdist_wininst/README.txt +++ /dev/null @@ -1,5 +0,0 @@ - -XXX Write description -XXX Dont't forget to mention upx - -XXX Add pointer to this file into PC/README.txt diff --git a/PC/bdist_wininst/archive.h b/PC/bdist_wininst/archive.h deleted file mode 100644 index 50ff15cddd..0000000000 --- a/PC/bdist_wininst/archive.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - IMPORTANT NOTE: IF THIS FILE IS CHANGED, PCBUILD\BDIST_WININST.VCXPROJ MUST - BE REBUILT AS WELL. - - IF CHANGES TO THIS FILE ARE CHECKED IN, THE RECOMPILED BINARIES MUST BE - CHECKED IN AS WELL! -*/ - -#pragma pack(1) - -/* zip-archive headers - * See: http://www.pkware.com/appnote.html - */ - -struct eof_cdir { - long tag; /* must be 0x06054b50 */ - short disknum; - short firstdisk; - short nTotalCDirThis; - short nTotalCDir; - long nBytesCDir; - long ofsCDir; - short commentlen; -}; - -struct cdir { - long tag; /* must be 0x02014b50 */ - short version_made; - short version_extract; - short gp_bitflag; - short comp_method; - short last_mod_file_time; - short last_mod_file_date; - long crc32; - long comp_size; - long uncomp_size; - short fname_length; - short extra_length; - short comment_length; - short disknum_start; - short int_file_attr; - long ext_file_attr; - long ofs_local_header; -}; - -struct fhdr { - long tag; /* must be 0x04034b50 */ - short version_needed; - short flags; - short method; - short last_mod_file_time; - short last_mod_file_date; - long crc32; - long comp_size; - long uncomp_size; - short fname_length; - short extra_length; -}; - - -struct meta_data_hdr { - int tag; - int uncomp_size; - int bitmap_size; -}; - -#pragma pack() - -/* installation scheme */ - -typedef struct tagSCHEME { - char *name; - char *prefix; -} SCHEME; - -typedef int (*NOTIFYPROC)(int code, LPSTR text, ...); - -extern BOOL -extract_file(char *dst, char *src, int method, int comp_size, - int uncomp_size, NOTIFYPROC notify); - -extern BOOL -unzip_archive(SCHEME *scheme, char *dirname, char *data, - DWORD size, NOTIFYPROC notify); - -extern char * -map_new_file(DWORD flags, char *filename, char - *pathname_part, int size, - WORD wFatDate, WORD wFatTime, - NOTIFYPROC callback); - -extern BOOL -ensure_directory (char *pathname, char *new_part, - NOTIFYPROC callback); - -/* codes for NOITIFYPROC */ -#define DIR_CREATED 1 -#define CAN_OVERWRITE 2 -#define FILE_CREATED 3 -#define ZLIB_ERROR 4 -#define SYSTEM_ERROR 5 -#define NUM_FILES 6 -#define FILE_OVERWRITTEN 7 - diff --git a/PC/bdist_wininst/bdist_wininst.vcxproj b/PC/bdist_wininst/bdist_wininst.vcxproj deleted file mode 100644 index 390bf4e627..0000000000 --- a/PC/bdist_wininst/bdist_wininst.vcxproj +++ /dev/null @@ -1,125 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|ARM"> - <Configuration>Debug</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="PGInstrument|ARM"> - <Configuration>PGInstrument</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="PGInstrument|Win32"> - <Configuration>PGInstrument</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="PGInstrument|x64"> - <Configuration>PGInstrument</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="PGUpdate|ARM"> - <Configuration>PGUpdate</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="PGUpdate|Win32"> - <Configuration>PGUpdate</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="PGUpdate|x64"> - <Configuration>PGUpdate</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|ARM"> - <Configuration>Release</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}</ProjectGuid> - <RootNamespace>wininst</RootNamespace> - <SupportPGO>false</SupportPGO> - </PropertyGroup> - <Import Project="..\..\PCbuild\python.props" /> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseOfMfc>false</UseOfMfc> - <CharacterSet>NotSet</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - <Import Project="..\..\PCbuild\pyproject.props" /> - </ImportGroup> - <PropertyGroup> - <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> - <OutDir>$(PySourcePath)lib\distutils\command\</OutDir> - <LinkIncremental>false</LinkIncremental> - <TargetName>wininst-$(VisualStudioVersion)</TargetName> - <TargetName Condition="$(PlatformToolset) == 'v140'">wininst-14.0</TargetName> - <TargetName Condition="$(PlatformToolset) == 'v120'">wininst-12.0</TargetName> - <TargetName Condition="$(PlatformToolset) == 'v110'">wininst-11.0</TargetName> - <TargetName Condition="$(PlatformToolset) == 'v100'">wininst-10.0</TargetName> - <TargetName Condition="$(Platform) == 'x64'">$(TargetName)-amd64</TargetName> - <TargetExt>.exe</TargetExt> - </PropertyGroup> - <ItemDefinitionGroup> - <Midl> - <TypeLibraryName>$(OutDir)wininst.tlb</TypeLibraryName> - </Midl> - <ClCompile> - <Optimization>MinSpace</Optimization> - <AdditionalIncludeDirectories>$(zlibDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary Condition="'$(Configuration)'=='Debug'">MultiThreadedDebug</RuntimeLibrary> - <RuntimeLibrary Condition="'$(Configuration)'=='Release'">MultiThreaded</RuntimeLibrary> - </ClCompile> - <ResourceCompile> - <AdditionalIncludeDirectories>$(PySourcePath)PC\bdist_wininst;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>comctl32.lib;imagehlp.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="extract.c" /> - <ClCompile Include="install.c" /> - <ClCompile Include="$(zlibDir)\adler32.c" /> - <ClCompile Include="$(zlibDir)\crc32.c" /> - <ClCompile Include="$(zlibDir)\inffast.c" /> - <ClCompile Include="$(zlibDir)\inflate.c" /> - <ClCompile Include="$(zlibDir)\inftrees.c" /> - <ClCompile Include="$(zlibDir)\zutil.c" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="archive.h" /> - <ClInclude Include="$(zlibDir)\zlib.h" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="install.rc" /> - </ItemGroup> - <ItemGroup> - <None Include="PythonPowered.bmp" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project>
\ No newline at end of file diff --git a/PC/bdist_wininst/bdist_wininst.vcxproj.filters b/PC/bdist_wininst/bdist_wininst.vcxproj.filters deleted file mode 100644 index c97742e723..0000000000 --- a/PC/bdist_wininst/bdist_wininst.vcxproj.filters +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{293b1092-03ad-4b7c-acb9-c4ab62e52f55}</UniqueIdentifier> - <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions> - </Filter> - <Filter Include="Source Files\zlib"> - <UniqueIdentifier>{0edc0406-282f-4dbc-b60e-a867c34a2a31}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{ea0c0f0e-3b73-474e-a999-e9689d032ccc}</UniqueIdentifier> - <Extensions>h;hpp;hxx;hm;inl</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{0c77c1cf-3f87-4f87-bd86-b425211c2181}</UniqueIdentifier> - <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions> - </Filter> - <Filter Include="Header Files\zlib"> - <UniqueIdentifier>{d10220c7-69e3-47c5-8d82-c8e0d4d2ac88}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="extract.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="install.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="$(zlibDir)\adler32.c"> - <Filter>Source Files\zlib</Filter> - </ClCompile> - <ClCompile Include="$(zlibDir)\crc32.c"> - <Filter>Source Files\zlib</Filter> - </ClCompile> - <ClCompile Include="$(zlibDir)\inffast.c"> - <Filter>Source Files\zlib</Filter> - </ClCompile> - <ClCompile Include="$(zlibDir)\inflate.c"> - <Filter>Source Files\zlib</Filter> - </ClCompile> - <ClCompile Include="$(zlibDir)\inftrees.c"> - <Filter>Source Files\zlib</Filter> - </ClCompile> - <ClCompile Include="$(zlibDir)\zutil.c"> - <Filter>Source Files\zlib</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="install.rc"> - <Filter>Resource Files</Filter> - </ResourceCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="archive.h"> - <Filter>Header Files</Filter> - </ClInclude> - <ClInclude Include="$(zlibDir)\zlib.h"> - <Filter>Header Files\zlib</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <None Include="PythonPowered.bmp"> - <Filter>Resource Files</Filter> - </None> - </ItemGroup> -</Project>
\ No newline at end of file diff --git a/PC/bdist_wininst/build.bat b/PC/bdist_wininst/build.bat deleted file mode 100644 index 3ce46cfd38..0000000000 --- a/PC/bdist_wininst/build.bat +++ /dev/null @@ -1,19 +0,0 @@ -@echo off -setlocal - -set D=%~dp0 -set PCBUILD=%~dp0..\..\PCbuild\ - - -echo Building Lib\distutils\command\wininst-xx.0.exe - -call "%PCBUILD%find_msbuild.bat" %MSBUILD% -if ERRORLEVEL 1 (echo Cannot locate MSBuild.exe on PATH or as MSBUILD variable & exit /b 2) - -%MSBUILD% "%D%bdist_wininst.vcxproj" "/p:SolutionDir=%PCBUILD%\" /p:Configuration=Release /p:Platform=Win32 -if errorlevel 1 goto :eof - - -echo Building Lib\distutils\command\wininst-xx.0-amd64.exe - -%MSBUILD% "%D%bdist_wininst.vcxproj" "/p:SolutionDir=%PCBUILD%\" /p:Configuration=Release /p:Platform=x64 diff --git a/PC/bdist_wininst/extract.c b/PC/bdist_wininst/extract.c deleted file mode 100644 index 0249d9ff54..0000000000 --- a/PC/bdist_wininst/extract.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - IMPORTANT NOTE: IF THIS FILE IS CHANGED, PCBUILD\BDIST_WININST.VCXPROJ MUST - BE REBUILT AS WELL. - - IF CHANGES TO THIS FILE ARE CHECKED IN, THE RECOMPILED BINARIES MUST BE - CHECKED IN AS WELL! -*/ - -#include <windows.h> - -#include "zlib.h" - -#include <stdio.h> -#include <stdarg.h> - -#include "archive.h" - -/* Convert unix-path to dos-path */ -static void normpath(char *path) -{ - while (path && *path) { - if (*path == '/') - *path = '\\'; - ++path; - } -} - -BOOL ensure_directory(char *pathname, char *new_part, NOTIFYPROC notify) -{ - while (new_part && *new_part && (new_part = strchr(new_part, '\\'))) { - DWORD attr; - *new_part = '\0'; - attr = GetFileAttributes(pathname); - if (attr == -1) { - /* nothing found */ - if (!CreateDirectory(pathname, NULL) && notify) - notify(SYSTEM_ERROR, - "CreateDirectory (%s)", pathname); - else - notify(DIR_CREATED, pathname); - } - if (attr & FILE_ATTRIBUTE_DIRECTORY) { - ; - } else { - SetLastError(183); - if (notify) - notify(SYSTEM_ERROR, - "CreateDirectory (%s)", pathname); - } - *new_part = '\\'; - ++new_part; - } - return TRUE; -} - -/* XXX Should better explicitly specify - * uncomp_size and file_times instead of pfhdr! - */ -char *map_new_file(DWORD flags, char *filename, - char *pathname_part, int size, - WORD wFatDate, WORD wFatTime, - NOTIFYPROC notify) -{ - HANDLE hFile, hFileMapping; - char *dst; - FILETIME ft; - - try_again: - if (!flags) - flags = CREATE_NEW; - hFile = CreateFile(filename, - GENERIC_WRITE | GENERIC_READ, - 0, NULL, - flags, - FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - DWORD x = GetLastError(); - switch (x) { - case ERROR_FILE_EXISTS: - if (notify && notify(CAN_OVERWRITE, filename)) - hFile = CreateFile(filename, - GENERIC_WRITE|GENERIC_READ, - 0, NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - else { - if (notify) - notify(FILE_OVERWRITTEN, filename); - return NULL; - } - break; - case ERROR_PATH_NOT_FOUND: - if (ensure_directory(filename, pathname_part, notify)) - goto try_again; - else - return FALSE; - break; - default: - SetLastError(x); - break; - } - } - if (hFile == INVALID_HANDLE_VALUE) { - if (notify) - notify (SYSTEM_ERROR, "CreateFile (%s)", filename); - return NULL; - } - - if (notify) - notify(FILE_CREATED, filename); - - DosDateTimeToFileTime(wFatDate, wFatTime, &ft); - SetFileTime(hFile, &ft, &ft, &ft); - - - if (size == 0) { - /* We cannot map a zero-length file (Also it makes - no sense */ - CloseHandle(hFile); - return NULL; - } - - hFileMapping = CreateFileMapping(hFile, - NULL, PAGE_READWRITE, 0, size, NULL); - - CloseHandle(hFile); - - if (hFileMapping == NULL) { - if (notify) - notify(SYSTEM_ERROR, - "CreateFileMapping (%s)", filename); - return NULL; - } - - dst = MapViewOfFile(hFileMapping, - FILE_MAP_WRITE, 0, 0, 0); - - CloseHandle(hFileMapping); - - if (!dst) { - if (notify) - notify(SYSTEM_ERROR, "MapViewOfFile (%s)", filename); - return NULL; - } - return dst; -} - - -BOOL -extract_file(char *dst, char *src, int method, int comp_size, - int uncomp_size, NOTIFYPROC notify) -{ - z_stream zstream; - int result; - - if (method == Z_DEFLATED) { - int x; - memset(&zstream, 0, sizeof(zstream)); - zstream.next_in = src; - zstream.avail_in = comp_size+1; - zstream.next_out = dst; - zstream.avail_out = uncomp_size; - -/* Apparently an undocumented feature of zlib: Set windowsize - to negative values to suppress the gzip header and be compatible with - zip! */ - result = TRUE; - if (Z_OK != (x = inflateInit2(&zstream, -15))) { - if (notify) - notify(ZLIB_ERROR, - "inflateInit2 returns %d", x); - result = FALSE; - goto cleanup; - } - if (Z_STREAM_END != (x = inflate(&zstream, Z_FINISH))) { - if (notify) - notify(ZLIB_ERROR, - "inflate returns %d", x); - result = FALSE; - } - cleanup: - if (Z_OK != (x = inflateEnd(&zstream))) { - if (notify) - notify (ZLIB_ERROR, - "inflateEnd returns %d", x); - result = FALSE; - } - } else if (method == 0) { - memcpy(dst, src, uncomp_size); - result = TRUE; - } else - result = FALSE; - UnmapViewOfFile(dst); - return result; -} - -/* Open a zip-compatible archive and extract all files - * into the specified directory (which is assumed to exist) - */ -BOOL -unzip_archive(SCHEME *scheme, char *dirname, char *data, DWORD size, - NOTIFYPROC notify) -{ - int n; - char pathname[MAX_PATH]; - char *new_part; - - /* read the end of central directory record */ - struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof - (struct eof_cdir)]; - - int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir - - pe->ofsCDir; - - /* set position to start of central directory */ - int pos = arc_start + pe->ofsCDir; - - /* make sure this is a zip file */ - if (pe->tag != 0x06054b50) - return FALSE; - - /* Loop through the central directory, reading all entries */ - for (n = 0; n < pe->nTotalCDir; ++n) { - int i; - char *fname; - char *pcomp; - char *dst; - struct cdir *pcdir; - struct fhdr *pfhdr; - - pcdir = (struct cdir *)&data[pos]; - pfhdr = (struct fhdr *)&data[pcdir->ofs_local_header + - arc_start]; - - if (pcdir->tag != 0x02014b50) - return FALSE; - if (pfhdr->tag != 0x04034b50) - return FALSE; - pos += sizeof(struct cdir); - fname = (char *)&data[pos]; /* This is not null terminated! */ - pos += pcdir->fname_length + pcdir->extra_length + - pcdir->comment_length; - - pcomp = &data[pcdir->ofs_local_header - + sizeof(struct fhdr) - + arc_start - + pfhdr->fname_length - + pfhdr->extra_length]; - - /* dirname is the Python home directory (prefix) */ - strcpy(pathname, dirname); - if (pathname[strlen(pathname)-1] != '\\') - strcat(pathname, "\\"); - new_part = &pathname[lstrlen(pathname)]; - /* we must now match the first part of the pathname - * in the archive to a component in the installation - * scheme (PURELIB, PLATLIB, HEADERS, SCRIPTS, or DATA) - * and replace this part by the one in the scheme to use - */ - for (i = 0; scheme[i].name; ++i) { - if (0 == strnicmp(scheme[i].name, fname, - strlen(scheme[i].name))) { - char *rest; - int len; - - /* length of the replaced part */ - int namelen = strlen(scheme[i].name); - - strcat(pathname, scheme[i].prefix); - - rest = fname + namelen; - len = pfhdr->fname_length - namelen; - - if ((pathname[strlen(pathname)-1] != '\\') - && (pathname[strlen(pathname)-1] != '/')) - strcat(pathname, "\\"); - /* Now that pathname ends with a separator, - * we must make sure rest does not start with - * an additional one. - */ - if ((rest[0] == '\\') || (rest[0] == '/')) { - ++rest; - --len; - } - - strncat(pathname, rest, len); - goto Done; - } - } - /* no prefix to replace found, go unchanged */ - strncat(pathname, fname, pfhdr->fname_length); - Done: - normpath(pathname); - if (pathname[strlen(pathname)-1] != '\\') { - /* - * The local file header (pfhdr) does not always - * contain the compressed and uncompressed sizes of - * the data depending on bit 3 of the flags field. So - * it seems better to use the data from the central - * directory (pcdir). - */ - dst = map_new_file(0, pathname, new_part, - pcdir->uncomp_size, - pcdir->last_mod_file_date, - pcdir->last_mod_file_time, notify); - if (dst) { - if (!extract_file(dst, pcomp, pfhdr->method, - pcdir->comp_size, - pcdir->uncomp_size, - notify)) - return FALSE; - } /* else ??? */ - } - if (notify) - notify(NUM_FILES, new_part, (int)pe->nTotalCDir, - (int)n+1); - } - return TRUE; -} diff --git a/PC/bdist_wininst/install.c b/PC/bdist_wininst/install.c deleted file mode 100644 index 5d77542582..0000000000 --- a/PC/bdist_wininst/install.c +++ /dev/null @@ -1,2700 +0,0 @@ -/* - IMPORTANT NOTE: IF THIS FILE IS CHANGED, PCBUILD\BDIST_WININST.VCXPROJ MUST - BE REBUILT AS WELL. - - IF CHANGES TO THIS FILE ARE CHECKED IN, THE RECOMPILED BINARIES MUST BE - CHECKED IN AS WELL! -*/ - -/* - * Written by Thomas Heller, May 2000 - * - * $Id$ - */ - -/* - * Windows Installer program for distutils. - * - * (a kind of self-extracting zip-file) - * - * At runtime, the exefile has appended: - * - compressed setup-data in ini-format, containing the following sections: - * [metadata] - * author=Greg Ward - * author_email=gward@python.net - * description=Python Distribution Utilities - * licence=Python - * name=Distutils - * url=http://www.python.org/sigs/distutils-sig/ - * version=0.9pre - * - * [Setup] - * info= text to be displayed in the edit-box - * title= to be displayed by this program - * target_version = if present, python version required - * pyc_compile = if 0, do not compile py to pyc - * pyo_compile = if 0, do not compile py to pyo - * - * - a struct meta_data_hdr, describing the above - * - a zip-file, containing the modules to be installed. - * for the format see http://www.pkware.com/appnote.html - * - * What does this program do? - * - the setup-data is uncompressed and written to a temporary file. - * - setup-data is queried with GetPrivateProfile... calls - * - [metadata] - info is displayed in the dialog box - * - The registry is searched for installations of python - * - The user can select the python version to use. - * - The python-installation directory (sys.prefix) is displayed - * - When the start-button is pressed, files from the zip-archive - * are extracted to the file system. All .py filenames are stored - * in a list. - */ -/* - * Includes now an uninstaller. - */ - -/* - * To Do: - * - * display some explanation when no python version is found - * instead showing the user an empty listbox to select something from. - * - * Finish the code so that we can use other python installations - * additionally to those found in the registry, - * and then #define USE_OTHER_PYTHON_VERSIONS - * - * - install a help-button, which will display something meaningful - * to the poor user. - * text to the user - * - should there be a possibility to display a README file - * before starting the installation (if one is present in the archive) - * - more comments about what the code does(?) - * - * - evolve this into a full blown installer (???) - */ - -#include <windows.h> -#include <commctrl.h> -#include <imagehlp.h> -#include <objbase.h> -#include <shlobj.h> -#include <objidl.h> -#include "resource.h" - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <malloc.h> -#include <io.h> -#include <fcntl.h> - -#include "archive.h" - -/* Only for debugging! - static int dprintf(char *fmt, ...) - { - char Buffer[4096]; - va_list marker; - int result; - - va_start(marker, fmt); - result = wvsprintf(Buffer, fmt, marker); - OutputDebugString(Buffer); - return result; - } -*/ - -/* Bah: global variables */ -FILE *logfile; - -char modulename[MAX_PATH]; -wchar_t wmodulename[MAX_PATH]; - -HWND hwndMain; -HWND hDialog; - -char *ini_file; /* Full pathname of ini-file */ -/* From ini-file */ -char info[4096]; /* [Setup] info= */ -char title[80]; /* [Setup] title=, contains package name - including version: "Distutils-1.0.1" */ -char target_version[10]; /* [Setup] target_version=, required python - version or empty string */ -char build_info[80]; /* [Setup] build_info=, distutils version - and build date */ - -char meta_name[80]; /* package name without version like - 'Distutils' */ -char install_script[MAX_PATH]; -char *pre_install_script; /* run before we install a single file */ - -char user_access_control[10]; // one of 'auto', 'force', otherwise none. - -int py_major, py_minor; /* Python version selected for installation */ - -char *arc_data; /* memory mapped archive */ -DWORD arc_size; /* number of bytes in archive */ -int exe_size; /* number of bytes for exe-file portion */ -char python_dir[MAX_PATH]; -char pythondll[MAX_PATH]; -BOOL pyc_compile, pyo_compile; -/* Either HKLM or HKCU, depending on where Python itself is registered, and - the permissions of the current user. */ -HKEY hkey_root = (HKEY)-1; - -BOOL success; /* Installation successful? */ -char *failure_reason = NULL; - -HANDLE hBitmap; -char *bitmap_bytes; - -static const char *REGISTRY_SUFFIX_6432 = -#ifdef _WIN64 - ""; -#else - "-32"; -#endif - - -#define WM_NUMFILES WM_USER+1 -/* wParam: 0, lParam: total number of files */ -#define WM_NEXTFILE WM_USER+2 -/* wParam: number of this file */ -/* lParam: points to pathname */ - -static BOOL notify(int code, char *fmt, ...); - -/* Note: If scheme.prefix is nonempty, it must end with a '\'! */ -/* Note: purelib must be the FIRST entry! */ -SCHEME old_scheme[] = { - { "PURELIB", "" }, - { "PLATLIB", "" }, - { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */ - { "SCRIPTS", "Scripts\\" }, - { "DATA", "" }, - { NULL, NULL }, -}; - -SCHEME new_scheme[] = { - { "PURELIB", "Lib\\site-packages\\" }, - { "PLATLIB", "Lib\\site-packages\\" }, - { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */ - { "SCRIPTS", "Scripts\\" }, - { "DATA", "" }, - { NULL, NULL }, -}; - -static void unescape(char *dst, char *src, unsigned size) -{ - char *eon; - char ch; - - while (src && *src && (size > 2)) { - if (*src == '\\') { - switch (*++src) { - case 'n': - ++src; - *dst++ = '\r'; - *dst++ = '\n'; - size -= 2; - break; - case 'r': - ++src; - *dst++ = '\r'; - --size; - break; - case '0': case '1': case '2': case '3': - ch = (char)strtol(src, &eon, 8); - if (ch == '\n') { - *dst++ = '\r'; - --size; - } - *dst++ = ch; - --size; - src = eon; - } - } else { - *dst++ = *src++; - --size; - } - } - *dst = '\0'; -} - -static struct tagFile { - char *path; - struct tagFile *next; -} *file_list = NULL; - -static void set_failure_reason(char *reason) -{ - if (failure_reason) - free(failure_reason); - failure_reason = strdup(reason); - success = FALSE; -} -static char *get_failure_reason() -{ - if (!failure_reason) - return "Installation failed."; - return failure_reason; -} - -static void add_to_filelist(char *path) -{ - struct tagFile *p; - p = (struct tagFile *)malloc(sizeof(struct tagFile)); - p->path = strdup(path); - p->next = file_list; - file_list = p; -} - -static int do_compile_files(int (__cdecl * PyRun_SimpleString)(char *), - int optimize) -{ - struct tagFile *p; - int total, n; - char Buffer[MAX_PATH + 64]; - int errors = 0; - - total = 0; - p = file_list; - while (p) { - ++total; - p = p->next; - } - SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETRANGE, 0, - MAKELPARAM(0, total)); - SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, 0, 0); - - n = 0; - p = file_list; - while (p) { - ++n; - wsprintf(Buffer, - "import py_compile; py_compile.compile (r'%s')", - p->path); - if (PyRun_SimpleString(Buffer)) { - ++errors; - } - /* We send the notification even if the files could not - * be created so that the uninstaller will remove them - * in case they are created later. - */ - wsprintf(Buffer, "%s%c", p->path, optimize ? 'o' : 'c'); - notify(FILE_CREATED, Buffer); - - SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, n, 0); - SetDlgItemText(hDialog, IDC_INFO, p->path); - p = p->next; - } - return errors; -} - -#define DECLPROC(dll, result, name, args)\ - typedef result (*__PROC__##name) args;\ - result (*name)args = (__PROC__##name)GetProcAddress(dll, #name) - - -#define DECLVAR(dll, type, name)\ - type *name = (type*)GetProcAddress(dll, #name) - -typedef void PyObject; - -// Convert a "char *" string to "whcar_t *", or NULL on error. -// Result string must be free'd -wchar_t *widen_string(char *src) -{ - wchar_t *result; - DWORD dest_cch; - int src_len = strlen(src) + 1; // include NULL term in all ops - /* use MultiByteToWideChar() to see how much we need. */ - /* NOTE: this will include the null-term in the length */ - dest_cch = MultiByteToWideChar(CP_ACP, 0, src, src_len, NULL, 0); - // alloc the buffer - result = (wchar_t *)malloc(dest_cch * sizeof(wchar_t)); - if (result==NULL) - return NULL; - /* do the conversion */ - if (0==MultiByteToWideChar(CP_ACP, 0, src, src_len, result, dest_cch)) { - free(result); - return NULL; - } - return result; -} - -/* - * Returns number of files which failed to compile, - * -1 if python could not be loaded at all - */ -static int compile_filelist(HINSTANCE hPython, BOOL optimize_flag) -{ - DECLPROC(hPython, void, Py_Initialize, (void)); - DECLPROC(hPython, void, Py_SetProgramName, (wchar_t *)); - DECLPROC(hPython, void, Py_Finalize, (void)); - DECLPROC(hPython, int, PyRun_SimpleString, (char *)); - DECLPROC(hPython, PyObject *, PySys_GetObject, (char *)); - DECLVAR(hPython, int, Py_OptimizeFlag); - - int errors = 0; - struct tagFile *p = file_list; - - if (!p) - return 0; - - if (!Py_Initialize || !Py_SetProgramName || !Py_Finalize) - return -1; - - if (!PyRun_SimpleString || !PySys_GetObject || !Py_OptimizeFlag) - return -1; - - *Py_OptimizeFlag = optimize_flag ? 1 : 0; - Py_SetProgramName(wmodulename); - Py_Initialize(); - - errors += do_compile_files(PyRun_SimpleString, optimize_flag); - Py_Finalize(); - - return errors; -} - -typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); - -struct PyMethodDef { - char *ml_name; - PyCFunction ml_meth; - int ml_flags; - char *ml_doc; -}; -typedef struct PyMethodDef PyMethodDef; - -// XXX - all of these are potentially fragile! We load and unload -// the Python DLL multiple times - so storing functions pointers -// is dangerous (although things *look* OK at present) -// Better might be to roll prepare_script_environment() into -// LoadPythonDll(), and create a new UnloadPythonDLL() which also -// clears the global pointers. -void *(*g_Py_BuildValue)(char *, ...); -int (*g_PyArg_ParseTuple)(PyObject *, char *, ...); -PyObject * (*g_PyLong_FromVoidPtr)(void *); - -PyObject *g_PyExc_ValueError; -PyObject *g_PyExc_OSError; - -PyObject *(*g_PyErr_Format)(PyObject *, char *, ...); - -#define DEF_CSIDL(name) { name, #name } - -struct { - int nFolder; - char *name; -} csidl_names[] = { - /* Startup menu for all users. - NT only */ - DEF_CSIDL(CSIDL_COMMON_STARTMENU), - /* Startup menu. */ - DEF_CSIDL(CSIDL_STARTMENU), - -/* DEF_CSIDL(CSIDL_COMMON_APPDATA), */ -/* DEF_CSIDL(CSIDL_LOCAL_APPDATA), */ - /* Repository for application-specific data. - Needs Internet Explorer 4.0 */ - DEF_CSIDL(CSIDL_APPDATA), - - /* The desktop for all users. - NT only */ - DEF_CSIDL(CSIDL_COMMON_DESKTOPDIRECTORY), - /* The desktop. */ - DEF_CSIDL(CSIDL_DESKTOPDIRECTORY), - - /* Startup folder for all users. - NT only */ - DEF_CSIDL(CSIDL_COMMON_STARTUP), - /* Startup folder. */ - DEF_CSIDL(CSIDL_STARTUP), - - /* Programs item in the start menu for all users. - NT only */ - DEF_CSIDL(CSIDL_COMMON_PROGRAMS), - /* Program item in the user's start menu. */ - DEF_CSIDL(CSIDL_PROGRAMS), - -/* DEF_CSIDL(CSIDL_PROGRAM_FILES_COMMON), */ -/* DEF_CSIDL(CSIDL_PROGRAM_FILES), */ - - /* Virtual folder containing fonts. */ - DEF_CSIDL(CSIDL_FONTS), -}; - -#define DIM(a) (sizeof(a) / sizeof((a)[0])) - -static PyObject *FileCreated(PyObject *self, PyObject *args) -{ - char *path; - if (!g_PyArg_ParseTuple(args, "s", &path)) - return NULL; - notify(FILE_CREATED, path); - return g_Py_BuildValue(""); -} - -static PyObject *DirectoryCreated(PyObject *self, PyObject *args) -{ - char *path; - if (!g_PyArg_ParseTuple(args, "s", &path)) - return NULL; - notify(DIR_CREATED, path); - return g_Py_BuildValue(""); -} - -static PyObject *GetSpecialFolderPath(PyObject *self, PyObject *args) -{ - char *name; - char lpszPath[MAX_PATH]; - int i; - static HRESULT (WINAPI *My_SHGetSpecialFolderPath)(HWND hwnd, - LPTSTR lpszPath, - int nFolder, - BOOL fCreate); - - if (!My_SHGetSpecialFolderPath) { - HINSTANCE hLib = LoadLibrary("shell32.dll"); - if (!hLib) { - g_PyErr_Format(g_PyExc_OSError, - "function not available"); - return NULL; - } - My_SHGetSpecialFolderPath = (BOOL (WINAPI *)(HWND, LPTSTR, - int, BOOL)) - GetProcAddress(hLib, - "SHGetSpecialFolderPathA"); - } - - if (!g_PyArg_ParseTuple(args, "s", &name)) - return NULL; - - if (!My_SHGetSpecialFolderPath) { - g_PyErr_Format(g_PyExc_OSError, "function not available"); - return NULL; - } - - for (i = 0; i < DIM(csidl_names); ++i) { - if (0 == strcmpi(csidl_names[i].name, name)) { - int nFolder; - nFolder = csidl_names[i].nFolder; - if (My_SHGetSpecialFolderPath(NULL, lpszPath, - nFolder, 0)) - return g_Py_BuildValue("s", lpszPath); - else { - g_PyErr_Format(g_PyExc_OSError, - "no such folder (%s)", name); - return NULL; - } - - } - }; - g_PyErr_Format(g_PyExc_ValueError, "unknown CSIDL (%s)", name); - return NULL; -} - -static PyObject *CreateShortcut(PyObject *self, PyObject *args) -{ - char *path; /* path and filename */ - char *description; - char *filename; - - char *arguments = NULL; - char *iconpath = NULL; - int iconindex = 0; - char *workdir = NULL; - - WCHAR wszFilename[MAX_PATH]; - - IShellLink *ps1 = NULL; - IPersistFile *pPf = NULL; - - HRESULT hr; - - hr = CoInitialize(NULL); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "CoInitialize failed, error 0x%x", hr); - goto error; - } - - if (!g_PyArg_ParseTuple(args, "sss|sssi", - &path, &description, &filename, - &arguments, &workdir, &iconpath, &iconindex)) - return NULL; - - hr = CoCreateInstance(&CLSID_ShellLink, - NULL, - CLSCTX_INPROC_SERVER, - &IID_IShellLink, - &ps1); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "CoCreateInstance failed, error 0x%x", hr); - goto error; - } - - hr = ps1->lpVtbl->QueryInterface(ps1, &IID_IPersistFile, - (void **)&pPf); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "QueryInterface(IPersistFile) error 0x%x", hr); - goto error; - } - - - hr = ps1->lpVtbl->SetPath(ps1, path); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "SetPath() failed, error 0x%x", hr); - goto error; - } - - hr = ps1->lpVtbl->SetDescription(ps1, description); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "SetDescription() failed, error 0x%x", hr); - goto error; - } - - if (arguments) { - hr = ps1->lpVtbl->SetArguments(ps1, arguments); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "SetArguments() error 0x%x", hr); - goto error; - } - } - - if (iconpath) { - hr = ps1->lpVtbl->SetIconLocation(ps1, iconpath, iconindex); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "SetIconLocation() error 0x%x", hr); - goto error; - } - } - - if (workdir) { - hr = ps1->lpVtbl->SetWorkingDirectory(ps1, workdir); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "SetWorkingDirectory() error 0x%x", hr); - goto error; - } - } - - MultiByteToWideChar(CP_ACP, 0, - filename, -1, - wszFilename, MAX_PATH); - - hr = pPf->lpVtbl->Save(pPf, wszFilename, TRUE); - if (FAILED(hr)) { - g_PyErr_Format(g_PyExc_OSError, - "Failed to create shortcut '%s' - error 0x%x", filename, hr); - goto error; - } - - pPf->lpVtbl->Release(pPf); - ps1->lpVtbl->Release(ps1); - CoUninitialize(); - return g_Py_BuildValue(""); - - error: - if (pPf) - pPf->lpVtbl->Release(pPf); - - if (ps1) - ps1->lpVtbl->Release(ps1); - - CoUninitialize(); - - return NULL; -} - -static PyObject *PyMessageBox(PyObject *self, PyObject *args) -{ - int rc; - char *text, *caption; - int flags; - if (!g_PyArg_ParseTuple(args, "ssi", &text, &caption, &flags)) - return NULL; - rc = MessageBox(GetFocus(), text, caption, flags); - return g_Py_BuildValue("i", rc); -} - -static PyObject *GetRootHKey(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return g_PyLong_FromVoidPtr(hkey_root); -} - -#define METH_VARARGS 0x0001 -#define METH_NOARGS 0x0004 - -PyMethodDef meth[] = { - {"create_shortcut", CreateShortcut, METH_VARARGS, NULL}, - {"get_special_folder_path", GetSpecialFolderPath, METH_VARARGS, NULL}, - {"get_root_hkey", GetRootHKey, METH_NOARGS, NULL}, - {"file_created", FileCreated, METH_VARARGS, NULL}, - {"directory_created", DirectoryCreated, METH_VARARGS, NULL}, - {"message_box", PyMessageBox, METH_VARARGS, NULL}, -}; - -static HINSTANCE LoadPythonDll(char *fname) -{ - char fullpath[_MAX_PATH]; - LONG size = sizeof(fullpath); - char subkey_name[80]; - char buffer[260 + 12]; - HINSTANCE h; - - /* make sure PYTHONHOME is set, to that sys.path is initialized correctly */ - wsprintf(buffer, "PYTHONHOME=%s", python_dir); - _putenv(buffer); - h = LoadLibrary(fname); - if (h) - return h; - wsprintf(subkey_name, - "SOFTWARE\\Python\\PythonCore\\%d.%d%s\\InstallPath", - py_major, py_minor, REGISTRY_SUFFIX_6432); - if (ERROR_SUCCESS != RegQueryValue(HKEY_CURRENT_USER, subkey_name, - fullpath, &size) && - ERROR_SUCCESS != RegQueryValue(HKEY_LOCAL_MACHINE, subkey_name, - fullpath, &size)) - return NULL; - strcat(fullpath, "\\"); - strcat(fullpath, fname); - // We use LOAD_WITH_ALTERED_SEARCH_PATH to ensure any dependent DLLs - // next to the Python DLL (eg, the CRT DLL) are also loaded. - return LoadLibraryEx(fullpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); -} - -static int prepare_script_environment(HINSTANCE hPython) -{ - PyObject *mod; - DECLPROC(hPython, PyObject *, PyImport_ImportModule, (char *)); - DECLPROC(hPython, int, PyObject_SetAttrString, (PyObject *, char *, PyObject *)); - DECLPROC(hPython, PyObject *, PyObject_GetAttrString, (PyObject *, char *)); - DECLPROC(hPython, PyObject *, PyCFunction_New, (PyMethodDef *, PyObject *)); - DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...)); - DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...)); - DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *)); - DECLPROC(hPython, PyObject *, PyLong_FromVoidPtr, (void *)); - if (!PyImport_ImportModule || !PyObject_GetAttrString || - !PyObject_SetAttrString || !PyCFunction_New) - return 1; - if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format) - return 1; - - mod = PyImport_ImportModule("builtins"); - if (mod) { - int i; - g_PyExc_ValueError = PyObject_GetAttrString(mod, "ValueError"); - g_PyExc_OSError = PyObject_GetAttrString(mod, "OSError"); - for (i = 0; i < DIM(meth); ++i) { - PyObject_SetAttrString(mod, meth[i].ml_name, - PyCFunction_New(&meth[i], NULL)); - } - } - g_Py_BuildValue = Py_BuildValue; - g_PyArg_ParseTuple = PyArg_ParseTuple; - g_PyErr_Format = PyErr_Format; - g_PyLong_FromVoidPtr = PyLong_FromVoidPtr; - - return 0; -} - -/* - * This function returns one of the following error codes: - * 1 if the Python-dll does not export the functions we need - * 2 if no install-script is specified in pathname - * 3 if the install-script file could not be opened - * the return value of PyRun_SimpleString() or Py_FinalizeEx() otherwise, - * which is 0 if everything is ok, -1 if an exception had occurred - * in the install-script. - */ - -static int -do_run_installscript(HINSTANCE hPython, char *pathname, int argc, char **argv) -{ - int fh, result, i; - static wchar_t *wargv[256]; - DECLPROC(hPython, void, Py_Initialize, (void)); - DECLPROC(hPython, int, PySys_SetArgv, (int, wchar_t **)); - DECLPROC(hPython, int, PyRun_SimpleString, (char *)); - DECLPROC(hPython, int, Py_FinalizeEx, (void)); - DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...)); - DECLPROC(hPython, PyObject *, PyCFunction_New, - (PyMethodDef *, PyObject *)); - DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...)); - DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *)); - - if (!Py_Initialize || !PySys_SetArgv - || !PyRun_SimpleString || !Py_FinalizeEx) - return 1; - - if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format) - return 1; - - if (!PyCFunction_New || !PyArg_ParseTuple || !PyErr_Format) - return 1; - - if (pathname == NULL || pathname[0] == '\0') - return 2; - - fh = open(pathname, _O_RDONLY | O_NOINHERIT); - if (-1 == fh) { - fprintf(stderr, "Could not open postinstall-script %s\n", - pathname); - return 3; - } - - SetDlgItemText(hDialog, IDC_INFO, "Running Script..."); - - Py_Initialize(); - - prepare_script_environment(hPython); - // widen the argv array for py3k. - memset(wargv, 0, sizeof(wargv)); - for (i=0;i<argc;i++) - wargv[i] = argv[i] ? widen_string(argv[i]) : NULL; - PySys_SetArgv(argc, wargv); - // free the strings we just widened. - for (i=0;i<argc;i++) - if (wargv[i]) - free(wargv[i]); - - result = 3; - { - struct _stat statbuf; - if(0 == _fstat(fh, &statbuf)) { - char *script = alloca(statbuf.st_size + 5); - int n = read(fh, script, statbuf.st_size); - if (n > 0) { - script[n] = '\n'; - script[n+1] = 0; - result = PyRun_SimpleString(script); - } - } - } - if (Py_FinalizeEx() < 0) { - result = -1; - } - - close(fh); - return result; -} - -static int -run_installscript(char *pathname, int argc, char **argv, char **pOutput) -{ - HINSTANCE hPython; - int result = 1; - int out_buf_size; - HANDLE redirected, old_stderr, old_stdout; - char *tempname; - - *pOutput = NULL; - - tempname = tempnam(NULL, NULL); - // We use a static CRT while the Python version we load uses - // the CRT from one of various possible DLLs. As a result we - // need to redirect the standard handles using the API rather - // than the CRT. - redirected = CreateFile( - tempname, - GENERIC_WRITE | GENERIC_READ, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, - NULL); - old_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - old_stderr = GetStdHandle(STD_ERROR_HANDLE); - SetStdHandle(STD_OUTPUT_HANDLE, redirected); - SetStdHandle(STD_ERROR_HANDLE, redirected); - - hPython = LoadPythonDll(pythondll); - if (hPython) { - result = do_run_installscript(hPython, pathname, argc, argv); - FreeLibrary(hPython); - } else { - fprintf(stderr, "*** Could not load Python ***"); - } - SetStdHandle(STD_OUTPUT_HANDLE, old_stdout); - SetStdHandle(STD_ERROR_HANDLE, old_stderr); - out_buf_size = min(GetFileSize(redirected, NULL), 4096); - *pOutput = malloc(out_buf_size+1); - if (*pOutput) { - DWORD nread = 0; - SetFilePointer(redirected, 0, 0, FILE_BEGIN); - ReadFile(redirected, *pOutput, out_buf_size, &nread, NULL); - (*pOutput)[nread] = '\0'; - } - CloseHandle(redirected); - DeleteFile(tempname); - return result; -} - -static int do_run_simple_script(HINSTANCE hPython, char *script) -{ - int rc; - DECLPROC(hPython, void, Py_Initialize, (void)); - DECLPROC(hPython, void, Py_SetProgramName, (wchar_t *)); - DECLPROC(hPython, int, Py_FinalizeEx, (void)); - DECLPROC(hPython, int, PyRun_SimpleString, (char *)); - DECLPROC(hPython, void, PyErr_Print, (void)); - - if (!Py_Initialize || !Py_SetProgramName || !Py_FinalizeEx || - !PyRun_SimpleString || !PyErr_Print) - return -1; - - Py_SetProgramName(wmodulename); - Py_Initialize(); - prepare_script_environment(hPython); - rc = PyRun_SimpleString(script); - if (rc) - PyErr_Print(); - if (Py_FinalizeEx() < 0) { - rc = -1; - } - return rc; -} - -static int run_simple_script(char *script) -{ - int rc; - HINSTANCE hPython; - char *tempname = tempnam(NULL, NULL); - // Redirect output using win32 API - see comments above... - HANDLE redirected = CreateFile( - tempname, - GENERIC_WRITE | GENERIC_READ, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, - NULL); - HANDLE old_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - HANDLE old_stderr = GetStdHandle(STD_ERROR_HANDLE); - SetStdHandle(STD_OUTPUT_HANDLE, redirected); - SetStdHandle(STD_ERROR_HANDLE, redirected); - - hPython = LoadPythonDll(pythondll); - if (!hPython) { - char reason[128]; - wsprintf(reason, "Can't load Python for pre-install script (%d)", GetLastError()); - set_failure_reason(reason); - return -1; - } - rc = do_run_simple_script(hPython, script); - FreeLibrary(hPython); - SetStdHandle(STD_OUTPUT_HANDLE, old_stdout); - SetStdHandle(STD_ERROR_HANDLE, old_stderr); - /* We only care about the output when we fail. If the script works - OK, then we discard it - */ - if (rc) { - int err_buf_size; - char *err_buf; - const char *prefix = "Running the pre-installation script failed\r\n"; - int prefix_len = strlen(prefix); - err_buf_size = GetFileSize(redirected, NULL); - if (err_buf_size==INVALID_FILE_SIZE) // an error - let's try anyway... - err_buf_size = 4096; - err_buf = malloc(prefix_len + err_buf_size + 1); - if (err_buf) { - DWORD n = 0; - strcpy(err_buf, prefix); - SetFilePointer(redirected, 0, 0, FILE_BEGIN); - ReadFile(redirected, err_buf+prefix_len, err_buf_size, &n, NULL); - err_buf[prefix_len+n] = '\0'; - set_failure_reason(err_buf); - free(err_buf); - } else { - set_failure_reason("Out of memory!"); - } - } - CloseHandle(redirected); - DeleteFile(tempname); - return rc; -} - - -static BOOL SystemError(int error, char *msg) -{ - char Buffer[1024]; - int n; - - if (error) { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&lpMsgBuf, - 0, - NULL - ); - strncpy(Buffer, lpMsgBuf, sizeof(Buffer)); - LocalFree(lpMsgBuf); - } else - Buffer[0] = '\0'; - n = lstrlen(Buffer); - _snprintf(Buffer+n, sizeof(Buffer)-n, msg); - MessageBox(hwndMain, Buffer, "Runtime Error", MB_OK | MB_ICONSTOP); - return FALSE; -} - -static BOOL notify (int code, char *fmt, ...) -{ - char Buffer[1024]; - va_list marker; - BOOL result = TRUE; - int a, b; - char *cp; - - va_start(marker, fmt); - _vsnprintf(Buffer, sizeof(Buffer), fmt, marker); - - switch (code) { -/* Questions */ - case CAN_OVERWRITE: - break; - -/* Information notification */ - case DIR_CREATED: - if (logfile) - fprintf(logfile, "100 Made Dir: %s\n", fmt); - break; - - case FILE_CREATED: - if (logfile) - fprintf(logfile, "200 File Copy: %s\n", fmt); - goto add_to_filelist_label; - break; - - case FILE_OVERWRITTEN: - if (logfile) - fprintf(logfile, "200 File Overwrite: %s\n", fmt); - add_to_filelist_label: - if ((cp = strrchr(fmt, '.')) && (0 == strcmp (cp, ".py"))) - add_to_filelist(fmt); - break; - -/* Error Messages */ - case ZLIB_ERROR: - MessageBox(GetFocus(), Buffer, "Error", - MB_OK | MB_ICONWARNING); - break; - - case SYSTEM_ERROR: - SystemError(GetLastError(), Buffer); - break; - - case NUM_FILES: - a = va_arg(marker, int); - b = va_arg(marker, int); - SendMessage(hDialog, WM_NUMFILES, 0, MAKELPARAM(0, a)); - SendMessage(hDialog, WM_NEXTFILE, b,(LPARAM)fmt); - } - va_end(marker); - - return result; -} - -static char *MapExistingFile(char *pathname, DWORD *psize) -{ - HANDLE hFile, hFileMapping; - DWORD nSizeLow, nSizeHigh; - char *data; - - hFile = CreateFile(pathname, - GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return NULL; - nSizeLow = GetFileSize(hFile, &nSizeHigh); - hFileMapping = CreateFileMapping(hFile, - NULL, PAGE_READONLY, 0, 0, NULL); - CloseHandle(hFile); - - if (hFileMapping == NULL) - return NULL; - - data = MapViewOfFile(hFileMapping, - FILE_MAP_READ, 0, 0, 0); - - CloseHandle(hFileMapping); - *psize = nSizeLow; - return data; -} - - -static void create_bitmap(HWND hwnd) -{ - BITMAPFILEHEADER *bfh; - BITMAPINFO *bi; - HDC hdc; - - if (!bitmap_bytes) - return; - - if (hBitmap) - return; - - hdc = GetDC(hwnd); - - bfh = (BITMAPFILEHEADER *)bitmap_bytes; - bi = (BITMAPINFO *)(bitmap_bytes + sizeof(BITMAPFILEHEADER)); - - hBitmap = CreateDIBitmap(hdc, - &bi->bmiHeader, - CBM_INIT, - bitmap_bytes + bfh->bfOffBits, - bi, - DIB_RGB_COLORS); - ReleaseDC(hwnd, hdc); -} - -/* Extract everything we need to begin the installation. Currently this - is the INI filename with install data, and the raw pre-install script -*/ -static BOOL ExtractInstallData(char *data, DWORD size, int *pexe_size, - char **out_ini_file, char **out_preinstall_script) -{ - /* read the end of central directory record */ - struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof - (struct eof_cdir)]; - - int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir - - pe->ofsCDir; - - int ofs = arc_start - sizeof (struct meta_data_hdr); - - /* read meta_data info */ - struct meta_data_hdr *pmd = (struct meta_data_hdr *)&data[ofs]; - char *src, *dst; - char *ini_file; - char tempdir[MAX_PATH]; - - /* ensure that if we fail, we don't have garbage out pointers */ - *out_ini_file = *out_preinstall_script = NULL; - - if (pe->tag != 0x06054b50) { - return FALSE; - } - - if (pmd->tag != 0x1234567B) { - return SystemError(0, - "Invalid cfgdata magic number (see bdist_wininst.py)"); - } - if (ofs < 0) { - return FALSE; - } - - if (pmd->bitmap_size) { - /* Store pointer to bitmap bytes */ - bitmap_bytes = (char *)pmd - pmd->uncomp_size - pmd->bitmap_size; - } - - *pexe_size = ofs - pmd->uncomp_size - pmd->bitmap_size; - - src = ((char *)pmd) - pmd->uncomp_size; - ini_file = malloc(MAX_PATH); /* will be returned, so do not free it */ - if (!ini_file) - return FALSE; - if (!GetTempPath(sizeof(tempdir), tempdir) - || !GetTempFileName(tempdir, "~du", 0, ini_file)) { - SystemError(GetLastError(), - "Could not create temporary file"); - return FALSE; - } - - dst = map_new_file(CREATE_ALWAYS, ini_file, NULL, pmd->uncomp_size, - 0, 0, NULL/*notify*/); - if (!dst) - return FALSE; - /* Up to the first \0 is the INI file data. */ - strncpy(dst, src, pmd->uncomp_size); - src += strlen(dst) + 1; - /* Up to next \0 is the pre-install script */ - *out_preinstall_script = strdup(src); - *out_ini_file = ini_file; - UnmapViewOfFile(dst); - return TRUE; -} - -static void PumpMessages(void) -{ - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -LRESULT CALLBACK -WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HDC hdc; - HFONT hFont; - int h; - PAINTSTRUCT ps; - switch (msg) { - case WM_PAINT: - hdc = BeginPaint(hwnd, &ps); - h = GetSystemMetrics(SM_CYSCREEN) / 10; - hFont = CreateFont(h, 0, 0, 0, 700, TRUE, - 0, 0, 0, 0, 0, 0, 0, "Times Roman"); - hFont = SelectObject(hdc, hFont); - SetBkMode(hdc, TRANSPARENT); - TextOut(hdc, 15, 15, title, strlen(title)); - SetTextColor(hdc, RGB(255, 255, 255)); - TextOut(hdc, 10, 10, title, strlen(title)); - DeleteObject(SelectObject(hdc, hFont)); - EndPaint(hwnd, &ps); - return 0; - } - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -static HWND CreateBackground(char *title) -{ - WNDCLASS wc; - HWND hwnd; - char buffer[4096]; - - wc.style = CS_VREDRAW | CS_HREDRAW; - wc.lpfnWndProc = WindowProc; - wc.cbWndExtra = 0; - wc.cbClsExtra = 0; - wc.hInstance = GetModuleHandle(NULL); - wc.hIcon = NULL; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 128)); - wc.lpszMenuName = NULL; - wc.lpszClassName = "SetupWindowClass"; - - if (!RegisterClass(&wc)) - MessageBox(hwndMain, - "Could not register window class", - "Setup.exe", MB_OK); - - wsprintf(buffer, "Setup %s", title); - hwnd = CreateWindow("SetupWindowClass", - buffer, - 0, - 0, 0, - GetSystemMetrics(SM_CXFULLSCREEN), - GetSystemMetrics(SM_CYFULLSCREEN), - NULL, - NULL, - GetModuleHandle(NULL), - NULL); - ShowWindow(hwnd, SW_SHOWMAXIMIZED); - UpdateWindow(hwnd); - return hwnd; -} - -/* - * Center a window on the screen - */ -static void CenterWindow(HWND hwnd) -{ - RECT rc; - int w, h; - - GetWindowRect(hwnd, &rc); - w = GetSystemMetrics(SM_CXSCREEN); - h = GetSystemMetrics(SM_CYSCREEN); - MoveWindow(hwnd, - (w - (rc.right-rc.left))/2, - (h - (rc.bottom-rc.top))/2, - rc.right-rc.left, rc.bottom-rc.top, FALSE); -} - -#include <prsht.h> - -INT_PTR CALLBACK -IntroDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - LPNMHDR lpnm; - char Buffer[4096]; - - switch (msg) { - case WM_INITDIALOG: - create_bitmap(hwnd); - if(hBitmap) - SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, - IMAGE_BITMAP, (LPARAM)hBitmap); - CenterWindow(GetParent(hwnd)); - wsprintf(Buffer, - "This Wizard will install %s on your computer. " - "Click Next to continue " - "or Cancel to exit the Setup Wizard.", - meta_name); - SetDlgItemText(hwnd, IDC_TITLE, Buffer); - SetDlgItemText(hwnd, IDC_INTRO_TEXT, info); - SetDlgItemText(hwnd, IDC_BUILD_INFO, build_info); - return FALSE; - - case WM_NOTIFY: - lpnm = (LPNMHDR) lParam; - - switch (lpnm->code) { - case PSN_SETACTIVE: - PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT); - break; - - case PSN_WIZNEXT: - break; - - case PSN_RESET: - break; - - default: - break; - } - } - return FALSE; -} - -#ifdef USE_OTHER_PYTHON_VERSIONS -/* These are really private variables used to communicate - * between StatusRoutine and CheckPythonExe - */ -char bound_image_dll[_MAX_PATH]; -int bound_image_major; -int bound_image_minor; - -static BOOL __stdcall StatusRoutine(IMAGEHLP_STATUS_REASON reason, - PSTR ImageName, - PSTR DllName, - ULONG Va, - ULONG Parameter) -{ - char fname[_MAX_PATH]; - int int_version; - - switch(reason) { - case BindOutOfMemory: - case BindRvaToVaFailed: - case BindNoRoomInImage: - case BindImportProcedureFailed: - break; - - case BindImportProcedure: - case BindForwarder: - case BindForwarderNOT: - case BindImageModified: - case BindExpandFileHeaders: - case BindImageComplete: - case BindSymbolsNotUpdated: - case BindMismatchedSymbols: - case BindImportModuleFailed: - break; - - case BindImportModule: - if (1 == sscanf(DllName, "python%d", &int_version)) { - SearchPath(NULL, DllName, NULL, sizeof(fname), - fname, NULL); - strcpy(bound_image_dll, fname); - bound_image_major = int_version / 10; - bound_image_minor = int_version % 10; - OutputDebugString("BOUND "); - OutputDebugString(fname); - OutputDebugString("\n"); - } - break; - } - return TRUE; -} - -/* - */ -static LPSTR get_sys_prefix(LPSTR exe, LPSTR dll) -{ - void (__cdecl * Py_Initialize)(void); - void (__cdecl * Py_SetProgramName)(char *); - void (__cdecl * Py_Finalize)(void); - void* (__cdecl * PySys_GetObject)(char *); - void (__cdecl * PySys_SetArgv)(int, char **); - char* (__cdecl * Py_GetPrefix)(void); - char* (__cdecl * Py_GetPath)(void); - HINSTANCE hPython; - LPSTR prefix = NULL; - int (__cdecl * PyRun_SimpleString)(char *); - - { - char Buffer[256]; - wsprintf(Buffer, "PYTHONHOME=%s", exe); - *strrchr(Buffer, '\\') = '\0'; -// MessageBox(GetFocus(), Buffer, "PYTHONHOME", MB_OK); - _putenv(Buffer); - _putenv("PYTHONPATH="); - } - - hPython = LoadLibrary(dll); - if (!hPython) - return NULL; - Py_Initialize = (void (*)(void))GetProcAddress - (hPython,"Py_Initialize"); - - PySys_SetArgv = (void (*)(int, char **))GetProcAddress - (hPython,"PySys_SetArgv"); - - PyRun_SimpleString = (int (*)(char *))GetProcAddress - (hPython,"PyRun_SimpleString"); - - Py_SetProgramName = (void (*)(char *))GetProcAddress - (hPython,"Py_SetProgramName"); - - PySys_GetObject = (void* (*)(char *))GetProcAddress - (hPython,"PySys_GetObject"); - - Py_GetPrefix = (char * (*)(void))GetProcAddress - (hPython,"Py_GetPrefix"); - - Py_GetPath = (char * (*)(void))GetProcAddress - (hPython,"Py_GetPath"); - - Py_Finalize = (void (*)(void))GetProcAddress(hPython, - "Py_Finalize"); - Py_SetProgramName(exe); - Py_Initialize(); - PySys_SetArgv(1, &exe); - - MessageBox(GetFocus(), Py_GetPrefix(), "PREFIX", MB_OK); - MessageBox(GetFocus(), Py_GetPath(), "PATH", MB_OK); - - Py_Finalize(); - FreeLibrary(hPython); - - return prefix; -} - -static BOOL -CheckPythonExe(LPSTR pathname, LPSTR version, int *pmajor, int *pminor) -{ - bound_image_dll[0] = '\0'; - if (!BindImageEx(BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE | BIND_ALL_IMAGES, - pathname, - NULL, - NULL, - StatusRoutine)) - return SystemError(0, "Could not bind image"); - if (bound_image_dll[0] == '\0') - return SystemError(0, "Does not seem to be a python executable"); - *pmajor = bound_image_major; - *pminor = bound_image_minor; - if (version && *version) { - char core_version[12]; - wsprintf(core_version, "%d.%d", bound_image_major, bound_image_minor); - if (strcmp(version, core_version)) - return SystemError(0, "Wrong Python version"); - } - get_sys_prefix(pathname, bound_image_dll); - return TRUE; -} - -/* - * Browse for other python versions. Insert it into the listbox specified - * by hwnd. version, if not NULL or empty, is the version required. - */ -static BOOL GetOtherPythonVersion(HWND hwnd, LPSTR version) -{ - char vers_name[_MAX_PATH + 80]; - DWORD itemindex; - OPENFILENAME of; - char pathname[_MAX_PATH]; - DWORD result; - - strcpy(pathname, "python.exe"); - - memset(&of, 0, sizeof(of)); - of.lStructSize = sizeof(OPENFILENAME); - of.hwndOwner = GetParent(hwnd); - of.hInstance = NULL; - of.lpstrFilter = "python.exe\0python.exe\0"; - of.lpstrCustomFilter = NULL; - of.nMaxCustFilter = 0; - of.nFilterIndex = 1; - of.lpstrFile = pathname; - of.nMaxFile = sizeof(pathname); - of.lpstrFileTitle = NULL; - of.nMaxFileTitle = 0; - of.lpstrInitialDir = NULL; - of.lpstrTitle = "Python executable"; - of.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; - of.lpstrDefExt = "exe"; - - result = GetOpenFileName(&of); - if (result) { - int major, minor; - if (!CheckPythonExe(pathname, version, &major, &minor)) { - return FALSE; - } - *strrchr(pathname, '\\') = '\0'; - wsprintf(vers_name, "Python Version %d.%d in %s", - major, minor, pathname); - itemindex = SendMessage(hwnd, LB_INSERTSTRING, -1, - (LPARAM)(LPSTR)vers_name); - SendMessage(hwnd, LB_SETCURSEL, itemindex, 0); - SendMessage(hwnd, LB_SETITEMDATA, itemindex, - (LPARAM)(LPSTR)strdup(pathname)); - return TRUE; - } - return FALSE; -} -#endif /* USE_OTHER_PYTHON_VERSIONS */ - -typedef struct _InstalledVersionInfo { - char prefix[MAX_PATH+1]; // sys.prefix directory. - HKEY hkey; // Is this Python in HKCU or HKLM? -} InstalledVersionInfo; - - -/* - * Fill the listbox specified by hwnd with all python versions found - * in the registry. version, if not NULL or empty, is the version - * required. - */ -static BOOL GetPythonVersions(HWND hwnd, HKEY hkRoot, LPSTR version) -{ - DWORD index = 0; - char core_version[80]; - HKEY hKey; - BOOL result = TRUE; - DWORD bufsize; - - if (ERROR_SUCCESS != RegOpenKeyEx(hkRoot, - "Software\\Python\\PythonCore", - 0, KEY_READ, &hKey)) - return FALSE; - bufsize = sizeof(core_version); - while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index, - core_version, &bufsize, NULL, - NULL, NULL, NULL)) { - char subkey_name[80], vers_name[80]; - int itemindex; - DWORD value_size; - HKEY hk; - - bufsize = sizeof(core_version); - ++index; - if (version && *version && strcmp(version, core_version)) - continue; - - wsprintf(vers_name, "Python Version %s (found in registry)", - core_version); - wsprintf(subkey_name, - "Software\\Python\\PythonCore\\%s\\InstallPath", - core_version); - if (ERROR_SUCCESS == RegOpenKeyEx(hkRoot, subkey_name, 0, KEY_READ, &hk)) { - InstalledVersionInfo *ivi = - (InstalledVersionInfo *)malloc(sizeof(InstalledVersionInfo)); - value_size = sizeof(ivi->prefix); - if (ivi && - ERROR_SUCCESS == RegQueryValueEx(hk, NULL, NULL, NULL, - ivi->prefix, &value_size)) { - itemindex = SendMessage(hwnd, LB_ADDSTRING, 0, - (LPARAM)(LPSTR)vers_name); - ivi->hkey = hkRoot; - SendMessage(hwnd, LB_SETITEMDATA, itemindex, - (LPARAM)(LPSTR)ivi); - } - RegCloseKey(hk); - } - } - RegCloseKey(hKey); - return result; -} - -/* Determine if the current user can write to HKEY_LOCAL_MACHINE */ -BOOL HasLocalMachinePrivs() -{ - HKEY hKey; - DWORD result; - static char KeyName[] = - "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; - - result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - KeyName, - 0, - KEY_CREATE_SUB_KEY, - &hKey); - if (result==0) - RegCloseKey(hKey); - return result==0; -} - -// Check the root registry key to use - either HKLM or HKCU. -// If Python is installed in HKCU, then our extension also must be installed -// in HKCU - as Python won't be available for other users, we shouldn't either -// (and will fail if we are!) -// If Python is installed in HKLM, then we will also prefer to use HKLM, but -// this may not be possible - so we silently fall back to HKCU. -// -// We assume hkey_root is already set to where Python itself is installed. -void CheckRootKey(HWND hwnd) -{ - if (hkey_root==HKEY_CURRENT_USER) { - ; // as above, always install ourself in HKCU too. - } else if (hkey_root==HKEY_LOCAL_MACHINE) { - // Python in HKLM, but we may or may not have permissions there. - // Open the uninstall key with 'create' permissions - if this fails, - // we don't have permission. - if (!HasLocalMachinePrivs()) - hkey_root = HKEY_CURRENT_USER; - } else { - MessageBox(hwnd, "Don't know Python's installation type", - "Strange", MB_OK | MB_ICONSTOP); - /* Default to wherever they can, but preferring HKLM */ - hkey_root = HasLocalMachinePrivs() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; - } -} - -/* Return the installation scheme depending on Python version number */ -SCHEME *GetScheme(int major, int minor) -{ - if (major > 2) - return new_scheme; - else if((major == 2) && (minor >= 2)) - return new_scheme; - return old_scheme; -} - -INT_PTR CALLBACK -SelectPythonDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - LPNMHDR lpnm; - - switch (msg) { - case WM_INITDIALOG: - if (hBitmap) - SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, - IMAGE_BITMAP, (LPARAM)hBitmap); - GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST), - HKEY_LOCAL_MACHINE, target_version); - GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST), - HKEY_CURRENT_USER, target_version); - { /* select the last entry which is the highest python - version found */ - int count; - count = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, - LB_GETCOUNT, 0, 0); - if (count && count != LB_ERR) - SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, LB_SETCURSEL, - count-1, 0); - - /* If a specific Python version is required, - * display a prominent notice showing this fact. - */ - if (target_version && target_version[0]) { - char buffer[4096]; - wsprintf(buffer, - "Python %s is required for this package. " - "Select installation to use:", - target_version); - SetDlgItemText(hwnd, IDC_TITLE, buffer); - } - - if (count == 0) { - char Buffer[4096]; - const char *msg; - if (target_version && target_version[0]) { - wsprintf(Buffer, - "Python version %s required, which was not found" - " in the registry.", target_version); - msg = Buffer; - } else - msg = "No Python installation found in the registry."; - MessageBox(hwnd, msg, "Cannot install", - MB_OK | MB_ICONSTOP); - } - } - goto UpdateInstallDir; - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) { -/* - case IDC_OTHERPYTHON: - if (GetOtherPythonVersion(GetDlgItem(hwnd, IDC_VERSIONS_LIST), - target_version)) - goto UpdateInstallDir; - break; -*/ - case IDC_VERSIONS_LIST: - switch (HIWORD(wParam)) { - int id; - case LBN_SELCHANGE: - UpdateInstallDir: - PropSheet_SetWizButtons(GetParent(hwnd), - PSWIZB_BACK | PSWIZB_NEXT); - id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, - LB_GETCURSEL, 0, 0); - if (id == LB_ERR) { - PropSheet_SetWizButtons(GetParent(hwnd), - PSWIZB_BACK); - SetDlgItemText(hwnd, IDC_PATH, ""); - SetDlgItemText(hwnd, IDC_INSTALL_PATH, ""); - strcpy(python_dir, ""); - strcpy(pythondll, ""); - } else { - char *pbuf; - int result; - InstalledVersionInfo *ivi; - PropSheet_SetWizButtons(GetParent(hwnd), - PSWIZB_BACK | PSWIZB_NEXT); - /* Get the python directory */ - ivi = (InstalledVersionInfo *) - SendDlgItemMessage(hwnd, - IDC_VERSIONS_LIST, - LB_GETITEMDATA, - id, - 0); - hkey_root = ivi->hkey; - strcpy(python_dir, ivi->prefix); - SetDlgItemText(hwnd, IDC_PATH, python_dir); - /* retrieve the python version and pythondll to use */ - result = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, - LB_GETTEXTLEN, (WPARAM)id, 0); - pbuf = (char *)malloc(result + 1); - if (pbuf) { - /* guess the name of the python-dll */ - SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, - LB_GETTEXT, (WPARAM)id, - (LPARAM)pbuf); - result = sscanf(pbuf, "Python Version %d.%d", - &py_major, &py_minor); - if (result == 2) { -#ifdef _DEBUG - wsprintf(pythondll, "python%d%d_d.dll", - py_major, py_minor); -#else - wsprintf(pythondll, "python%d%d.dll", - py_major, py_minor); -#endif - } - free(pbuf); - } else - strcpy(pythondll, ""); - /* retrieve the scheme for this version */ - { - char install_path[_MAX_PATH]; - SCHEME *scheme = GetScheme(py_major, py_minor); - strcpy(install_path, python_dir); - if (install_path[strlen(install_path)-1] != '\\') - strcat(install_path, "\\"); - strcat(install_path, scheme[0].prefix); - SetDlgItemText(hwnd, IDC_INSTALL_PATH, install_path); - } - } - } - break; - } - return 0; - - case WM_NOTIFY: - lpnm = (LPNMHDR) lParam; - - switch (lpnm->code) { - int id; - case PSN_SETACTIVE: - id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, - LB_GETCURSEL, 0, 0); - if (id == LB_ERR) - PropSheet_SetWizButtons(GetParent(hwnd), - PSWIZB_BACK); - else - PropSheet_SetWizButtons(GetParent(hwnd), - PSWIZB_BACK | PSWIZB_NEXT); - break; - - case PSN_WIZNEXT: - break; - - case PSN_WIZFINISH: - break; - - case PSN_RESET: - break; - - default: - break; - } - } - return 0; -} - -static BOOL OpenLogfile(char *dir) -{ - char buffer[_MAX_PATH+1]; - time_t ltime; - struct tm *now; - long result; - HKEY hKey, hSubkey; - char subkey_name[256]; - static char KeyName[] = - "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; - const char *root_name = (hkey_root==HKEY_LOCAL_MACHINE ? - "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER"); - DWORD disposition; - - /* Use Create, as the Uninstall subkey may not exist under HKCU. - Use CreateKeyEx, so we can specify a SAM specifying write access - */ - result = RegCreateKeyEx(hkey_root, - KeyName, - 0, /* reserved */ - NULL, /* class */ - 0, /* options */ - KEY_CREATE_SUB_KEY, /* sam */ - NULL, /* security */ - &hKey, /* result key */ - NULL); /* disposition */ - if (result != ERROR_SUCCESS) { - if (result == ERROR_ACCESS_DENIED) { - /* This should no longer be able to happen - we have already - checked if they have permissions in HKLM, and all users - should have write access to HKCU. - */ - MessageBox(GetFocus(), - "You do not seem to have sufficient access rights\n" - "on this machine to install this software", - NULL, - MB_OK | MB_ICONSTOP); - return FALSE; - } else { - MessageBox(GetFocus(), KeyName, "Could not open key", MB_OK); - } - } - - sprintf(buffer, "%s\\%s-wininst.log", dir, meta_name); - logfile = fopen(buffer, "a"); - if (!logfile) { - char error[1024]; - - sprintf(error, "Can't create \"%s\" (%s).\n\n" - "Try to execute the installer as administrator.", - buffer, strerror(errno)); - MessageBox(GetFocus(), error, NULL, MB_OK | MB_ICONSTOP); - return FALSE; - } - - time(<ime); - now = localtime(<ime); - strftime(buffer, sizeof(buffer), - "*** Installation started %Y/%m/%d %H:%M ***\n", - localtime(<ime)); - fprintf(logfile, buffer); - fprintf(logfile, "Source: %s\n", modulename); - - /* Root key must be first entry processed by uninstaller. */ - fprintf(logfile, "999 Root Key: %s\n", root_name); - - sprintf(subkey_name, "%s-py%d.%d", meta_name, py_major, py_minor); - - result = RegCreateKeyEx(hKey, subkey_name, - 0, NULL, 0, - KEY_WRITE, - NULL, - &hSubkey, - &disposition); - - if (result != ERROR_SUCCESS) - MessageBox(GetFocus(), subkey_name, "Could not create key", MB_OK); - - RegCloseKey(hKey); - - if (disposition == REG_CREATED_NEW_KEY) - fprintf(logfile, "020 Reg DB Key: [%s]%s\n", KeyName, subkey_name); - - sprintf(buffer, "Python %d.%d %s", py_major, py_minor, title); - - result = RegSetValueEx(hSubkey, "DisplayName", - 0, - REG_SZ, - buffer, - strlen(buffer)+1); - - if (result != ERROR_SUCCESS) - MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK); - - fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n", - KeyName, subkey_name, "DisplayName", buffer); - - { - FILE *fp; - sprintf(buffer, "%s\\Remove%s.exe", dir, meta_name); - fp = fopen(buffer, "wb"); - fwrite(arc_data, exe_size, 1, fp); - fclose(fp); - - sprintf(buffer, "\"%s\\Remove%s.exe\" -u \"%s\\%s-wininst.log\"", - dir, meta_name, dir, meta_name); - - result = RegSetValueEx(hSubkey, "UninstallString", - 0, - REG_SZ, - buffer, - strlen(buffer)+1); - - if (result != ERROR_SUCCESS) - MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK); - - fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n", - KeyName, subkey_name, "UninstallString", buffer); - } - return TRUE; -} - -static void CloseLogfile(void) -{ - char buffer[_MAX_PATH+1]; - time_t ltime; - struct tm *now; - - time(<ime); - now = localtime(<ime); - strftime(buffer, sizeof(buffer), - "*** Installation finished %Y/%m/%d %H:%M ***\n", - localtime(<ime)); - fprintf(logfile, buffer); - if (logfile) - fclose(logfile); -} - -INT_PTR CALLBACK -InstallFilesDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - LPNMHDR lpnm; - char Buffer[4096]; - SCHEME *scheme; - - switch (msg) { - case WM_INITDIALOG: - if (hBitmap) - SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, - IMAGE_BITMAP, (LPARAM)hBitmap); - wsprintf(Buffer, - "Click Next to begin the installation of %s. " - "If you want to review or change any of your " - " installation settings, click Back. " - "Click Cancel to exit the wizard.", - meta_name); - SetDlgItemText(hwnd, IDC_TITLE, Buffer); - SetDlgItemText(hwnd, IDC_INFO, "Ready to install"); - break; - - case WM_NUMFILES: - SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, lParam); - PumpMessages(); - return TRUE; - - case WM_NEXTFILE: - SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, wParam, - 0); - SetDlgItemText(hwnd, IDC_INFO, (LPSTR)lParam); - PumpMessages(); - return TRUE; - - case WM_NOTIFY: - lpnm = (LPNMHDR) lParam; - - switch (lpnm->code) { - case PSN_SETACTIVE: - PropSheet_SetWizButtons(GetParent(hwnd), - PSWIZB_BACK | PSWIZB_NEXT); - break; - - case PSN_WIZFINISH: - break; - - case PSN_WIZNEXT: - /* Handle a Next button click here */ - hDialog = hwnd; - success = TRUE; - - /* Disable the buttons while we work. Sending CANCELTOCLOSE has - the effect of disabling the cancel button, which is a) as we - do everything synchronously we can't cancel, and b) the next - step is 'finished', when it is too late to cancel anyway. - The next step being 'Finished' means we also don't need to - restore the button state back */ - PropSheet_SetWizButtons(GetParent(hwnd), 0); - SendMessage(GetParent(hwnd), PSM_CANCELTOCLOSE, 0, 0); - /* Make sure the installation directory name ends in a */ - /* backslash */ - if (python_dir[strlen(python_dir)-1] != '\\') - strcat(python_dir, "\\"); - /* Strip the trailing backslash again */ - python_dir[strlen(python_dir)-1] = '\0'; - - CheckRootKey(hwnd); - - if (!OpenLogfile(python_dir)) - break; - -/* - * The scheme we have to use depends on the Python version... - if sys.version < "2.2": - WINDOWS_SCHEME = { - 'purelib': '$base', - 'platlib': '$base', - 'headers': '$base/Include/$dist_name', - 'scripts': '$base/Scripts', - 'data' : '$base', - } - else: - WINDOWS_SCHEME = { - 'purelib': '$base/Lib/site-packages', - 'platlib': '$base/Lib/site-packages', - 'headers': '$base/Include/$dist_name', - 'scripts': '$base/Scripts', - 'data' : '$base', - } -*/ - scheme = GetScheme(py_major, py_minor); - /* Run the pre-install script. */ - if (pre_install_script && *pre_install_script) { - SetDlgItemText (hwnd, IDC_TITLE, - "Running pre-installation script"); - run_simple_script(pre_install_script); - } - if (!success) { - break; - } - /* Extract all files from the archive */ - SetDlgItemText(hwnd, IDC_TITLE, "Installing files..."); - if (!unzip_archive (scheme, - python_dir, arc_data, - arc_size, notify)) - set_failure_reason("Failed to unzip installation files"); - /* Compile the py-files */ - if (success && pyc_compile) { - int errors; - HINSTANCE hPython; - SetDlgItemText(hwnd, IDC_TITLE, - "Compiling files to .pyc..."); - - SetDlgItemText(hDialog, IDC_INFO, "Loading python..."); - hPython = LoadPythonDll(pythondll); - if (hPython) { - errors = compile_filelist(hPython, FALSE); - FreeLibrary(hPython); - } - /* Compilation errors are intentionally ignored: - * Python2.0 contains a bug which will result - * in sys.path containing garbage under certain - * circumstances, and an error message will only - * confuse the user. - */ - } - if (success && pyo_compile) { - int errors; - HINSTANCE hPython; - SetDlgItemText(hwnd, IDC_TITLE, - "Compiling files to .pyo..."); - - SetDlgItemText(hDialog, IDC_INFO, "Loading python..."); - hPython = LoadPythonDll(pythondll); - if (hPython) { - errors = compile_filelist(hPython, TRUE); - FreeLibrary(hPython); - } - /* Errors ignored: see above */ - } - - - break; - - case PSN_RESET: - break; - - default: - break; - } - } - return 0; -} - - -INT_PTR CALLBACK -FinishedDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - LPNMHDR lpnm; - - switch (msg) { - case WM_INITDIALOG: - if (hBitmap) - SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, - IMAGE_BITMAP, (LPARAM)hBitmap); - if (!success) - SetDlgItemText(hwnd, IDC_INFO, get_failure_reason()); - - /* async delay: will show the dialog box completely before - the install_script is started */ - PostMessage(hwnd, WM_USER, 0, 0L); - return TRUE; - - case WM_USER: - - if (success && install_script && install_script[0]) { - char fname[MAX_PATH]; - char *buffer; - HCURSOR hCursor; - int result; - - char *argv[3] = {NULL, "-install", NULL}; - - SetDlgItemText(hwnd, IDC_TITLE, - "Please wait while running postinstall script..."); - strcpy(fname, python_dir); - strcat(fname, "\\Scripts\\"); - strcat(fname, install_script); - - if (logfile) - fprintf(logfile, "300 Run Script: [%s]%s\n", pythondll, fname); - - hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); - - argv[0] = fname; - - result = run_installscript(fname, 2, argv, &buffer); - if (0 != result) { - fprintf(stderr, "*** run_installscript: internal error 0x%X ***\n", result); - } - if (buffer) - SetDlgItemText(hwnd, IDC_INFO, buffer); - SetDlgItemText(hwnd, IDC_TITLE, - "Postinstall script finished.\n" - "Click the Finish button to exit the Setup wizard."); - - free(buffer); - SetCursor(hCursor); - CloseLogfile(); - } - - return TRUE; - - case WM_NOTIFY: - lpnm = (LPNMHDR) lParam; - - switch (lpnm->code) { - case PSN_SETACTIVE: /* Enable the Finish button */ - PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH); - break; - - case PSN_WIZNEXT: - break; - - case PSN_WIZFINISH: - break; - - case PSN_RESET: - break; - - default: - break; - } - } - return 0; -} - -void RunWizard(HWND hwnd) -{ - PROPSHEETPAGE psp = {0}; - HPROPSHEETPAGE ahpsp[4] = {0}; - PROPSHEETHEADER psh = {0}; - - /* Display module information */ - psp.dwSize = sizeof(psp); - psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; - psp.hInstance = GetModuleHandle (NULL); - psp.lParam = 0; - psp.pfnDlgProc = IntroDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_INTRO); - - ahpsp[0] = CreatePropertySheetPage(&psp); - - /* Select python version to use */ - psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; - psp.pszTemplate = MAKEINTRESOURCE(IDD_SELECTPYTHON); - psp.pfnDlgProc = SelectPythonDlgProc; - - ahpsp[1] = CreatePropertySheetPage(&psp); - - /* Install the files */ - psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; - psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLFILES); - psp.pfnDlgProc = InstallFilesDlgProc; - - ahpsp[2] = CreatePropertySheetPage(&psp); - - /* Show success or failure */ - psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; - psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHED); - psp.pfnDlgProc = FinishedDlgProc; - - ahpsp[3] = CreatePropertySheetPage(&psp); - - /* Create the property sheet */ - psh.dwSize = sizeof(psh); - psh.hInstance = GetModuleHandle(NULL); - psh.hwndParent = hwnd; - psh.phpage = ahpsp; - psh.dwFlags = PSH_WIZARD/*97*//*|PSH_WATERMARK|PSH_HEADER*/; - psh.pszbmWatermark = NULL; - psh.pszbmHeader = NULL; - psh.nStartPage = 0; - psh.nPages = 4; - - PropertySheet(&psh); -} - -// subtly different from HasLocalMachinePrivs(), in that after executing -// an 'elevated' process, we expect this to return TRUE - but there is no -// such implication for HasLocalMachinePrivs -BOOL MyIsUserAnAdmin() -{ - typedef BOOL (WINAPI *PFNIsUserAnAdmin)(); - static PFNIsUserAnAdmin pfnIsUserAnAdmin = NULL; - HMODULE shell32; - // This function isn't guaranteed to be available (and it can't hurt - // to leave the library loaded) - if (0 == (shell32=LoadLibrary("shell32.dll"))) - return FALSE; - if (NULL == (pfnIsUserAnAdmin=(PFNIsUserAnAdmin)GetProcAddress(shell32, "IsUserAnAdmin"))) - return FALSE; - return (*pfnIsUserAnAdmin)(); -} - -// Some magic for Vista's UAC. If there is a target_version, and -// if that target version is installed in the registry under -// HKLM, and we are not current administrator, then -// re-execute ourselves requesting elevation. -// Split into 2 functions - "should we elevate" and "spawn elevated" - -// Returns TRUE if we should spawn an elevated child -BOOL NeedAutoUAC() -{ - HKEY hk; - char key_name[80]; - // no Python version info == we can't know yet. - if (target_version[0] == '\0') - return FALSE; - // see how python is current installed - wsprintf(key_name, - "Software\\Python\\PythonCore\\%s\\InstallPath", - target_version); - if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, - key_name, 0, KEY_READ, &hk)) - return FALSE; - RegCloseKey(hk); - // Python is installed in HKLM - we must elevate. - return TRUE; -} - -// Spawn ourself as an elevated application. On failure, a message is -// displayed to the user - but this app will always terminate, even -// on error. -void SpawnUAC() -{ - // interesting failure scenario that has been seen: initial executable - // runs from a network drive - but once elevated, that network share - // isn't seen, and ShellExecute fails with SE_ERR_ACCESSDENIED. - int ret = (int)ShellExecute(0, "runas", modulename, "", NULL, - SW_SHOWNORMAL); - if (ret <= 32) { - char msg[128]; - wsprintf(msg, "Failed to start elevated process (ShellExecute returned %d)", ret); - MessageBox(0, msg, "Setup", MB_OK | MB_ICONERROR); - } -} - -int DoInstall(void) -{ - char ini_buffer[4096]; - - /* Read installation information */ - GetPrivateProfileString("Setup", "title", "", ini_buffer, - sizeof(ini_buffer), ini_file); - unescape(title, ini_buffer, sizeof(title)); - - GetPrivateProfileString("Setup", "info", "", ini_buffer, - sizeof(ini_buffer), ini_file); - unescape(info, ini_buffer, sizeof(info)); - - GetPrivateProfileString("Setup", "build_info", "", build_info, - sizeof(build_info), ini_file); - - pyc_compile = GetPrivateProfileInt("Setup", "target_compile", 1, - ini_file); - pyo_compile = GetPrivateProfileInt("Setup", "target_optimize", 1, - ini_file); - - GetPrivateProfileString("Setup", "target_version", "", - target_version, sizeof(target_version), - ini_file); - - GetPrivateProfileString("metadata", "name", "", - meta_name, sizeof(meta_name), - ini_file); - - GetPrivateProfileString("Setup", "install_script", "", - install_script, sizeof(install_script), - ini_file); - - GetPrivateProfileString("Setup", "user_access_control", "", - user_access_control, sizeof(user_access_control), ini_file); - - strcat(target_version, REGISTRY_SUFFIX_6432); - - // See if we need to do the Vista UAC magic. - if (strcmp(user_access_control, "force")==0) { - if (!MyIsUserAnAdmin()) { - SpawnUAC(); - return 0; - } - // already admin - keep going - } else if (strcmp(user_access_control, "auto")==0) { - // Check if it looks like we need UAC control, based - // on how Python itself was installed. - if (!MyIsUserAnAdmin() && NeedAutoUAC()) { - SpawnUAC(); - return 0; - } - } else { - // display a warning about unknown values - only the developer - // of the extension will see it (until they fix it!) - if (user_access_control[0] && strcmp(user_access_control, "none") != 0) { - MessageBox(GetFocus(), "Bad user_access_control value", "oops", MB_OK); - // nothing to do. - } - } - - hwndMain = CreateBackground(title); - - RunWizard(hwndMain); - - /* Clean up */ - UnmapViewOfFile(arc_data); - if (ini_file) - DeleteFile(ini_file); - - if (hBitmap) - DeleteObject(hBitmap); - - return 0; -} - -/*********************** uninstall section ******************************/ - -static int compare(const void *p1, const void *p2) -{ - return strcmp(*(char **)p2, *(char **)p1); -} - -/* - * Commit suicide (remove the uninstaller itself). - * - * Create a batch file to first remove the uninstaller - * (will succeed after it has finished), then the batch file itself. - * - * This technique has been demonstrated by Jeff Richter, - * MSJ 1/1996 - */ -void remove_exe(void) -{ - char exename[_MAX_PATH]; - char batname[_MAX_PATH]; - FILE *fp; - STARTUPINFO si; - PROCESS_INFORMATION pi; - - GetModuleFileName(NULL, exename, sizeof(exename)); - sprintf(batname, "%s.bat", exename); - fp = fopen(batname, "w"); - fprintf(fp, ":Repeat\n"); - fprintf(fp, "del \"%s\"\n", exename); - fprintf(fp, "if exist \"%s\" goto Repeat\n", exename); - fprintf(fp, "del \"%s\"\n", batname); - fclose(fp); - - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - if (CreateProcess(NULL, - batname, - NULL, - NULL, - FALSE, - CREATE_SUSPENDED | IDLE_PRIORITY_CLASS, - NULL, - "\\", - &si, - &pi)) { - SetThreadPriority(pi.hThread, THREAD_PRIORITY_IDLE); - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); - CloseHandle(pi.hProcess); - ResumeThread(pi.hThread); - CloseHandle(pi.hThread); - } -} - -void DeleteRegistryKey(char *string) -{ - char *keyname; - char *subkeyname; - char *delim; - HKEY hKey; - long result; - char *line; - - line = strdup(string); /* so we can change it */ - - keyname = strchr(line, '['); - if (!keyname) - return; - ++keyname; - - subkeyname = strchr(keyname, ']'); - if (!subkeyname) - return; - *subkeyname++='\0'; - delim = strchr(subkeyname, '\n'); - if (delim) - *delim = '\0'; - - result = RegOpenKeyEx(hkey_root, - keyname, - 0, - KEY_WRITE, - &hKey); - - if (result != ERROR_SUCCESS) - MessageBox(GetFocus(), string, "Could not open key", MB_OK); - else { - result = RegDeleteKey(hKey, subkeyname); - if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) - MessageBox(GetFocus(), string, "Could not delete key", MB_OK); - RegCloseKey(hKey); - } - free(line); -} - -void DeleteRegistryValue(char *string) -{ - char *keyname; - char *valuename; - char *value; - HKEY hKey; - long result; - char *line; - - line = strdup(string); /* so we can change it */ - -/* Format is 'Reg DB Value: [key]name=value' */ - keyname = strchr(line, '['); - if (!keyname) - return; - ++keyname; - valuename = strchr(keyname, ']'); - if (!valuename) - return; - *valuename++ = '\0'; - value = strchr(valuename, '='); - if (!value) - return; - - *value++ = '\0'; - - result = RegOpenKeyEx(hkey_root, - keyname, - 0, - KEY_WRITE, - &hKey); - if (result != ERROR_SUCCESS) - MessageBox(GetFocus(), string, "Could not open key", MB_OK); - else { - result = RegDeleteValue(hKey, valuename); - if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) - MessageBox(GetFocus(), string, "Could not delete value", MB_OK); - RegCloseKey(hKey); - } - free(line); -} - -BOOL MyDeleteFile(char *line) -{ - char *pathname = strchr(line, ':'); - if (!pathname) - return FALSE; - ++pathname; - while (isspace(*pathname)) - ++pathname; - return DeleteFile(pathname); -} - -BOOL MyRemoveDirectory(char *line) -{ - char *pathname = strchr(line, ':'); - if (!pathname) - return FALSE; - ++pathname; - while (isspace(*pathname)) - ++pathname; - return RemoveDirectory(pathname); -} - -BOOL Run_RemoveScript(char *line) -{ - char *dllname; - char *scriptname; - static char lastscript[MAX_PATH]; - -/* Format is 'Run Scripts: [pythondll]scriptname' */ -/* XXX Currently, pythondll carries no path!!! */ - dllname = strchr(line, '['); - if (!dllname) - return FALSE; - ++dllname; - scriptname = strchr(dllname, ']'); - if (!scriptname) - return FALSE; - *scriptname++ = '\0'; - /* this function may be called more than one time with the same - script, only run it one time */ - if (strcmp(lastscript, scriptname)) { - char *argv[3] = {NULL, "-remove", NULL}; - char *buffer = NULL; - - argv[0] = scriptname; - - if (0 != run_installscript(scriptname, 2, argv, &buffer)) - fprintf(stderr, "*** Could not run installation script ***"); - - if (buffer && buffer[0]) - MessageBox(GetFocus(), buffer, "uninstall-script", MB_OK); - free(buffer); - - strcpy(lastscript, scriptname); - } - return TRUE; -} - -int DoUninstall(int argc, char **argv) -{ - FILE *logfile; - char buffer[4096]; - int nLines = 0; - int i; - char *cp; - int nFiles = 0; - int nDirs = 0; - int nErrors = 0; - char **lines; - int lines_buffer_size = 10; - - if (argc != 3) { - MessageBox(NULL, - "Wrong number of args", - NULL, - MB_OK); - return 1; /* Error */ - } - if (strcmp(argv[1], "-u")) { - MessageBox(NULL, - "2. arg is not -u", - NULL, - MB_OK); - return 1; /* Error */ - } - - logfile = fopen(argv[2], "r"); - if (!logfile) { - MessageBox(NULL, - "could not open logfile", - NULL, - MB_OK); - return 1; /* Error */ - } - - lines = (char **)malloc(sizeof(char *) * lines_buffer_size); - if (!lines) - return SystemError(0, "Out of memory"); - - /* Read the whole logfile, reallocating the buffer */ - while (fgets(buffer, sizeof(buffer), logfile)) { - int len = strlen(buffer); - /* remove trailing white space */ - while (isspace(buffer[len-1])) - len -= 1; - buffer[len] = '\0'; - lines[nLines++] = strdup(buffer); - if (nLines >= lines_buffer_size) { - lines_buffer_size += 10; - lines = (char **)realloc(lines, - sizeof(char *) * lines_buffer_size); - if (!lines) - return SystemError(0, "Out of memory"); - } - } - fclose(logfile); - - /* Sort all the lines, so that highest 3-digit codes are first */ - qsort(&lines[0], nLines, sizeof(char *), - compare); - - if (IDYES != MessageBox(NULL, - "Are you sure you want to remove\n" - "this package from your computer?", - "Please confirm", - MB_YESNO | MB_ICONQUESTION)) - return 0; - - hkey_root = HKEY_LOCAL_MACHINE; - cp = ""; - for (i = 0; i < nLines; ++i) { - /* Ignore duplicate lines */ - if (strcmp(cp, lines[i])) { - int ign; - cp = lines[i]; - /* Parse the lines */ - if (2 == sscanf(cp, "%d Root Key: %s", &ign, &buffer)) { - if (strcmp(buffer, "HKEY_CURRENT_USER")==0) - hkey_root = HKEY_CURRENT_USER; - else { - // HKLM - check they have permissions. - if (!HasLocalMachinePrivs()) { - MessageBox(GetFocus(), - "You do not seem to have sufficient access rights\n" - "on this machine to uninstall this software", - NULL, - MB_OK | MB_ICONSTOP); - return 1; /* Error */ - } - } - } else if (2 == sscanf(cp, "%d Made Dir: %s", &ign, &buffer)) { - if (MyRemoveDirectory(cp)) - ++nDirs; - else { - int code = GetLastError(); - if (code != 2 && code != 3) { /* file or path not found */ - ++nErrors; - } - } - } else if (2 == sscanf(cp, "%d File Copy: %s", &ign, &buffer)) { - if (MyDeleteFile(cp)) - ++nFiles; - else { - int code = GetLastError(); - if (code != 2 && code != 3) { /* file or path not found */ - ++nErrors; - } - } - } else if (2 == sscanf(cp, "%d File Overwrite: %s", &ign, &buffer)) { - if (MyDeleteFile(cp)) - ++nFiles; - else { - int code = GetLastError(); - if (code != 2 && code != 3) { /* file or path not found */ - ++nErrors; - } - } - } else if (2 == sscanf(cp, "%d Reg DB Key: %s", &ign, &buffer)) { - DeleteRegistryKey(cp); - } else if (2 == sscanf(cp, "%d Reg DB Value: %s", &ign, &buffer)) { - DeleteRegistryValue(cp); - } else if (2 == sscanf(cp, "%d Run Script: %s", &ign, &buffer)) { - Run_RemoveScript(cp); - } - } - } - - if (DeleteFile(argv[2])) { - ++nFiles; - } else { - ++nErrors; - SystemError(GetLastError(), argv[2]); - } - if (nErrors) - wsprintf(buffer, - "%d files and %d directories removed\n" - "%d files or directories could not be removed", - nFiles, nDirs, nErrors); - else - wsprintf(buffer, "%d files and %d directories removed", - nFiles, nDirs); - MessageBox(NULL, buffer, "Uninstall Finished!", - MB_OK | MB_ICONINFORMATION); - remove_exe(); - return 0; -} - -int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, - LPSTR lpszCmdLine, INT nCmdShow) -{ - extern int __argc; - extern char **__argv; - char *basename; - - GetModuleFileName(NULL, modulename, sizeof(modulename)); - GetModuleFileNameW(NULL, wmodulename, sizeof(wmodulename)/sizeof(wmodulename[0])); - - /* Map the executable file to memory */ - arc_data = MapExistingFile(modulename, &arc_size); - if (!arc_data) { - SystemError(GetLastError(), "Could not open archive"); - return 1; - } - - /* OK. So this program can act as installer (self-extracting - * zip-file, or as uninstaller when started with '-u logfile' - * command line flags. - * - * The installer is usually started without command line flags, - * and the uninstaller is usually started with the '-u logfile' - * flag. What to do if some innocent user double-clicks the - * exe-file? - * The following implements a defensive strategy... - */ - - /* Try to extract the configuration data into a temporary file */ - if (ExtractInstallData(arc_data, arc_size, &exe_size, - &ini_file, &pre_install_script)) - return DoInstall(); - - if (!ini_file && __argc > 1) { - return DoUninstall(__argc, __argv); - } - - - basename = strrchr(modulename, '\\'); - if (basename) - ++basename; - - /* Last guess about the purpose of this program */ - if (basename && (0 == strncmp(basename, "Remove", 6))) - SystemError(0, "This program is normally started by windows"); - else - SystemError(0, "Setup program invalid or damaged"); - return 1; -} diff --git a/PC/bdist_wininst/install.rc b/PC/bdist_wininst/install.rc deleted file mode 100644 index dfa2ffcd74..0000000000 --- a/PC/bdist_wininst/install.rc +++ /dev/null @@ -1,77 +0,0 @@ -/* - IMPORTANT NOTE: IF THIS FILE IS CHANGED, PCBUILD\BDIST_WININST.VCXPROJ MUST - BE REBUILT AS WELL. - - IF CHANGES TO THIS FILE ARE CHECKED IN, THE RECOMPILED BINARIES MUST BE - CHECKED IN AS WELL! -*/ - -#include <winres.h> -#include "resource.h" - -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -#pragma code_page(1252) - -IDB_BITMAP BITMAP DISCARDABLE "PythonPowered.bmp" - - -IDD_INTRO DIALOGEX 0, 0, 379, 178 -STYLE WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Setup" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - LTEXT "This Wizard will install %s on your computer. Click Next to continue or Cancel to exit the Setup Wizard.", - IDC_TITLE,125,10,247,20,NOT WS_GROUP - EDITTEXT IDC_INTRO_TEXT,125,31,247,131,ES_MULTILINE | ES_READONLY | - WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP - CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8, - 104,163,WS_EX_CLIENTEDGE - LTEXT "",IDC_BUILD_INFO,125,163,247,8 -END - -IDD_SELECTPYTHON DIALOGEX 0, 0, 379, 178 -STYLE WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Setup" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - LTEXT "Select python installation to use:",IDC_TITLE,125,10, - 247,12,NOT WS_GROUP - EDITTEXT IDC_PATH,191,136,181,14,ES_AUTOHSCROLL | ES_READONLY - LTEXT "Python Directory:",IDC_STATIC,125,137,55,8 - LISTBOX IDC_VERSIONS_LIST,125,24,247,106,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8, - 104,163,WS_EX_CLIENTEDGE - EDITTEXT IDC_INSTALL_PATH,191,157,181,14,ES_AUTOHSCROLL | - ES_READONLY - LTEXT "Installation Directory:",IDC_STATIC,125,158,66,8 - PUSHBUTTON "Find other ...",IDC_OTHERPYTHON,322,7,50,14,NOT - WS_VISIBLE -END - -IDD_INSTALLFILES DIALOGEX 0, 0, 379, 178 -STYLE WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Setup" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - LTEXT "Click Next to begin the installation. If you want to review or change any of your installation settings, click Back. Click Cancel to exit the Wizard.", - IDC_TITLE,125,10,246,31,NOT WS_GROUP - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER, - 125,157,246,14 - CTEXT "Installation progress:",IDC_INFO,125,137,246,8 - CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8, - 104,163,WS_EX_CLIENTEDGE -END - -IDD_FINISHED DIALOGEX 0, 0, 379, 178 -STYLE WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Setup" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Click the Finish button to exit the Setup wizard.", - IDC_TITLE,125,10,247,31,NOT WS_GROUP - CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8, - 104,163,WS_EX_CLIENTEDGE - EDITTEXT IDC_INFO,125,40,247,131,ES_MULTILINE | ES_READONLY | - WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP -END diff --git a/PC/bdist_wininst/resource.h b/PC/bdist_wininst/resource.h deleted file mode 100644 index 86aeabb13a..0000000000 --- a/PC/bdist_wininst/resource.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - IMPORTANT NOTE: IF THIS FILE IS CHANGED, PCBUILD\BDIST_WININST.VCXPROJ MUST - BE REBUILT AS WELL. - - IF CHANGES TO THIS FILE ARE CHECKED IN, THE RECOMPILED BINARIES MUST BE - CHECKED IN AS WELL! -*/ - -#define IDD_DIALOG1 101 -#define IDB_BITMAP1 103 -#define IDD_INTRO 107 -#define IDD_SELECTPYTHON 108 -#define IDD_INSTALLFILES 109 -#define IDD_FINISHED 110 -#define IDB_BITMAP 110 -#define IDC_EDIT1 1000 -#define IDC_TITLE 1000 -#define IDC_START 1001 -#define IDC_PROGRESS 1003 -#define IDC_INFO 1004 -#define IDC_PYTHON15 1006 -#define IDC_PATH 1007 -#define IDC_PYTHON16 1008 -#define IDC_INSTALL_PATH 1008 -#define IDC_PYTHON20 1009 -#define IDC_BROWSE 1010 -#define IDC_INTRO_TEXT 1021 -#define IDC_VERSIONS_LIST 1022 -#define IDC_BUILD_INFO 1024 -#define IDC_BITMAP 1025 -#define IDC_OTHERPYTHON 1026 diff --git a/PC/layout/main.py b/PC/layout/main.py index 8c69c91542..fb6f526585 100644 --- a/PC/layout/main.py +++ b/PC/layout/main.py @@ -33,9 +33,6 @@ from .support.pip import * from .support.props import * from .support.nuspec import * -BDIST_WININST_FILES_ONLY = FileNameSet("wininst-*", "bdist_wininst.py") -BDIST_WININST_STUB = "PC/layout/support/distutils.command.bdist_wininst.py" - TEST_PYDS_ONLY = FileStemSet("xxlimited", "xxlimited_35", "_ctypes_test", "_test*") TEST_DIRS_ONLY = FileNameSet("test", "tests") @@ -100,17 +97,11 @@ def get_lib_layout(ns): else: if f in TCLTK_FILES_ONLY: return ns.include_tcltk - if f in BDIST_WININST_FILES_ONLY: - return ns.include_bdist_wininst return True for dest, src in rglob(ns.source / "Lib", "**/*", _c): yield dest, src - if not ns.include_bdist_wininst: - src = ns.source / BDIST_WININST_STUB - yield Path("distutils/command/bdist_wininst.py"), src - def get_tcltk_lib(ns): if not ns.include_tcltk: diff --git a/PC/layout/support/distutils.command.bdist_wininst.py b/PC/layout/support/distutils.command.bdist_wininst.py deleted file mode 100644 index 6e9b49fe42..0000000000 --- a/PC/layout/support/distutils.command.bdist_wininst.py +++ /dev/null @@ -1,25 +0,0 @@ -"""distutils.command.bdist_wininst - -Suppress the 'bdist_wininst' command, while still allowing -setuptools to import it without breaking.""" - -from distutils.core import Command -from distutils.errors import DistutilsPlatformError - - -class bdist_wininst(Command): - description = "create an executable installer for MS Windows" - - # Marker for tests that we have the unsupported bdist_wininst - _unsupported = True - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - raise DistutilsPlatformError( - "bdist_wininst is not supported in this Python distribution" - ) diff --git a/PC/layout/support/options.py b/PC/layout/support/options.py index 5e1543b59c..9faf20c0fd 100644 --- a/PC/layout/support/options.py +++ b/PC/layout/support/options.py @@ -26,7 +26,6 @@ OPTIONS = { "venv": {"help": "venv"}, "dev": {"help": "headers and libs"}, "symbols": {"help": "symbols"}, - "bdist-wininst": {"help": "bdist_wininst support"}, "underpth": {"help": "a python._pth file", "not-in-all": True}, "launchers": {"help": "specific launchers"}, "appxmanifest": {"help": "an appxmanifest"}, @@ -81,7 +80,6 @@ PRESETS = { "venv", "dev", "symbols", - "bdist-wininst", "chm", ], }, |