1bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 2d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller IMPORTANT NOTE: IF THIS FILE IS CHANGED, WININST-6.EXE MUST BE RECOMPILED 3d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller WITH THE MSVC6 WININST.DSW WORKSPACE FILE MANUALLY, AND WININST-7.1.EXE MUST 4d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller BE RECOMPILED WITH THE MSVC 2003.NET WININST-7.1.VCPROJ FILE MANUALLY. 5d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller 6d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller IF CHANGES TO THIS FILE ARE CHECKED INTO PYTHON CVS, THE RECOMPILED BINARIES 7d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller MUST BE CHECKED IN AS WELL! 8d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller*/ 9d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller 10d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller/* 11bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Written by Thomas Heller, May 2000 12bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 13bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * $Id$ 14bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 15bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 16bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 17bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Windows Installer program for distutils. 18bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 19bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * (a kind of self-extracting zip-file) 20bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 21bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * At runtime, the exefile has appended: 22bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - compressed setup-data in ini-format, containing the following sections: 23c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * [metadata] 24c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * author=Greg Ward 25c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * author_email=gward@python.net 26c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * description=Python Distribution Utilities 27c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * licence=Python 28c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * name=Distutils 29c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * url=http://www.python.org/sigs/distutils-sig/ 30c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * version=0.9pre 31bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 32c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * [Setup] 33c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * info= text to be displayed in the edit-box 34c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * title= to be displayed by this program 35c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * target_version = if present, python version required 36c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * pyc_compile = if 0, do not compile py to pyc 37c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * pyo_compile = if 0, do not compile py to pyo 38bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 39bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - a struct meta_data_hdr, describing the above 40bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - a zip-file, containing the modules to be installed. 41bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * for the format see http://www.pkware.com/appnote.html 42bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 43bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * What does this program do? 44bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - the setup-data is uncompressed and written to a temporary file. 45bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - setup-data is queried with GetPrivateProfile... calls 46bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - [metadata] - info is displayed in the dialog box 47bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - The registry is searched for installations of python 48bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - The user can select the python version to use. 49bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - The python-installation directory (sys.prefix) is displayed 50bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - When the start-button is pressed, files from the zip-archive 51bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * are extracted to the file system. All .py filenames are stored 52bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * in a list. 53bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 54bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 55bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Includes now an uninstaller. 56bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 57bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 58bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 59bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * To Do: 60bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 61bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * display some explanation when no python version is found 62bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * instead showing the user an empty listbox to select something from. 63bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 64bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Finish the code so that we can use other python installations 6524b07bcba350bb86c4d6ca446e1564647a199868Ezio Melotti * additionally to those found in the registry, 66bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * and then #define USE_OTHER_PYTHON_VERSIONS 67bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 68bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - install a help-button, which will display something meaningful 69bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * to the poor user. 70bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * text to the user 71bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - should there be a possibility to display a README file 72bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * before starting the installation (if one is present in the archive) 73bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - more comments about what the code does(?) 74bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 75bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - evolve this into a full blown installer (???) 76bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 77bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 78bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <windows.h> 79bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <commctrl.h> 80bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <imagehlp.h> 81bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <objbase.h> 82bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <shlobj.h> 83bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <objidl.h> 84bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include "resource.h" 85bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 86bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <stdio.h> 87bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <stdlib.h> 88bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <stdarg.h> 89bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <string.h> 90bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <time.h> 919f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <sys/types.h> 929f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <sys/stat.h> 939f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <malloc.h> 949f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <io.h> 959f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <fcntl.h> 96bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 97bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include "archive.h" 98bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 99bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Only for debugging! 100bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller static int dprintf(char *fmt, ...) 101bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller { 102bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller char Buffer[4096]; 103bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller va_list marker; 104bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller int result; 105bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 106bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller va_start(marker, fmt); 107bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller result = wvsprintf(Buffer, fmt, marker); 108bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller OutputDebugString(Buffer); 109bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller return result; 110bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller } 111bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller*/ 112bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 113bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Bah: global variables */ 114bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerFILE *logfile; 115bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 116bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar modulename[MAX_PATH]; 117bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 118bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerHWND hwndMain; 119bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerHWND hDialog; 120bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 121c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouchar *ini_file; /* Full pathname of ini-file */ 122bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* From ini-file */ 123c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouchar info[4096]; /* [Setup] info= */ 124c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouchar title[80]; /* [Setup] title=, contains package name 125c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou including version: "Distutils-1.0.1" */ 126c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouchar target_version[10]; /* [Setup] target_version=, required python 127c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou version or empty string */ 128c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouchar build_info[80]; /* [Setup] build_info=, distutils version 129c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou and build date */ 130c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 131c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouchar meta_name[80]; /* package name without version like 132c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 'Distutils' */ 133bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar install_script[MAX_PATH]; 134a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerchar *pre_install_script; /* run before we install a single file */ 135bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1367c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammondchar user_access_control[10]; // one of 'auto', 'force', otherwise none. 137bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 138c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouint py_major, py_minor; /* Python version selected for installation */ 139bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 140c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouchar *arc_data; /* memory mapped archive */ 141c83ea137d7e717f764e2f31fc2544f522de7d857Antoine PitrouDWORD arc_size; /* number of bytes in archive */ 142c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrouint exe_size; /* number of bytes for exe-file portion */ 143bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar python_dir[MAX_PATH]; 144bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar pythondll[MAX_PATH]; 145bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL pyc_compile, pyo_compile; 146f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond/* Either HKLM or HKCU, depending on where Python itself is registered, and 147f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond the permissions of the current user. */ 148f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark HammondHKEY hkey_root = (HKEY)-1; 149bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 150c2077b0d9b5bf99768c6f396bf7ae6c41b682465Ezio MelottiBOOL success; /* Installation successful? */ 151a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerchar *failure_reason = NULL; 152bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 153bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerHANDLE hBitmap; 154bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar *bitmap_bytes; 155bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 156bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 157bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define WM_NUMFILES WM_USER+1 158bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* wParam: 0, lParam: total number of files */ 159bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define WM_NEXTFILE WM_USER+2 160bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* wParam: number of this file */ 161bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* lParam: points to pathname */ 162bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 163bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL notify(int code, char *fmt, ...); 164bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 165bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Note: If scheme.prefix is nonempty, it must end with a '\'! */ 166bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Note: purelib must be the FIRST entry! */ 167bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerSCHEME old_scheme[] = { 168c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "PURELIB", "" }, 169c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "PLATLIB", "" }, 170c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */ 171c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "SCRIPTS", "Scripts\\" }, 172c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "DATA", "" }, 173c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { NULL, NULL }, 174bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 175bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 176bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerSCHEME new_scheme[] = { 177c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "PURELIB", "Lib\\site-packages\\" }, 178c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "PLATLIB", "Lib\\site-packages\\" }, 179c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */ 180c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "SCRIPTS", "Scripts\\" }, 181c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { "DATA", "" }, 182c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { NULL, NULL }, 183bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 184bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 185bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void unescape(char *dst, char *src, unsigned size) 186bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 187c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *eon; 188c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char ch; 189c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 190c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (src && *src && (size > 2)) { 191c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (*src == '\\') { 192c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (*++src) { 193c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case 'n': 194c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++src; 195c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *dst++ = '\r'; 196c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *dst++ = '\n'; 197c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou size -= 2; 198c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 199c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case 'r': 200c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++src; 201c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *dst++ = '\r'; 202c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou --size; 203c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 204c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case '0': case '1': case '2': case '3': 205c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ch = (char)strtol(src, &eon, 8); 206c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ch == '\n') { 207c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *dst++ = '\r'; 208c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou --size; 209c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 210c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *dst++ = ch; 211c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou --size; 212c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou src = eon; 213c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 214c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else { 215c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *dst++ = *src++; 216c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou --size; 217c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 218c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 219c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *dst = '\0'; 220bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 221bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 222bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic struct tagFile { 223c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *path; 224c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct tagFile *next; 225bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} *file_list = NULL; 226bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 227a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic void set_failure_reason(char *reason) 228a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 229a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller if (failure_reason) 230c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou free(failure_reason); 231a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller failure_reason = strdup(reason); 232a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller success = FALSE; 233a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 234a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic char *get_failure_reason() 235a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 236a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller if (!failure_reason) 237c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return "Installation failed."; 238a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller return failure_reason; 239a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 240a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 241bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void add_to_filelist(char *path) 242bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 243c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct tagFile *p; 244c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou p = (struct tagFile *)malloc(sizeof(struct tagFile)); 245c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou p->path = strdup(path); 246c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou p->next = file_list; 247c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou file_list = p; 248bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 249bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 250bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic int do_compile_files(int (__cdecl * PyRun_SimpleString)(char *), 251c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int optimize) 252bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 253c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct tagFile *p; 254c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int total, n; 255c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char Buffer[MAX_PATH + 64]; 256c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int errors = 0; 257c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 258c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou total = 0; 259c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou p = file_list; 260c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (p) { 261c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++total; 262c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou p = p->next; 263c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 264c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETRANGE, 0, 265c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MAKELPARAM(0, total)); 266c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, 0, 0); 267c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 268c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou n = 0; 269c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou p = file_list; 270c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (p) { 271c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++n; 272c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(Buffer, 273c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "import py_compile; py_compile.compile (r'%s')", 274c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou p->path); 275c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (PyRun_SimpleString(Buffer)) { 276c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++errors; 277c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 278c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* We send the notification even if the files could not 279c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * be created so that the uninstaller will remove them 280c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * in case they are created later. 281c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou */ 282c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(Buffer, "%s%c", p->path, optimize ? 'o' : 'c'); 283c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou notify(FILE_CREATED, Buffer); 284c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 285c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, n, 0); 286c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hDialog, IDC_INFO, p->path); 287c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou p = p->next; 288c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 289c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return errors; 290bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 291bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 292bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define DECLPROC(dll, result, name, args)\ 293bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller typedef result (*__PROC__##name) args;\ 294bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller result (*name)args = (__PROC__##name)GetProcAddress(dll, #name) 295bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 296bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 297bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define DECLVAR(dll, type, name)\ 298bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller type *name = (type*)GetProcAddress(dll, #name) 299bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 300bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellertypedef void PyObject; 301bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 302bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 303bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 304bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Returns number of files which failed to compile, 305bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * -1 if python could not be loaded at all 306bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 307bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic int compile_filelist(HINSTANCE hPython, BOOL optimize_flag) 308bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 309c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, Py_Initialize, (void)); 310c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, Py_SetProgramName, (char *)); 311c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, Py_Finalize, (void)); 312c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, int, PyRun_SimpleString, (char *)); 313c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, PySys_GetObject, (char *)); 314c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLVAR(hPython, int, Py_OptimizeFlag); 315bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 316c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int errors = 0; 317c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct tagFile *p = file_list; 318bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 319c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!p) 320c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 321bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 322c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!Py_Initialize || !Py_SetProgramName || !Py_Finalize) 323c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return -1; 324bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 325c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!PyRun_SimpleString || !PySys_GetObject || !Py_OptimizeFlag) 326c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return -1; 327bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 328c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *Py_OptimizeFlag = optimize_flag ? 1 : 0; 329c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_SetProgramName(modulename); 330c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Initialize(); 331bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 332c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou errors += do_compile_files(PyRun_SimpleString, optimize_flag); 333c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Finalize(); 334bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 335c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return errors; 336bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 337bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 338bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellertypedef PyObject *(*PyCFunction)(PyObject *, PyObject *); 339bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 340bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstruct PyMethodDef { 341c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *ml_name; 342c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PyCFunction ml_meth; 343c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int ml_flags; 344c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *ml_doc; 345bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 346bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellertypedef struct PyMethodDef PyMethodDef; 347bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 3487c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// XXX - all of these are potentially fragile! We load and unload 349c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou// the Python DLL multiple times - so storing functions pointers 3507c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// is dangerous (although things *look* OK at present) 3517c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// Better might be to roll prepare_script_environment() into 3527c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// LoadPythonDll(), and create a new UnloadPythonDLL() which also 3537c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// clears the global pointers. 354bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid *(*g_Py_BuildValue)(char *, ...); 355bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint (*g_PyArg_ParseTuple)(PyObject *, char *, ...); 3567c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark HammondPyObject * (*g_PyLong_FromVoidPtr)(void *); 357bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 358bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerPyObject *g_PyExc_ValueError; 359bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerPyObject *g_PyExc_OSError; 360bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 361bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerPyObject *(*g_PyErr_Format)(PyObject *, char *, ...); 362bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 363bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define DEF_CSIDL(name) { name, #name } 364bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 365bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstruct { 366c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int nFolder; 367c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *name; 368bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} csidl_names[] = { 369c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Startup menu for all users. 370c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NT only */ 371c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_COMMON_STARTMENU), 372c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Startup menu. */ 373c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_STARTMENU), 374bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 375bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* DEF_CSIDL(CSIDL_COMMON_APPDATA), */ 376bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* DEF_CSIDL(CSIDL_LOCAL_APPDATA), */ 377c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Repository for application-specific data. 378c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Needs Internet Explorer 4.0 */ 379c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_APPDATA), 380c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 381c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* The desktop for all users. 382c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NT only */ 383c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_COMMON_DESKTOPDIRECTORY), 384c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* The desktop. */ 385c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_DESKTOPDIRECTORY), 386c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 387c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Startup folder for all users. 388c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NT only */ 389c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_COMMON_STARTUP), 390c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Startup folder. */ 391c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_STARTUP), 392c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 393c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Programs item in the start menu for all users. 394c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NT only */ 395c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_COMMON_PROGRAMS), 396c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Program item in the user's start menu. */ 397c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_PROGRAMS), 398bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 399bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* DEF_CSIDL(CSIDL_PROGRAM_FILES_COMMON), */ 400bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* DEF_CSIDL(CSIDL_PROGRAM_FILES), */ 401bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 402c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Virtual folder containing fonts. */ 403c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DEF_CSIDL(CSIDL_FONTS), 404bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 405bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 406bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define DIM(a) (sizeof(a) / sizeof((a)[0])) 407bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 408bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic PyObject *FileCreated(PyObject *self, PyObject *args) 409bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 410c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *path; 411c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!g_PyArg_ParseTuple(args, "s", &path)) 412c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 413c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou notify(FILE_CREATED, path); 414c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return g_Py_BuildValue(""); 415bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 416bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 417bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic PyObject *DirectoryCreated(PyObject *self, PyObject *args) 418bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 419c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *path; 420c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!g_PyArg_ParseTuple(args, "s", &path)) 421c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 422c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou notify(DIR_CREATED, path); 423c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return g_Py_BuildValue(""); 424bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 425bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 426bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic PyObject *GetSpecialFolderPath(PyObject *self, PyObject *args) 427bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 428c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *name; 429c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char lpszPath[MAX_PATH]; 430c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int i; 431c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou static HRESULT (WINAPI *My_SHGetSpecialFolderPath)(HWND hwnd, 432c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LPTSTR lpszPath, 433c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int nFolder, 434c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou BOOL fCreate); 435c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 436c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!My_SHGetSpecialFolderPath) { 437c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HINSTANCE hLib = LoadLibrary("shell32.dll"); 438c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!hLib) { 439c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 440c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "function not available"); 441c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 442c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 443c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou My_SHGetSpecialFolderPath = (BOOL (WINAPI *)(HWND, LPTSTR, 444c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int, BOOL)) 445c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetProcAddress(hLib, 446c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "SHGetSpecialFolderPathA"); 447c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 448c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 449c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!g_PyArg_ParseTuple(args, "s", &name)) 450c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 451c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 452c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!My_SHGetSpecialFolderPath) { 453c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, "function not available"); 454c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 455c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 456c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 457c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou for (i = 0; i < DIM(csidl_names); ++i) { 458c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (0 == strcmpi(csidl_names[i].name, name)) { 459c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int nFolder; 460c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou nFolder = csidl_names[i].nFolder; 461c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (My_SHGetSpecialFolderPath(NULL, lpszPath, 462c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou nFolder, 0)) 463c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return g_Py_BuildValue("s", lpszPath); 464c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else { 465c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 466c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "no such folder (%s)", name); 467c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 468c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 469c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 470c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 471c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou }; 472c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_ValueError, "unknown CSIDL (%s)", name); 473c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 474bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 475bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 476bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic PyObject *CreateShortcut(PyObject *self, PyObject *args) 477bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 478c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *path; /* path and filename */ 479c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *description; 480c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *filename; 481c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 482c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *arguments = NULL; 483c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *iconpath = NULL; 484c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int iconindex = 0; 485c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *workdir = NULL; 486c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 487c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou WCHAR wszFilename[MAX_PATH]; 488c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 489c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou IShellLink *ps1 = NULL; 490c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou IPersistFile *pPf = NULL; 491c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 492c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HRESULT hr; 493c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 494c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = CoInitialize(NULL); 495c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 496c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 497c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "CoInitialize failed, error 0x%x", hr); 498c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 499c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 500c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 501c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!g_PyArg_ParseTuple(args, "sss|sssi", 502c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &path, &description, &filename, 503c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &arguments, &workdir, &iconpath, &iconindex)) 504c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 505c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 506c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = CoCreateInstance(&CLSID_ShellLink, 507c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 508c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CLSCTX_INPROC_SERVER, 509c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &IID_IShellLink, 510c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &ps1); 511c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 512c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 513c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "CoCreateInstance failed, error 0x%x", hr); 514c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 515c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 516c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 517c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = ps1->lpVtbl->QueryInterface(ps1, &IID_IPersistFile, 518c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (void **)&pPf); 519c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 520c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 521c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "QueryInterface(IPersistFile) error 0x%x", hr); 522c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 523c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 524c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 525c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 526c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = ps1->lpVtbl->SetPath(ps1, path); 527c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 528c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 529c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "SetPath() failed, error 0x%x", hr); 530c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 531c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 532c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 533c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = ps1->lpVtbl->SetDescription(ps1, description); 534c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 535c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 536c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "SetDescription() failed, error 0x%x", hr); 537c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 538c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 539c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 540c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (arguments) { 541c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = ps1->lpVtbl->SetArguments(ps1, arguments); 542c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 543c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 544c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "SetArguments() error 0x%x", hr); 545c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 546c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 547c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 548c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 549c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (iconpath) { 550c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = ps1->lpVtbl->SetIconLocation(ps1, iconpath, iconindex); 551c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 552c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 553c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "SetIconLocation() error 0x%x", hr); 554c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 555c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 556c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 557c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 558c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (workdir) { 559c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = ps1->lpVtbl->SetWorkingDirectory(ps1, workdir); 560c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 561c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 562c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "SetWorkingDirectory() error 0x%x", hr); 563c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 564c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 565c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 566c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 567c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MultiByteToWideChar(CP_ACP, 0, 568c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou filename, -1, 569c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wszFilename, MAX_PATH); 570c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 571c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hr = pPf->lpVtbl->Save(pPf, wszFilename, TRUE); 572c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (FAILED(hr)) { 573c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format(g_PyExc_OSError, 574c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Failed to create shortcut '%s' - error 0x%x", filename, hr); 575c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto error; 576c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 577c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 578c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou pPf->lpVtbl->Release(pPf); 579c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ps1->lpVtbl->Release(ps1); 580c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CoUninitialize(); 581c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return g_Py_BuildValue(""); 582c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 583bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller error: 584c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (pPf) 585c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou pPf->lpVtbl->Release(pPf); 586bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 587c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ps1) 588c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ps1->lpVtbl->Release(ps1); 589bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 590c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CoUninitialize(); 591bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 592c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 593bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 594bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 595a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic PyObject *PyMessageBox(PyObject *self, PyObject *args) 596a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 597c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int rc; 598c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *text, *caption; 599c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int flags; 600c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!g_PyArg_ParseTuple(args, "ssi", &text, &caption, &flags)) 601c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 602c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou rc = MessageBox(GetFocus(), text, caption, flags); 603c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return g_Py_BuildValue("i", rc); 604a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 605a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 606f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammondstatic PyObject *GetRootHKey(PyObject *self) 607f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond{ 608c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return g_PyLong_FromVoidPtr(hkey_root); 609f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond} 610f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond 611bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define METH_VARARGS 0x0001 612f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond#define METH_NOARGS 0x0004 613f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammondtypedef PyObject *(*PyCFunction)(PyObject *, PyObject *); 614bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 615bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerPyMethodDef meth[] = { 616c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou {"create_shortcut", CreateShortcut, METH_VARARGS, NULL}, 617c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou {"get_special_folder_path", GetSpecialFolderPath, METH_VARARGS, NULL}, 618c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou {"get_root_hkey", (PyCFunction)GetRootHKey, METH_NOARGS, NULL}, 619c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou {"file_created", FileCreated, METH_VARARGS, NULL}, 620c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou {"directory_created", DirectoryCreated, METH_VARARGS, NULL}, 621c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou {"message_box", PyMessageBox, METH_VARARGS, NULL}, 622bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 623bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 62448340390ac23a66cc2251a12d8690207726b85beThomas Hellerstatic HINSTANCE LoadPythonDll(char *fname) 62548340390ac23a66cc2251a12d8690207726b85beThomas Heller{ 626c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char fullpath[_MAX_PATH]; 627c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LONG size = sizeof(fullpath); 628c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char subkey_name[80]; 629c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char buffer[260 + 12]; 630c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HINSTANCE h; 631c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 632c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* make sure PYTHONHOME is set, to that sys.path is initialized correctly */ 633c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(buffer, "PYTHONHOME=%s", python_dir); 634c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou _putenv(buffer); 635c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou h = LoadLibrary(fname); 636c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (h) 637c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return h; 638c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(subkey_name, 639c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "SOFTWARE\\Python\\PythonCore\\%d.%d\\InstallPath", 640c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou py_major, py_minor); 641c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ERROR_SUCCESS != RegQueryValue(HKEY_CURRENT_USER, subkey_name, 642c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fullpath, &size) && 643c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ERROR_SUCCESS != RegQueryValue(HKEY_LOCAL_MACHINE, subkey_name, 644c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fullpath, &size)) 645c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 646c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcat(fullpath, "\\"); 647c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcat(fullpath, fname); 648c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return LoadLibrary(fullpath); 64948340390ac23a66cc2251a12d8690207726b85beThomas Heller} 65048340390ac23a66cc2251a12d8690207726b85beThomas Heller 651a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic int prepare_script_environment(HINSTANCE hPython) 652a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 653c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PyObject *mod; 654c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, PyImport_ImportModule, (char *)); 655c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, int, PyObject_SetAttrString, (PyObject *, char *, PyObject *)); 656c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, PyObject_GetAttrString, (PyObject *, char *)); 657c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, PyCFunction_New, (PyMethodDef *, PyObject *)); 658c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...)); 659c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...)); 660c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *)); 661c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, PyLong_FromVoidPtr, (void *)); 662c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!PyImport_ImportModule || !PyObject_GetAttrString || 663c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou !PyObject_SetAttrString || !PyCFunction_New) 664c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; 665c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format) 666c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; 667c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 668c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou mod = PyImport_ImportModule("__builtin__"); 669c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (mod) { 670c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int i; 671c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyExc_ValueError = PyObject_GetAttrString(mod, "ValueError"); 672c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyExc_OSError = PyObject_GetAttrString(mod, "OSError"); 673c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou for (i = 0; i < DIM(meth); ++i) { 674c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PyObject_SetAttrString(mod, meth[i].ml_name, 675c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PyCFunction_New(&meth[i], NULL)); 676c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 677c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 678c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_Py_BuildValue = Py_BuildValue; 679c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyArg_ParseTuple = PyArg_ParseTuple; 680c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyErr_Format = PyErr_Format; 681c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou g_PyLong_FromVoidPtr = PyLong_FromVoidPtr; 682c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 683c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 684a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 685a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 686bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 687bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * This function returns one of the following error codes: 688bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 1 if the Python-dll does not export the functions we need 689bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 2 if no install-script is specified in pathname 690bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 3 if the install-script file could not be opened 6919f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller * the return value of PyRun_SimpleString() otherwise, 692bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * which is 0 if everything is ok, -1 if an exception had occurred 693bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * in the install-script. 694bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 695bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 696bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic int 6976ed1cb001416d6704a5af0f7d8c00ce3e5413d96Mark Hammonddo_run_installscript(HINSTANCE hPython, char *pathname, int argc, char **argv) 698bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 699c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int fh, result; 700c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, Py_Initialize, (void)); 701c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, int, PySys_SetArgv, (int, char **)); 702c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, int, PyRun_SimpleString, (char *)); 703c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, Py_Finalize, (void)); 704c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...)); 705c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, PyCFunction_New, 706c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (PyMethodDef *, PyObject *)); 707c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...)); 708c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *)); 709c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 710c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!Py_Initialize || !PySys_SetArgv 711c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou || !PyRun_SimpleString || !Py_Finalize) 712c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; 713c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 714c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format) 715c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; 716c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 717c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!PyCFunction_New || !PyArg_ParseTuple || !PyErr_Format) 718c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; 719c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 720c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (pathname == NULL || pathname[0] == '\0') 721c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 2; 722c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 723c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fh = open(pathname, _O_RDONLY); 724c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (-1 == fh) { 725c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(stderr, "Could not open postinstall-script %s\n", 726c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou pathname); 727c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 3; 728c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 729c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 730c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hDialog, IDC_INFO, "Running Script..."); 731c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 732c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Initialize(); 733c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 734c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou prepare_script_environment(hPython); 735c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PySys_SetArgv(argc, argv); 736c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = 3; 737c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { 738c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct _stat statbuf; 739c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if(0 == _fstat(fh, &statbuf)) { 740c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *script = alloca(statbuf.st_size + 5); 741c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int n = read(fh, script, statbuf.st_size); 742c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (n > 0) { 743c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou script[n] = '\n'; 744c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou script[n+1] = 0; 745c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = PyRun_SimpleString(script); 746c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 747c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 748c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 749c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Finalize(); 750c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 751c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou close(fh); 752c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return result; 7536ed1cb001416d6704a5af0f7d8c00ce3e5413d96Mark Hammond} 754bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 7556ed1cb001416d6704a5af0f7d8c00ce3e5413d96Mark Hammondstatic int 7566ed1cb001416d6704a5af0f7d8c00ce3e5413d96Mark Hammondrun_installscript(char *pathname, int argc, char **argv, char **pOutput) 7576ed1cb001416d6704a5af0f7d8c00ce3e5413d96Mark Hammond{ 758c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HINSTANCE hPython; 759c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int result = 1; 760c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int out_buf_size; 761c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HANDLE redirected, old_stderr, old_stdout; 762c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *tempname; 763c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 764c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *pOutput = NULL; 765c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 766c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou tempname = tempnam(NULL, NULL); 767c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // We use a static CRT while the Python version we load uses 768c2077b0d9b5bf99768c6f396bf7ae6c41b682465Ezio Melotti // the CRT from one of various possible DLLs. As a result we 769c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // need to redirect the standard handles using the API rather 770c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // than the CRT. 771c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou redirected = CreateFile( 772c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou tempname, 773c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GENERIC_WRITE | GENERIC_READ, 774c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE_SHARE_READ, 775c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 776c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CREATE_ALWAYS, 777c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 778c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL); 779c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou old_stdout = GetStdHandle(STD_OUTPUT_HANDLE); 780c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou old_stderr = GetStdHandle(STD_ERROR_HANDLE); 781c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetStdHandle(STD_OUTPUT_HANDLE, redirected); 782c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetStdHandle(STD_ERROR_HANDLE, redirected); 783c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 784c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hPython = LoadPythonDll(pythondll); 785c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hPython) { 786c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = do_run_installscript(hPython, pathname, argc, argv); 787c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FreeLibrary(hPython); 788c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else { 789c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(stderr, "*** Could not load Python ***"); 790c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 791c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetStdHandle(STD_OUTPUT_HANDLE, old_stdout); 792c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetStdHandle(STD_ERROR_HANDLE, old_stderr); 793c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou out_buf_size = min(GetFileSize(redirected, NULL), 4096); 794c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *pOutput = malloc(out_buf_size+1); 795c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (*pOutput) { 796c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD nread = 0; 797c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetFilePointer(redirected, 0, 0, FILE_BEGIN); 798c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ReadFile(redirected, *pOutput, out_buf_size, &nread, NULL); 799c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (*pOutput)[nread] = '\0'; 800c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 801c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CloseHandle(redirected); 802c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DeleteFile(tempname); 803c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return result; 804bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 805bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 806a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic int do_run_simple_script(HINSTANCE hPython, char *script) 807a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 808c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int rc; 809c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, Py_Initialize, (void)); 810c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, Py_SetProgramName, (char *)); 811c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, Py_Finalize, (void)); 812c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, int, PyRun_SimpleString, (char *)); 813c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DECLPROC(hPython, void, PyErr_Print, (void)); 814c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 815c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!Py_Initialize || !Py_SetProgramName || !Py_Finalize || 816c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou !PyRun_SimpleString || !PyErr_Print) 817c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return -1; 818c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 819c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_SetProgramName(modulename); 820c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Initialize(); 821c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou prepare_script_environment(hPython); 822c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou rc = PyRun_SimpleString(script); 823c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (rc) 824c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PyErr_Print(); 825c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Finalize(); 826c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return rc; 827a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 828a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 829a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic int run_simple_script(char *script) 830a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 831c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int rc; 832c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HINSTANCE hPython; 833c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *tempname = tempnam(NULL, NULL); 834c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // Redirect output using win32 API - see comments above... 835c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HANDLE redirected = CreateFile( 836c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou tempname, 837c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GENERIC_WRITE | GENERIC_READ, 838c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE_SHARE_READ, 839c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 840c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CREATE_ALWAYS, 841c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 842c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL); 843c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HANDLE old_stdout = GetStdHandle(STD_OUTPUT_HANDLE); 844c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HANDLE old_stderr = GetStdHandle(STD_ERROR_HANDLE); 845c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetStdHandle(STD_OUTPUT_HANDLE, redirected); 846c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetStdHandle(STD_ERROR_HANDLE, redirected); 847c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 848c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hPython = LoadPythonDll(pythondll); 849c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!hPython) { 850c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char reason[128]; 851c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(reason, "Can't load Python for pre-install script (%d)", GetLastError()); 852c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou set_failure_reason(reason); 853c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return -1; 854c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 855c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou rc = do_run_simple_script(hPython, script); 856c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FreeLibrary(hPython); 857c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetStdHandle(STD_OUTPUT_HANDLE, old_stdout); 858c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetStdHandle(STD_ERROR_HANDLE, old_stderr); 859c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* We only care about the output when we fail. If the script works 860c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou OK, then we discard it 861c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou */ 862c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (rc) { 863c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int err_buf_size; 864c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *err_buf; 865c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou const char *prefix = "Running the pre-installation script failed\r\n"; 866c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int prefix_len = strlen(prefix); 867c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou err_buf_size = GetFileSize(redirected, NULL); 868c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (err_buf_size==INVALID_FILE_SIZE) // an error - let's try anyway... 869c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou err_buf_size = 4096; 870c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou err_buf = malloc(prefix_len + err_buf_size + 1); 871c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (err_buf) { 872c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD n = 0; 873c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(err_buf, prefix); 874c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetFilePointer(redirected, 0, 0, FILE_BEGIN); 875c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ReadFile(redirected, err_buf+prefix_len, err_buf_size, &n, NULL); 876c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou err_buf[prefix_len+n] = '\0'; 877c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou set_failure_reason(err_buf); 878c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou free(err_buf); 879c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else { 880c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou set_failure_reason("Out of memory!"); 881c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 882c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 883c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CloseHandle(redirected); 884c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DeleteFile(tempname); 885c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return rc; 886a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 887a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 888a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 889bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL SystemError(int error, char *msg) 890bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 891c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char Buffer[1024]; 892c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int n; 893c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 894c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (error) { 895c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LPVOID lpMsgBuf; 896c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FormatMessage( 897c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FORMAT_MESSAGE_ALLOCATE_BUFFER | 898c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FORMAT_MESSAGE_FROM_SYSTEM, 899c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 900c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou error, 901c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 902c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (LPSTR)&lpMsgBuf, 903c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 904c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL 905c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ); 906c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strncpy(Buffer, lpMsgBuf, sizeof(Buffer)); 907c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LocalFree(lpMsgBuf); 908c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else 909c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Buffer[0] = '\0'; 910c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou n = lstrlen(Buffer); 911c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou _snprintf(Buffer+n, sizeof(Buffer)-n, msg); 912c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(hwndMain, Buffer, "Runtime Error", MB_OK | MB_ICONSTOP); 913c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 914bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 915bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 916bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL notify (int code, char *fmt, ...) 917bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 918c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char Buffer[1024]; 919c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou va_list marker; 920c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou BOOL result = TRUE; 921c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int a, b; 922c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *cp; 923bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 924c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou va_start(marker, fmt); 925c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou _vsnprintf(Buffer, sizeof(Buffer), fmt, marker); 926bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 927c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (code) { 928bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Questions */ 929c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case CAN_OVERWRITE: 930c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 931bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 932bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Information notification */ 933c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case DIR_CREATED: 934c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (logfile) 935c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "100 Made Dir: %s\n", fmt); 936c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 937c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 938c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case FILE_CREATED: 939c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (logfile) 940c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "200 File Copy: %s\n", fmt); 941c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto add_to_filelist_label; 942c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 943c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 944c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case FILE_OVERWRITTEN: 945c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (logfile) 946c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "200 File Overwrite: %s\n", fmt); 947c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou add_to_filelist_label: 948c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if ((cp = strrchr(fmt, '.')) && (0 == strcmp (cp, ".py"))) 949c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou add_to_filelist(fmt); 950c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 951bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 952bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Error Messages */ 953c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case ZLIB_ERROR: 954c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), Buffer, "Error", 955c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_OK | MB_ICONWARNING); 956c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 957c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 958c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case SYSTEM_ERROR: 959c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SystemError(GetLastError(), Buffer); 960c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 961c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 962c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case NUM_FILES: 963c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou a = va_arg(marker, int); 964c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou b = va_arg(marker, int); 965c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendMessage(hDialog, WM_NUMFILES, 0, MAKELPARAM(0, a)); 966c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendMessage(hDialog, WM_NEXTFILE, b,(LPARAM)fmt); 967c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 968c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou va_end(marker); 969c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 970c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return result; 971bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 972bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 973bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic char *MapExistingFile(char *pathname, DWORD *psize) 974bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 975c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HANDLE hFile, hFileMapping; 976c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD nSizeLow, nSizeHigh; 977c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *data; 978c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 979c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hFile = CreateFile(pathname, 980c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GENERIC_READ, FILE_SHARE_READ, NULL, 981c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou OPEN_EXISTING, 982c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE_ATTRIBUTE_NORMAL, NULL); 983c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hFile == INVALID_HANDLE_VALUE) 984c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 985c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou nSizeLow = GetFileSize(hFile, &nSizeHigh); 986c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hFileMapping = CreateFileMapping(hFile, 987c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, PAGE_READONLY, 0, 0, NULL); 988c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CloseHandle(hFile); 989c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 990c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hFileMapping == INVALID_HANDLE_VALUE) 991c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 992c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 993c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou data = MapViewOfFile(hFileMapping, 994c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE_MAP_READ, 0, 0, 0); 995c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 996c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CloseHandle(hFileMapping); 997c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *psize = nSizeLow; 998c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return data; 999bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1000bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1001bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1002bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void create_bitmap(HWND hwnd) 1003bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1004c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou BITMAPFILEHEADER *bfh; 1005c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou BITMAPINFO *bi; 1006c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HDC hdc; 1007bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1008c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!bitmap_bytes) 1009c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return; 1010bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1011c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hBitmap) 1012c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return; 1013bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1014c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hdc = GetDC(hwnd); 1015bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1016c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bfh = (BITMAPFILEHEADER *)bitmap_bytes; 1017c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bi = (BITMAPINFO *)(bitmap_bytes + sizeof(BITMAPFILEHEADER)); 1018bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1019c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hBitmap = CreateDIBitmap(hdc, 1020c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &bi->bmiHeader, 1021c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CBM_INIT, 1022c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bitmap_bytes + bfh->bfOffBits, 1023c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bi, 1024c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DIB_RGB_COLORS); 1025c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ReleaseDC(hwnd, hdc); 1026bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1027bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1028a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller/* Extract everything we need to begin the installation. Currently this 1029a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller is the INI filename with install data, and the raw pre-install script 1030a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller*/ 1031a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic BOOL ExtractInstallData(char *data, DWORD size, int *pexe_size, 1032c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char **out_ini_file, char **out_preinstall_script) 1033bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1034c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* read the end of central directory record */ 1035c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof 1036c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (struct eof_cdir)]; 1037c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1038c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir - 1039c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou pe->ofsCDir; 1040c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1041c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int ofs = arc_start - sizeof (struct meta_data_hdr); 1042c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1043c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* read meta_data info */ 1044c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct meta_data_hdr *pmd = (struct meta_data_hdr *)&data[ofs]; 1045c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *src, *dst; 1046c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *ini_file; 1047c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char tempdir[MAX_PATH]; 1048c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1049c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* ensure that if we fail, we don't have garbage out pointers */ 1050c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *out_ini_file = *out_preinstall_script = NULL; 1051c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1052c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (pe->tag != 0x06054b50) { 1053c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1054c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1055c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1056c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (pmd->tag != 0x1234567B) { 1057c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return SystemError(0, 1058c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Invalid cfgdata magic number (see bdist_wininst.py)"); 1059c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1060c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ofs < 0) { 1061c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1062c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1063c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1064c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (pmd->bitmap_size) { 1065c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Store pointer to bitmap bytes */ 1066c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bitmap_bytes = (char *)pmd - pmd->uncomp_size - pmd->bitmap_size; 1067c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1068c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1069c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *pexe_size = ofs - pmd->uncomp_size - pmd->bitmap_size; 1070c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1071c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou src = ((char *)pmd) - pmd->uncomp_size; 1072c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ini_file = malloc(MAX_PATH); /* will be returned, so do not free it */ 1073c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!ini_file) 1074c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1075c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!GetTempPath(sizeof(tempdir), tempdir) 1076c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou || !GetTempFileName(tempdir, "~du", 0, ini_file)) { 1077c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SystemError(GetLastError(), 1078c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Could not create temporary file"); 1079c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1080c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1081c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1082c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou dst = map_new_file(CREATE_ALWAYS, ini_file, NULL, pmd->uncomp_size, 1083c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 0, NULL/*notify*/); 1084c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!dst) 1085c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1086c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Up to the first \0 is the INI file data. */ 1087c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strncpy(dst, src, pmd->uncomp_size); 1088c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou src += strlen(dst) + 1; 1089c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Up to next \0 is the pre-install script */ 1090c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *out_preinstall_script = strdup(src); 1091c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *out_ini_file = ini_file; 1092c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou UnmapViewOfFile(dst); 1093c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 1094bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1095bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1096bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void PumpMessages(void) 1097bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1098c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MSG msg; 1099c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 1100c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou TranslateMessage(&msg); 1101c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DispatchMessage(&msg); 1102c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1103bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1104bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1105bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerLRESULT CALLBACK 1106bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1107bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1108c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HDC hdc; 1109c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HFONT hFont; 1110c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int h; 1111c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PAINTSTRUCT ps; 1112c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (msg) { 1113c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_PAINT: 1114c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hdc = BeginPaint(hwnd, &ps); 1115c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou h = GetSystemMetrics(SM_CYSCREEN) / 10; 1116c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hFont = CreateFont(h, 0, 0, 0, 700, TRUE, 1117c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 0, 0, 0, 0, 0, 0, "Times Roman"); 1118c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hFont = SelectObject(hdc, hFont); 1119c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetBkMode(hdc, TRANSPARENT); 1120c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou TextOut(hdc, 15, 15, title, strlen(title)); 1121c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetTextColor(hdc, RGB(255, 255, 255)); 1122c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou TextOut(hdc, 10, 10, title, strlen(title)); 1123c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DeleteObject(SelectObject(hdc, hFont)); 1124c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou EndPaint(hwnd, &ps); 1125c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 1126c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1127c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return DefWindowProc(hwnd, msg, wParam, lParam); 1128bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1129bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1130bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic HWND CreateBackground(char *title) 1131bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1132c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou WNDCLASS wc; 1133c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HWND hwnd; 1134c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char buffer[4096]; 1135c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1136c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.style = CS_VREDRAW | CS_HREDRAW; 1137c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.lpfnWndProc = WindowProc; 1138c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.cbWndExtra = 0; 1139c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.cbClsExtra = 0; 1140c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.hInstance = GetModuleHandle(NULL); 1141c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.hIcon = NULL; 1142c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.hCursor = LoadCursor(NULL, IDC_ARROW); 1143c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 128)); 1144c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.lpszMenuName = NULL; 1145c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wc.lpszClassName = "SetupWindowClass"; 1146c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1147c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!RegisterClass(&wc)) 1148c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(hwndMain, 1149c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Could not register window class", 1150c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Setup.exe", MB_OK); 1151c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1152c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(buffer, "Setup %s", title); 1153c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hwnd = CreateWindow("SetupWindowClass", 1154c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou buffer, 1155c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 1156c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 0, 1157c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetSystemMetrics(SM_CXFULLSCREEN), 1158c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetSystemMetrics(SM_CYFULLSCREEN), 1159c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 1160c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 1161c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetModuleHandle(NULL), 1162c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL); 1163c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ShowWindow(hwnd, SW_SHOWMAXIMIZED); 1164c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou UpdateWindow(hwnd); 1165c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return hwnd; 1166bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1167bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1168bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1169bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Center a window on the screen 1170bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1171bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void CenterWindow(HWND hwnd) 1172bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1173c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RECT rc; 1174c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int w, h; 1175c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1176c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetWindowRect(hwnd, &rc); 1177c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou w = GetSystemMetrics(SM_CXSCREEN); 1178c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou h = GetSystemMetrics(SM_CYSCREEN); 1179c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MoveWindow(hwnd, 1180c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (w - (rc.right-rc.left))/2, 1181c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (h - (rc.bottom-rc.top))/2, 1182c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou rc.right-rc.left, rc.bottom-rc.top, FALSE); 1183bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1184bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1185bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <prsht.h> 1186bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1187bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL CALLBACK 1188bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerIntroDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1189bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1190c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LPNMHDR lpnm; 1191c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char Buffer[4096]; 1192c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1193c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (msg) { 1194c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_INITDIALOG: 1195c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou create_bitmap(hwnd); 1196c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if(hBitmap) 1197c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, 1198c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou IMAGE_BITMAP, (LPARAM)hBitmap); 1199c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CenterWindow(GetParent(hwnd)); 1200c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(Buffer, 1201c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "This Wizard will install %s on your computer. " 1202c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Click Next to continue " 1203c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "or Cancel to exit the Setup Wizard.", 1204c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou meta_name); 1205c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, Buffer); 1206c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_INTRO_TEXT, info); 1207c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_BUILD_INFO, build_info); 1208c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1209c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1210c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_NOTIFY: 1211c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou lpnm = (LPNMHDR) lParam; 1212c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1213c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (lpnm->code) { 1214c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_SETACTIVE: 1215c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT); 1216c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1217c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1218c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_WIZNEXT: 1219c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1220c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1221c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_RESET: 1222c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1223c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1224c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou default: 1225c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1226c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1227c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1228c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1229bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1230bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1231bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#ifdef USE_OTHER_PYTHON_VERSIONS 1232bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* These are really private variables used to communicate 1233bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * between StatusRoutine and CheckPythonExe 1234bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1235bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar bound_image_dll[_MAX_PATH]; 1236bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint bound_image_major; 1237bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint bound_image_minor; 1238bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1239bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL __stdcall StatusRoutine(IMAGEHLP_STATUS_REASON reason, 1240c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PSTR ImageName, 1241c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PSTR DllName, 1242c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ULONG Va, 1243c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ULONG Parameter) 1244bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1245c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char fname[_MAX_PATH]; 1246c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int int_version; 1247c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1248c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch(reason) { 1249c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindOutOfMemory: 1250c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindRvaToVaFailed: 1251c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindNoRoomInImage: 1252c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindImportProcedureFailed: 1253c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1254c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1255c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindImportProcedure: 1256c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindForwarder: 1257c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindForwarderNOT: 1258c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindImageModified: 1259c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindExpandFileHeaders: 1260c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindImageComplete: 1261c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindSymbolsNotUpdated: 1262c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindMismatchedSymbols: 1263c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindImportModuleFailed: 1264c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1265c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1266c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case BindImportModule: 1267c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (1 == sscanf(DllName, "python%d", &int_version)) { 1268c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SearchPath(NULL, DllName, NULL, sizeof(fname), 1269c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fname, NULL); 1270c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(bound_image_dll, fname); 1271c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bound_image_major = int_version / 10; 1272c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bound_image_minor = int_version % 10; 1273c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou OutputDebugString("BOUND "); 1274c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou OutputDebugString(fname); 1275c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou OutputDebugString("\n"); 1276c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1277c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1278c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1279c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 1280bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1281bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1282bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1283bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1284bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic LPSTR get_sys_prefix(LPSTR exe, LPSTR dll) 1285bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1286c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou void (__cdecl * Py_Initialize)(void); 1287c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou void (__cdecl * Py_SetProgramName)(char *); 1288c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou void (__cdecl * Py_Finalize)(void); 1289c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou void* (__cdecl * PySys_GetObject)(char *); 1290c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou void (__cdecl * PySys_SetArgv)(int, char **); 1291c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char* (__cdecl * Py_GetPrefix)(void); 1292c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char* (__cdecl * Py_GetPath)(void); 1293c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HINSTANCE hPython; 1294c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LPSTR prefix = NULL; 1295c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int (__cdecl * PyRun_SimpleString)(char *); 1296c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1297c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { 1298c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char Buffer[256]; 1299c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(Buffer, "PYTHONHOME=%s", exe); 1300c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *strrchr(Buffer, '\\') = '\0'; 1301c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou// MessageBox(GetFocus(), Buffer, "PYTHONHOME", MB_OK); 1302c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou _putenv(Buffer); 1303c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou _putenv("PYTHONPATH="); 1304c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1305c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1306c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hPython = LoadLibrary(dll); 1307c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!hPython) 1308c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return NULL; 1309c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Initialize = (void (*)(void))GetProcAddress 1310c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (hPython,"Py_Initialize"); 1311c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1312c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PySys_SetArgv = (void (*)(int, char **))GetProcAddress 1313c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (hPython,"PySys_SetArgv"); 1314c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1315c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PyRun_SimpleString = (int (*)(char *))GetProcAddress 1316c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (hPython,"PyRun_SimpleString"); 1317c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1318c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_SetProgramName = (void (*)(char *))GetProcAddress 1319c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (hPython,"Py_SetProgramName"); 1320c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1321c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PySys_GetObject = (void* (*)(char *))GetProcAddress 1322c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (hPython,"PySys_GetObject"); 1323c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1324c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_GetPrefix = (char * (*)(void))GetProcAddress 1325c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (hPython,"Py_GetPrefix"); 1326c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1327c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_GetPath = (char * (*)(void))GetProcAddress 1328c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (hPython,"Py_GetPath"); 1329c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1330c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Finalize = (void (*)(void))GetProcAddress(hPython, 1331c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Py_Finalize"); 1332c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_SetProgramName(exe); 1333c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Initialize(); 1334c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PySys_SetArgv(1, &exe); 1335c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1336c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), Py_GetPrefix(), "PREFIX", MB_OK); 1337c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), Py_GetPath(), "PATH", MB_OK); 1338c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1339c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Py_Finalize(); 1340c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FreeLibrary(hPython); 1341c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1342c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return prefix; 1343bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1344bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1345bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL 1346bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerCheckPythonExe(LPSTR pathname, LPSTR version, int *pmajor, int *pminor) 1347bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1348c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bound_image_dll[0] = '\0'; 1349c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!BindImageEx(BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE | BIND_ALL_IMAGES, 1350c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou pathname, 1351c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 1352c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 1353c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou StatusRoutine)) 1354c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return SystemError(0, "Could not bind image"); 1355c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (bound_image_dll[0] == '\0') 1356c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return SystemError(0, "Does not seem to be a python executable"); 1357c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *pmajor = bound_image_major; 1358c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *pminor = bound_image_minor; 1359c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (version && *version) { 1360c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char core_version[12]; 1361c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(core_version, "%d.%d", bound_image_major, bound_image_minor); 1362c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (strcmp(version, core_version)) 1363c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return SystemError(0, "Wrong Python version"); 1364c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1365c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou get_sys_prefix(pathname, bound_image_dll); 1366c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 1367bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1368bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1369bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1370bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Browse for other python versions. Insert it into the listbox specified 1371bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * by hwnd. version, if not NULL or empty, is the version required. 1372bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1373bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL GetOtherPythonVersion(HWND hwnd, LPSTR version) 1374bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1375c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char vers_name[_MAX_PATH + 80]; 1376c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD itemindex; 1377c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou OPENFILENAME of; 1378c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char pathname[_MAX_PATH]; 1379c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD result; 1380c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1381c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(pathname, "python.exe"); 1382c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1383c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou memset(&of, 0, sizeof(of)); 1384c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.lStructSize = sizeof(OPENFILENAME); 1385c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.hwndOwner = GetParent(hwnd); 1386c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.hInstance = NULL; 1387c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.lpstrFilter = "python.exe\0python.exe\0"; 1388c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.lpstrCustomFilter = NULL; 1389c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.nMaxCustFilter = 0; 1390c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.nFilterIndex = 1; 1391c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.lpstrFile = pathname; 1392c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.nMaxFile = sizeof(pathname); 1393c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.lpstrFileTitle = NULL; 1394c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.nMaxFileTitle = 0; 1395c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.lpstrInitialDir = NULL; 1396c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.lpstrTitle = "Python executable"; 1397c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; 1398c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou of.lpstrDefExt = "exe"; 1399c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1400c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = GetOpenFileName(&of); 1401c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result) { 1402c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int major, minor; 1403c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!CheckPythonExe(pathname, version, &major, &minor)) { 1404c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1405c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1406c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *strrchr(pathname, '\\') = '\0'; 1407c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(vers_name, "Python Version %d.%d in %s", 1408c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou major, minor, pathname); 1409c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou itemindex = SendMessage(hwnd, LB_INSERTSTRING, -1, 1410c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (LPARAM)(LPSTR)vers_name); 1411c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendMessage(hwnd, LB_SETCURSEL, itemindex, 0); 1412c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendMessage(hwnd, LB_SETITEMDATA, itemindex, 1413c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (LPARAM)(LPSTR)strdup(pathname)); 1414c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 1415c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1416c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1417bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1418bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#endif /* USE_OTHER_PYTHON_VERSIONS */ 1419bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1420f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammondtypedef struct _InstalledVersionInfo { 1421f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond char prefix[MAX_PATH+1]; // sys.prefix directory. 1422f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond HKEY hkey; // Is this Python in HKCU or HKLM? 1423f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond} InstalledVersionInfo; 1424f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond 1425bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1426bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1427bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Fill the listbox specified by hwnd with all python versions found 1428bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * in the registry. version, if not NULL or empty, is the version 1429bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * required. 1430bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1431bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL GetPythonVersions(HWND hwnd, HKEY hkRoot, LPSTR version) 1432bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1433c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD index = 0; 1434c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char core_version[80]; 1435c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY hKey; 1436c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou BOOL result = TRUE; 1437c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD bufsize; 1438c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1439c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ERROR_SUCCESS != RegOpenKeyEx(hkRoot, 1440c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Software\\Python\\PythonCore", 1441c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, KEY_READ, &hKey)) 1442c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1443c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bufsize = sizeof(core_version); 1444c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index, 1445c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou core_version, &bufsize, NULL, 1446c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, NULL, NULL)) { 1447c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char subkey_name[80], vers_name[80]; 1448c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int itemindex; 1449c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD value_size; 1450c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY hk; 1451c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1452c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bufsize = sizeof(core_version); 1453c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++index; 1454c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (version && *version && strcmp(version, core_version)) 1455c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou continue; 1456c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1457c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(vers_name, "Python Version %s (found in registry)", 1458c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou core_version); 1459c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(subkey_name, 1460c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Software\\Python\\PythonCore\\%s\\InstallPath", 1461c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou core_version); 1462c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ERROR_SUCCESS == RegOpenKeyEx(hkRoot, subkey_name, 0, KEY_READ, &hk)) { 1463c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou InstalledVersionInfo *ivi = 1464c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (InstalledVersionInfo *)malloc(sizeof(InstalledVersionInfo)); 1465c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou value_size = sizeof(ivi->prefix); 1466c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ivi && 1467c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ERROR_SUCCESS == RegQueryValueEx(hk, NULL, NULL, NULL, 1468c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ivi->prefix, &value_size)) { 1469c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou itemindex = SendMessage(hwnd, LB_ADDSTRING, 0, 1470c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (LPARAM)(LPSTR)vers_name); 1471c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ivi->hkey = hkRoot; 1472c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendMessage(hwnd, LB_SETITEMDATA, itemindex, 1473c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (LPARAM)(LPSTR)ivi); 1474c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1475c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RegCloseKey(hk); 1476c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1477c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1478c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RegCloseKey(hKey); 1479c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return result; 1480bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1481bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1482f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond/* Determine if the current user can write to HKEY_LOCAL_MACHINE */ 1483f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark HammondBOOL HasLocalMachinePrivs() 1484f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond{ 1485c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY hKey; 1486c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD result; 1487c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou static char KeyName[] = 1488c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; 1489c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1490c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 1491c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KeyName, 1492c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 1493c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KEY_CREATE_SUB_KEY, 1494c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &hKey); 1495c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result==0) 1496c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RegCloseKey(hKey); 1497c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return result==0; 1498f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond} 1499f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond 1500f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// Check the root registry key to use - either HKLM or HKCU. 1501f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// If Python is installed in HKCU, then our extension also must be installed 1502f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// in HKCU - as Python won't be available for other users, we shouldn't either 1503f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// (and will fail if we are!) 1504f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// If Python is installed in HKLM, then we will also prefer to use HKLM, but 1505f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// this may not be possible - so we silently fall back to HKCU. 1506f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// 1507f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// We assume hkey_root is already set to where Python itself is installed. 1508f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammondvoid CheckRootKey(HWND hwnd) 1509f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond{ 1510c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hkey_root==HKEY_CURRENT_USER) { 1511c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ; // as above, always install ourself in HKCU too. 1512c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else if (hkey_root==HKEY_LOCAL_MACHINE) { 1513c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // Python in HKLM, but we may or may not have permissions there. 1514c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // Open the uninstall key with 'create' permissions - if this fails, 1515c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // we don't have permission. 1516c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!HasLocalMachinePrivs()) 1517c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hkey_root = HKEY_CURRENT_USER; 1518c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else { 1519c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(hwnd, "Don't know Python's installation type", 1520c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Strange", MB_OK | MB_ICONSTOP); 1521c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Default to wherever they can, but preferring HKLM */ 1522c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hkey_root = HasLocalMachinePrivs() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 1523c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1524f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond} 1525f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond 1526bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Return the installation scheme depending on Python version number */ 1527bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerSCHEME *GetScheme(int major, int minor) 1528bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1529c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (major > 2) 1530c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return new_scheme; 1531c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else if((major == 2) && (minor >= 2)) 1532c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return new_scheme; 1533c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return old_scheme; 1534bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1535bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1536bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL CALLBACK 1537bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerSelectPythonDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1538bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1539c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LPNMHDR lpnm; 1540c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1541c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (msg) { 1542c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_INITDIALOG: 1543c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hBitmap) 1544c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, 1545c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou IMAGE_BITMAP, (LPARAM)hBitmap); 1546c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST), 1547c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY_LOCAL_MACHINE, target_version); 1548c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST), 1549c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY_CURRENT_USER, target_version); 1550c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { /* select the last entry which is the highest python 1551c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou version found */ 1552c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int count; 1553c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou count = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 1554c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LB_GETCOUNT, 0, 0); 1555c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (count && count != LB_ERR) 1556c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, LB_SETCURSEL, 1557c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou count-1, 0); 1558c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1559c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* If a specific Python version is required, 1560c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * display a prominent notice showing this fact. 1561c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou */ 1562c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (target_version && target_version[0]) { 1563c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char buffer[4096]; 1564c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(buffer, 1565c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Python %s is required for this package. " 1566c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Select installation to use:", 1567c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou target_version); 1568c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, buffer); 1569c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1570c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1571c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (count == 0) { 1572c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char Buffer[4096]; 1573c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *msg; 1574c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (target_version && target_version[0]) { 1575c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(Buffer, 1576c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Python version %s required, which was not found" 1577c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou " in the registry.", target_version); 1578c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou msg = Buffer; 1579c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else 1580c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou msg = "No Python installation found in the registry."; 1581c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(hwnd, msg, "Cannot install", 1582c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_OK | MB_ICONSTOP); 1583c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1584c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1585c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou goto UpdateInstallDir; 1586c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1587c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1588c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_COMMAND: 1589c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (LOWORD(wParam)) { 1590bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1591bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller case IDC_OTHERPYTHON: 1592bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller if (GetOtherPythonVersion(GetDlgItem(hwnd, IDC_VERSIONS_LIST), 1593bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller target_version)) 1594bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller goto UpdateInstallDir; 1595bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller break; 1596bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller*/ 1597c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case IDC_VERSIONS_LIST: 1598c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (HIWORD(wParam)) { 1599c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int id; 1600c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case LBN_SELCHANGE: 1601c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou UpdateInstallDir: 1602c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 1603c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PSWIZB_BACK | PSWIZB_NEXT); 1604c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 1605c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LB_GETCURSEL, 0, 0); 1606c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (id == LB_ERR) { 1607c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 1608c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PSWIZB_BACK); 1609c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_PATH, ""); 1610c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_INSTALL_PATH, ""); 1611c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(python_dir, ""); 1612c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(pythondll, ""); 1613c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else { 1614c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *pbuf; 1615c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int result; 1616c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou InstalledVersionInfo *ivi; 1617c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 1618c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PSWIZB_BACK | PSWIZB_NEXT); 1619c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Get the python directory */ 1620ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter ivi = (InstalledVersionInfo *) 1621c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, 1622ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter IDC_VERSIONS_LIST, 1623ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter LB_GETITEMDATA, 1624ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter id, 1625ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter 0); 1626ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter hkey_root = ivi->hkey; 1627ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter strcpy(python_dir, ivi->prefix); 1628ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter SetDlgItemText(hwnd, IDC_PATH, python_dir); 1629ca56dd4767617a2f5e946130de4beb06442a5cd5Martin Panter /* retrieve the python version and pythondll to use */ 1630c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 1631c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LB_GETTEXTLEN, (WPARAM)id, 0); 1632c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou pbuf = (char *)malloc(result + 1); 1633c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (pbuf) { 1634c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* guess the name of the python-dll */ 1635c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 1636c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LB_GETTEXT, (WPARAM)id, 1637c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou (LPARAM)pbuf); 1638c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = sscanf(pbuf, "Python Version %d.%d", 1639c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &py_major, &py_minor); 1640c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result == 2) { 1641bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#ifdef _DEBUG 1642c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(pythondll, "python%d%d_d.dll", 1643c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou py_major, py_minor); 1644bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#else 1645c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(pythondll, "python%d%d.dll", 1646c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou py_major, py_minor); 1647bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#endif 1648c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1649c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou free(pbuf); 1650c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else 1651c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(pythondll, ""); 1652c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* retrieve the scheme for this version */ 1653c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { 1654c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char install_path[_MAX_PATH]; 1655c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SCHEME *scheme = GetScheme(py_major, py_minor); 1656c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(install_path, python_dir); 1657c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (install_path[strlen(install_path)-1] != '\\') 1658c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcat(install_path, "\\"); 1659c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcat(install_path, scheme[0].prefix); 1660c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_INSTALL_PATH, install_path); 1661c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1662c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1663c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1664c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1665c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1666c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 1667c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1668c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_NOTIFY: 1669c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou lpnm = (LPNMHDR) lParam; 1670c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1671c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (lpnm->code) { 1672c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int id; 1673c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_SETACTIVE: 1674c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 1675c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LB_GETCURSEL, 0, 0); 1676c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (id == LB_ERR) 1677c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 1678c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PSWIZB_BACK); 1679c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else 1680c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 1681c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PSWIZB_BACK | PSWIZB_NEXT); 1682c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1683c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1684c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_WIZNEXT: 1685c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1686c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1687c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_WIZFINISH: 1688c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1689c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1690c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_RESET: 1691c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1692c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1693c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou default: 1694c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1695c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1696c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1697c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 1698bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1699bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1700bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL OpenLogfile(char *dir) 1701bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1702c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char buffer[_MAX_PATH+1]; 1703c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou time_t ltime; 1704c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct tm *now; 1705c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou long result; 1706c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY hKey, hSubkey; 1707c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char subkey_name[256]; 1708c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou static char KeyName[] = 1709c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; 1710c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou const char *root_name = (hkey_root==HKEY_LOCAL_MACHINE ? 1711c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER"); 1712c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DWORD disposition; 1713c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1714c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Use Create, as the Uninstall subkey may not exist under HKCU. 1715c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Use CreateKeyEx, so we can specify a SAM specifying write access 1716c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou */ 1717c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegCreateKeyEx(hkey_root, 1718c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KeyName, 1719c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, /* reserved */ 1720c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, /* class */ 1721c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, /* options */ 1722c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KEY_CREATE_SUB_KEY, /* sam */ 1723c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, /* security */ 1724c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &hKey, /* result key */ 1725c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL); /* disposition */ 1726c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result != ERROR_SUCCESS) { 1727c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result == ERROR_ACCESS_DENIED) { 1728c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* This should no longer be able to happen - we have already 1729c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou checked if they have permissions in HKLM, and all users 1730c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou should have write access to HKCU. 1731c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou */ 1732c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), 1733c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "You do not seem to have sufficient access rights\n" 1734c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "on this machine to install this software", 1735c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 1736c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_OK | MB_ICONSTOP); 1737c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 1738c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else { 1739c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), KeyName, "Could not open key", MB_OK); 1740c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1741c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1742c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1743c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sprintf(buffer, "%s\\%s-wininst.log", dir, meta_name); 1744c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou logfile = fopen(buffer, "a"); 1745209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson if (!logfile) { 1746209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson char error[1024]; 1747209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson 1748209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson sprintf(error, "Can't create \"%s\" (%s).\n\n" 1749209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson "Try to execute the installer as administrator.", 1750209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson buffer, strerror(errno)); 1751209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson MessageBox(GetFocus(), error, NULL, MB_OK | MB_ICONSTOP); 1752209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson return FALSE; 1753209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson } 1754209dd468fb233be5691639024212ff291da3f5b2Benjamin Peterson 1755c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou time(<ime); 1756c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou now = localtime(<ime); 1757c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strftime(buffer, sizeof(buffer), 1758c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "*** Installation started %Y/%m/%d %H:%M ***\n", 1759c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou localtime(<ime)); 1760c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, buffer); 1761c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "Source: %s\n", modulename); 1762c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1763c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Root key must be first entry processed by uninstaller. */ 1764c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "999 Root Key: %s\n", root_name); 1765c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1766c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sprintf(subkey_name, "%s-py%d.%d", meta_name, py_major, py_minor); 1767c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1768c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegCreateKeyEx(hKey, subkey_name, 1769c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, NULL, 0, 1770c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KEY_WRITE, 1771c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 1772c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &hSubkey, 1773c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &disposition); 1774c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1775c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result != ERROR_SUCCESS) 1776c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), subkey_name, "Could not create key", MB_OK); 1777c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1778c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RegCloseKey(hKey); 1779c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1780c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (disposition == REG_CREATED_NEW_KEY) 1781c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "020 Reg DB Key: [%s]%s\n", KeyName, subkey_name); 1782c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1783c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sprintf(buffer, "Python %d.%d %s", py_major, py_minor, title); 1784c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1785c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegSetValueEx(hSubkey, "DisplayName", 1786c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 1787c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou REG_SZ, 1788c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou buffer, 1789c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strlen(buffer)+1); 1790c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1791c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result != ERROR_SUCCESS) 1792c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK); 1793c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1794c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n", 1795c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KeyName, subkey_name, "DisplayName", buffer); 1796c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1797c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou { 1798c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE *fp; 1799c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sprintf(buffer, "%s\\Remove%s.exe", dir, meta_name); 1800c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fp = fopen(buffer, "wb"); 1801c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fwrite(arc_data, exe_size, 1, fp); 1802c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fclose(fp); 1803c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1804c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sprintf(buffer, "\"%s\\Remove%s.exe\" -u \"%s\\%s-wininst.log\"", 1805c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou dir, meta_name, dir, meta_name); 1806c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1807c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegSetValueEx(hSubkey, "UninstallString", 1808c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 1809c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou REG_SZ, 1810c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou buffer, 1811c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strlen(buffer)+1); 1812c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1813c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result != ERROR_SUCCESS) 1814c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK); 1815c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1816c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n", 1817c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KeyName, subkey_name, "UninstallString", buffer); 1818c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1819c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 1820bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1821bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1822bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void CloseLogfile(void) 1823bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1824c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char buffer[_MAX_PATH+1]; 1825c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou time_t ltime; 1826c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou struct tm *now; 1827c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1828c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou time(<ime); 1829c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou now = localtime(<ime); 1830c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strftime(buffer, sizeof(buffer), 1831c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "*** Installation finished %Y/%m/%d %H:%M ***\n", 1832c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou localtime(<ime)); 1833c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, buffer); 1834c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (logfile) 1835c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fclose(logfile); 1836bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1837bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1838bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL CALLBACK 1839bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerInstallFilesDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1840bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1841c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LPNMHDR lpnm; 1842c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char Buffer[4096]; 1843c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SCHEME *scheme; 1844c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1845c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (msg) { 1846c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_INITDIALOG: 1847c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hBitmap) 1848c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, 1849c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou IMAGE_BITMAP, (LPARAM)hBitmap); 1850c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(Buffer, 1851c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Click Next to begin the installation of %s. " 1852c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "If you want to review or change any of your " 1853c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou " installation settings, click Back. " 1854c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Click Cancel to exit the wizard.", 1855c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou meta_name); 1856c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, Buffer); 1857c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_INFO, "Ready to install"); 1858c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1859c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1860c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_NUMFILES: 1861c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, lParam); 1862c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PumpMessages(); 1863c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 1864c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1865c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_NEXTFILE: 1866c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, wParam, 1867c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0); 1868c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_INFO, (LPSTR)lParam); 1869c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PumpMessages(); 1870c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 1871c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1872c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_NOTIFY: 1873c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou lpnm = (LPNMHDR) lParam; 1874c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1875c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (lpnm->code) { 1876c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_SETACTIVE: 1877c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 1878c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PSWIZB_BACK | PSWIZB_NEXT); 1879c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1880c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1881c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_WIZFINISH: 1882c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1883c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1884c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_WIZNEXT: 1885c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Handle a Next button click here */ 1886c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hDialog = hwnd; 1887c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou success = TRUE; 1888c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1889c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Disable the buttons while we work. Sending CANCELTOCLOSE has 1890c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou the effect of disabling the cancel button, which is a) as we 1891c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou do everything synchronously we can't cancel, and b) the next 1892c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou step is 'finished', when it is too late to cancel anyway. 1893c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou The next step being 'Finished' means we also don't need to 1894c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou restore the button state back */ 1895c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 0); 1896c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendMessage(GetParent(hwnd), PSM_CANCELTOCLOSE, 0, 0); 1897c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Make sure the installation directory name ends in a */ 1898c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* backslash */ 1899c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (python_dir[strlen(python_dir)-1] != '\\') 1900c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcat(python_dir, "\\"); 1901c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Strip the trailing backslash again */ 1902c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou python_dir[strlen(python_dir)-1] = '\0'; 1903c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1904c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CheckRootKey(hwnd); 1905c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1906c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!OpenLogfile(python_dir)) 1907c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1908bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1909bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1910bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * The scheme we have to use depends on the Python version... 1911bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller if sys.version < "2.2": 1912f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka WINDOWS_SCHEME = { 1913f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'purelib': '$base', 1914f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'platlib': '$base', 1915f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'headers': '$base/Include/$dist_name', 1916f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'scripts': '$base/Scripts', 1917f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'data' : '$base', 1918f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka } 1919bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller else: 1920f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka WINDOWS_SCHEME = { 1921f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'purelib': '$base/Lib/site-packages', 1922f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'platlib': '$base/Lib/site-packages', 1923f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'headers': '$base/Include/$dist_name', 1924f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'scripts': '$base/Scripts', 1925f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka 'data' : '$base', 1926f0aa88f6e856710c4cf5bdb23a81817a841c4553Serhiy Storchaka } 1927bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller*/ 1928c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou scheme = GetScheme(py_major, py_minor); 1929c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Run the pre-install script. */ 1930c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (pre_install_script && *pre_install_script) { 1931c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText (hwnd, IDC_TITLE, 1932c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Running pre-installation script"); 1933c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou run_simple_script(pre_install_script); 1934c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1935c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!success) { 1936c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1937c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1938c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Extract all files from the archive */ 1939c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, "Installing files..."); 1940c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!unzip_archive (scheme, 1941c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou python_dir, arc_data, 1942c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou arc_size, notify)) 1943c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou set_failure_reason("Failed to unzip installation files"); 1944c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Compile the py-files */ 1945c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (success && pyc_compile) { 1946c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int errors; 1947c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HINSTANCE hPython; 1948c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, 1949c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Compiling files to .pyc..."); 1950c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1951c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hDialog, IDC_INFO, "Loading python..."); 1952c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hPython = LoadPythonDll(pythondll); 1953c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hPython) { 1954c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou errors = compile_filelist(hPython, FALSE); 1955c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FreeLibrary(hPython); 1956c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1957c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Compilation errors are intentionally ignored: 1958c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * Python2.0 contains a bug which will result 1959c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * in sys.path containing garbage under certain 1960c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * circumstances, and an error message will only 1961c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * confuse the user. 1962c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou */ 1963c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1964c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (success && pyo_compile) { 1965c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int errors; 1966c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HINSTANCE hPython; 1967c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, 1968c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Compiling files to .pyo..."); 1969c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1970c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hDialog, IDC_INFO, "Loading python..."); 1971c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hPython = LoadPythonDll(pythondll); 1972c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hPython) { 1973c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou errors = compile_filelist(hPython, TRUE); 1974c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FreeLibrary(hPython); 1975c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1976c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Errors ignored: see above */ 1977c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1978c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1979c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1980c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1981c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1982c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_RESET: 1983c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1984c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1985c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou default: 1986c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 1987c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1988c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 1989c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 1990bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1991bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1992bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1993bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL CALLBACK 1994bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerFinishedDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1995bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1996c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LPNMHDR lpnm; 1997c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 1998c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (msg) { 1999c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_INITDIALOG: 2000c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hBitmap) 2001c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, 2002c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou IMAGE_BITMAP, (LPARAM)hBitmap); 2003c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!success) 2004c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_INFO, get_failure_reason()); 2005c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2006c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* async delay: will show the dialog box completely before 2007c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou the install_script is started */ 2008c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PostMessage(hwnd, WM_USER, 0, 0L); 2009c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 2010c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2011c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_USER: 2012c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2013c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (success && install_script && install_script[0]) { 2014c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char fname[MAX_PATH]; 2015c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *buffer; 2016c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HCURSOR hCursor; 2017c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int result; 2018c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2019c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *argv[3] = {NULL, "-install", NULL}; 2020c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2021c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, 2022c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Please wait while running postinstall script..."); 2023c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(fname, python_dir); 2024c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcat(fname, "\\Scripts\\"); 2025c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcat(fname, install_script); 2026c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2027c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (logfile) 2028c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(logfile, "300 Run Script: [%s]%s\n", pythondll, fname); 2029c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2030c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); 2031c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2032c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou argv[0] = fname; 2033c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2034c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = run_installscript(fname, 2, argv, &buffer); 2035c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (0 != result) { 2036c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(stderr, "*** run_installscript: internal error 0x%X ***\n", result); 2037c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2038c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (buffer) 2039c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_INFO, buffer); 2040c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, 2041c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Postinstall script finished.\n" 2042c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Click the Finish button to exit the Setup wizard."); 2043c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2044c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou free(buffer); 2045c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetCursor(hCursor); 2046c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CloseLogfile(); 2047c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2048c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2049c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 2050c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2051c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case WM_NOTIFY: 2052c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou lpnm = (LPNMHDR) lParam; 2053c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2054c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou switch (lpnm->code) { 2055c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_SETACTIVE: /* Enable the Finish button */ 2056c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH); 2057c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 2058c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2059c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_WIZNEXT: 2060c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 2061c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2062c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_WIZFINISH: 2063c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 2064c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2065c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou case PSN_RESET: 2066c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 2067c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2068c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou default: 2069c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou break; 2070c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2071c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2072c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 2073bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2074bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2075bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid RunWizard(HWND hwnd) 2076bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2077c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PROPSHEETPAGE psp = {0}; 2078c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HPROPSHEETPAGE ahpsp[4] = {0}; 2079c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PROPSHEETHEADER psh = {0}; 2080c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2081c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Display module information */ 2082c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.dwSize = sizeof(psp); 2083c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; 2084c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.hInstance = GetModuleHandle (NULL); 2085c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.lParam = 0; 2086c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.pfnDlgProc = IntroDlgProc; 2087c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.pszTemplate = MAKEINTRESOURCE(IDD_INTRO); 2088c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2089c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ahpsp[0] = CreatePropertySheetPage(&psp); 2090c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2091c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Select python version to use */ 2092c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; 2093c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.pszTemplate = MAKEINTRESOURCE(IDD_SELECTPYTHON); 2094c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.pfnDlgProc = SelectPythonDlgProc; 2095c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2096c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ahpsp[1] = CreatePropertySheetPage(&psp); 2097c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2098c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Install the files */ 2099c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; 2100c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLFILES); 2101c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.pfnDlgProc = InstallFilesDlgProc; 2102c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2103c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ahpsp[2] = CreatePropertySheetPage(&psp); 2104c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2105c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Show success or failure */ 2106c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; 2107c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHED); 2108c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psp.pfnDlgProc = FinishedDlgProc; 2109c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2110c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ahpsp[3] = CreatePropertySheetPage(&psp); 2111c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2112c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Create the property sheet */ 2113c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.dwSize = sizeof(psh); 2114c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.hInstance = GetModuleHandle(NULL); 2115c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.hwndParent = hwnd; 2116c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.phpage = ahpsp; 2117c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.dwFlags = PSH_WIZARD/*97*//*|PSH_WATERMARK|PSH_HEADER*/; 2118c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.pszbmWatermark = NULL; 2119c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.pszbmHeader = NULL; 2120c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.nStartPage = 0; 2121c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou psh.nPages = 4; 2122c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2123c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PropertySheet(&psh); 2124bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2125bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 21267c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// subtly different from HasLocalMachinePrivs(), in that after executing 21277c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// an 'elevated' process, we expect this to return TRUE - but there is no 21287c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// such implication for HasLocalMachinePrivs 21297c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark HammondBOOL MyIsUserAnAdmin() 21307c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond{ 2131c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou typedef BOOL (WINAPI *PFNIsUserAnAdmin)(); 2132c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou static PFNIsUserAnAdmin pfnIsUserAnAdmin = NULL; 2133c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HMODULE shell32; 2134c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // This function isn't guaranteed to be available (and it can't hurt 2135c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // to leave the library loaded) 2136c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (0 == (shell32=LoadLibrary("shell32.dll"))) 2137c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 2138c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (0 == (pfnIsUserAnAdmin=(PFNIsUserAnAdmin)GetProcAddress(shell32, "IsUserAnAdmin"))) 2139c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 2140c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return (*pfnIsUserAnAdmin)(); 21417c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond} 21427c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond 21437c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// Some magic for Vista's UAC. If there is a target_version, and 21447c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// if that target version is installed in the registry under 21457c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// HKLM, and we are not current administrator, then 21467c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// re-execute ourselves requesting elevation. 21477c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// Split into 2 functions - "should we elevate" and "spawn elevated" 21487c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond 21497c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// Returns TRUE if we should spawn an elevated child 21507c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark HammondBOOL NeedAutoUAC() 21517c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond{ 2152c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY hk; 2153c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char key_name[80]; 2154c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // no Python version info == we can't know yet. 2155c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (target_version[0] == '\0') 2156c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 2157c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // see how python is current installed 2158c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(key_name, 2159c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Software\\Python\\PythonCore\\%s\\InstallPath", 2160c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou target_version); 2161c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, 2162c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou key_name, 0, KEY_READ, &hk)) 2163c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 2164c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RegCloseKey(hk); 2165c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // Python is installed in HKLM - we must elevate. 2166c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 21677c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond} 21687c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond 21695bd88333ee233e2770942e9ffe26db0e83789048Mark Hammond// Returns TRUE if the platform supports UAC. 21705bd88333ee233e2770942e9ffe26db0e83789048Mark HammondBOOL PlatformSupportsUAC() 21715bd88333ee233e2770942e9ffe26db0e83789048Mark Hammond{ 2172c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // Note that win2k does seem to support ShellExecute with 'runas', 2173c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // but does *not* support IsUserAnAdmin - so we just pretend things 2174c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // only work on XP and later. 2175c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou BOOL bIsWindowsXPorLater; 2176c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou OSVERSIONINFO winverinfo; 2177c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou winverinfo.dwOSVersionInfoSize = sizeof(winverinfo); 2178c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!GetVersionEx(&winverinfo)) 2179c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; // something bad has gone wrong 2180c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou bIsWindowsXPorLater = 21815bd88333ee233e2770942e9ffe26db0e83789048Mark Hammond ( (winverinfo.dwMajorVersion > 5) || 21825bd88333ee233e2770942e9ffe26db0e83789048Mark Hammond ( (winverinfo.dwMajorVersion == 5) && (winverinfo.dwMinorVersion >= 1) )); 2183c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return bIsWindowsXPorLater; 21845bd88333ee233e2770942e9ffe26db0e83789048Mark Hammond} 21855bd88333ee233e2770942e9ffe26db0e83789048Mark Hammond 21867c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// Spawn ourself as an elevated application. On failure, a message is 21877c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// displayed to the user - but this app will always terminate, even 21887c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond// on error. 21897c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammondvoid SpawnUAC() 21907c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond{ 2191c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // interesting failure scenario that has been seen: initial executable 2192c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // runs from a network drive - but once elevated, that network share 2193c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // isn't seen, and ShellExecute fails with SE_ERR_ACCESSDENIED. 2194c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int ret = (int)ShellExecute(0, "runas", modulename, "", NULL, 2195c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SW_SHOWNORMAL); 2196c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ret <= 32) { 2197c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char msg[128]; 2198c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(msg, "Failed to start elevated process (ShellExecute returned %d)", ret); 2199c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(0, msg, "Setup", MB_OK | MB_ICONERROR); 2200c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 22017c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond} 22027c5c8e6823e476b46a30373e5a95e8b8e4c5fa09Mark Hammond 2203bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint DoInstall(void) 2204bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2205c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char ini_buffer[4096]; 2206c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2207c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Read installation information */ 2208c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPrivateProfileString("Setup", "title", "", ini_buffer, 2209c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sizeof(ini_buffer), ini_file); 2210c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou unescape(title, ini_buffer, sizeof(title)); 2211c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2212c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPrivateProfileString("Setup", "info", "", ini_buffer, 2213c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sizeof(ini_buffer), ini_file); 2214c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou unescape(info, ini_buffer, sizeof(info)); 2215c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2216c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPrivateProfileString("Setup", "build_info", "", build_info, 2217c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sizeof(build_info), ini_file); 2218c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2219c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou pyc_compile = GetPrivateProfileInt("Setup", "target_compile", 1, 2220c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ini_file); 2221c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou pyo_compile = GetPrivateProfileInt("Setup", "target_optimize", 1, 2222c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ini_file); 2223c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2224c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPrivateProfileString("Setup", "target_version", "", 2225c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou target_version, sizeof(target_version), 2226c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ini_file); 2227c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2228c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPrivateProfileString("metadata", "name", "", 2229c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou meta_name, sizeof(meta_name), 2230c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ini_file); 2231c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2232c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPrivateProfileString("Setup", "install_script", "", 2233c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou install_script, sizeof(install_script), 2234c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ini_file); 2235c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2236c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetPrivateProfileString("Setup", "user_access_control", "", 2237c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou user_access_control, sizeof(user_access_control), ini_file); 2238c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2239c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // See if we need to do the Vista UAC magic. 2240c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (strcmp(user_access_control, "force")==0) { 2241c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (PlatformSupportsUAC() && !MyIsUserAnAdmin()) { 2242c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SpawnUAC(); 2243c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 2244c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2245c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // already admin - keep going 2246c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else if (strcmp(user_access_control, "auto")==0) { 2247c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // Check if it looks like we need UAC control, based 2248c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // on how Python itself was installed. 2249c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (PlatformSupportsUAC() && !MyIsUserAnAdmin() && NeedAutoUAC()) { 2250c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SpawnUAC(); 2251c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 2252c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2253c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else { 2254c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // display a warning about unknown values - only the developer 2255c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // of the extension will see it (until they fix it!) 2256c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (user_access_control[0] && strcmp(user_access_control, "none") != 0) { 2257c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), "Bad user_access_control value", "oops", MB_OK); 2258c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // nothing to do. 2259c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2260c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2261c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2262c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hwndMain = CreateBackground(title); 2263c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2264c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RunWizard(hwndMain); 2265c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2266c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Clean up */ 2267c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou UnmapViewOfFile(arc_data); 2268c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ini_file) 2269c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DeleteFile(ini_file); 2270c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2271c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (hBitmap) 2272c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DeleteObject(hBitmap); 2273c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2274c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 2275bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2276bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2277bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/*********************** uninstall section ******************************/ 2278bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2279bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic int compare(const void *p1, const void *p2) 2280bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2281c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return strcmp(*(char **)p2, *(char **)p1); 2282bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2283bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2284bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 2285bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Commit suicide (remove the uninstaller itself). 2286bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 2287bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Create a batch file to first remove the uninstaller 2288bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * (will succeed after it has finished), then the batch file itself. 2289bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 2290bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * This technique has been demonstrated by Jeff Richter, 2291bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * MSJ 1/1996 2292bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 2293bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid remove_exe(void) 2294bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2295c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char exename[_MAX_PATH]; 2296c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char batname[_MAX_PATH]; 2297c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE *fp; 2298c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou STARTUPINFO si; 2299c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou PROCESS_INFORMATION pi; 2300c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2301c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetModuleFileName(NULL, exename, sizeof(exename)); 2302c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sprintf(batname, "%s.bat", exename); 2303c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fp = fopen(batname, "w"); 2304c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(fp, ":Repeat\n"); 2305c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(fp, "del \"%s\"\n", exename); 2306c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(fp, "if exist \"%s\" goto Repeat\n", exename); 2307c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(fp, "del \"%s\"\n", batname); 2308c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fclose(fp); 2309c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2310c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ZeroMemory(&si, sizeof(si)); 2311c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou si.cb = sizeof(si); 2312c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou si.dwFlags = STARTF_USESHOWWINDOW; 2313c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou si.wShowWindow = SW_HIDE; 2314c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (CreateProcess(NULL, 2315c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou batname, 2316c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 2317c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 2318c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FALSE, 2319c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CREATE_SUSPENDED | IDLE_PRIORITY_CLASS, 2320c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 2321c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "\\", 2322c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &si, 2323c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &pi)) { 2324c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetThreadPriority(pi.hThread, THREAD_PRIORITY_IDLE); 2325c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); 2326c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); 2327c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CloseHandle(pi.hProcess); 2328c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ResumeThread(pi.hThread); 2329c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou CloseHandle(pi.hThread); 2330c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2331bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2332bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2333bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid DeleteRegistryKey(char *string) 2334bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2335c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *keyname; 2336c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *subkeyname; 2337c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *delim; 2338c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY hKey; 2339c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou long result; 2340c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *line; 2341c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2342c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou line = strdup(string); /* so we can change it */ 2343c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2344c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou keyname = strchr(line, '['); 2345c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!keyname) 2346c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return; 2347c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++keyname; 2348c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2349c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou subkeyname = strchr(keyname, ']'); 2350c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!subkeyname) 2351c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return; 2352c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *subkeyname++='\0'; 2353c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou delim = strchr(subkeyname, '\n'); 2354c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (delim) 2355c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *delim = '\0'; 2356c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2357c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegOpenKeyEx(hkey_root, 2358c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou keyname, 2359c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 2360c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KEY_WRITE, 2361c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &hKey); 2362c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2363c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result != ERROR_SUCCESS) 2364c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), string, "Could not open key", MB_OK); 2365c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else { 2366c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegDeleteKey(hKey, subkeyname); 2367c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) 2368c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), string, "Could not delete key", MB_OK); 2369c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RegCloseKey(hKey); 2370c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2371c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou free(line); 2372bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2373bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2374bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid DeleteRegistryValue(char *string) 2375bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2376c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *keyname; 2377c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *valuename; 2378c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *value; 2379c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou HKEY hKey; 2380c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou long result; 2381c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *line; 2382bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2383c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou line = strdup(string); /* so we can change it */ 2384bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2385bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Format is 'Reg DB Value: [key]name=value' */ 2386c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou keyname = strchr(line, '['); 2387c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!keyname) 2388c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return; 2389c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++keyname; 2390c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou valuename = strchr(keyname, ']'); 2391c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!valuename) 2392c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return; 2393c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *valuename++ = '\0'; 2394c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou value = strchr(valuename, '='); 2395c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!value) 2396c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return; 2397c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2398c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *value++ = '\0'; 2399c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2400c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegOpenKeyEx(hkey_root, 2401c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou keyname, 2402c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 0, 2403c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou KEY_WRITE, 2404c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &hKey); 2405c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result != ERROR_SUCCESS) 2406c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), string, "Could not open key", MB_OK); 2407c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else { 2408c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou result = RegDeleteValue(hKey, valuename); 2409c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) 2410c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), string, "Could not delete value", MB_OK); 2411c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou RegCloseKey(hKey); 2412c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2413c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou free(line); 2414bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2415bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2416bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL MyDeleteFile(char *line) 2417bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2418c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *pathname = strchr(line, ':'); 2419c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!pathname) 2420c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 2421c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++pathname; 2422c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (isspace(*pathname)) 2423c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++pathname; 2424c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return DeleteFile(pathname); 2425bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2426bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2427bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL MyRemoveDirectory(char *line) 2428bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2429c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *pathname = strchr(line, ':'); 2430c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!pathname) 2431c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 2432c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++pathname; 2433c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (isspace(*pathname)) 2434c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++pathname; 2435c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return RemoveDirectory(pathname); 2436bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2437bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2438bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL Run_RemoveScript(char *line) 2439bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2440c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *dllname; 2441c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *scriptname; 2442c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou static char lastscript[MAX_PATH]; 2443bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2444bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Format is 'Run Scripts: [pythondll]scriptname' */ 2445bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* XXX Currently, pythondll carries no path!!! */ 2446c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou dllname = strchr(line, '['); 2447c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!dllname) 2448c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 2449c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++dllname; 2450c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou scriptname = strchr(dllname, ']'); 2451c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!scriptname) 2452c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return FALSE; 2453c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou *scriptname++ = '\0'; 2454c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* this function may be called more than one time with the same 2455c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou script, only run it one time */ 2456c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (strcmp(lastscript, scriptname)) { 2457c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *argv[3] = {NULL, "-remove", NULL}; 2458c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *buffer = NULL; 2459c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2460c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou argv[0] = scriptname; 2461c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2462c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (0 != run_installscript(scriptname, 2, argv, &buffer)) 2463c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fprintf(stderr, "*** Could not run installation script ***"); 2464c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2465c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (buffer && buffer[0]) 2466c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), buffer, "uninstall-script", MB_OK); 2467c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou free(buffer); 2468c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2469c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou strcpy(lastscript, scriptname); 2470c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2471c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return TRUE; 2472bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2473bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2474bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint DoUninstall(int argc, char **argv) 2475bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2476c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou FILE *logfile; 2477c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char buffer[4096]; 2478c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int nLines = 0; 2479c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int i; 2480c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *cp; 2481c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int nFiles = 0; 2482c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int nDirs = 0; 2483c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int nErrors = 0; 2484c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char **lines; 2485c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int lines_buffer_size = 10; 2486c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2487c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (argc != 3) { 2488c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(NULL, 2489c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Wrong number of args", 2490c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 2491c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_OK); 2492c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; /* Error */ 2493c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2494c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (strcmp(argv[1], "-u")) { 2495c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(NULL, 2496c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "2. arg is not -u", 2497c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 2498c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_OK); 2499c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; /* Error */ 2500c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2501c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2502c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou logfile = fopen(argv[2], "r"); 2503c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!logfile) { 2504c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(NULL, 2505c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "could not open logfile", 2506c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 2507c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_OK); 2508c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; /* Error */ 2509c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2510c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2511c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou lines = (char **)malloc(sizeof(char *) * lines_buffer_size); 2512c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!lines) 2513c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return SystemError(0, "Out of memory"); 2514c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2515c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Read the whole logfile, realloacting the buffer */ 2516c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (fgets(buffer, sizeof(buffer), logfile)) { 2517c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int len = strlen(buffer); 2518c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* remove trailing white space */ 2519c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou while (isspace(buffer[len-1])) 2520c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou len -= 1; 2521c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou buffer[len] = '\0'; 2522c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou lines[nLines++] = strdup(buffer); 2523c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (nLines >= lines_buffer_size) { 2524c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou lines_buffer_size += 10; 2525c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou lines = (char **)realloc(lines, 2526c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou sizeof(char *) * lines_buffer_size); 2527c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!lines) 2528c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return SystemError(0, "Out of memory"); 2529c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2530c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2531c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou fclose(logfile); 2532c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2533c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Sort all the lines, so that highest 3-digit codes are first */ 2534c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou qsort(&lines[0], nLines, sizeof(char *), 2535c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou compare); 2536c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2537c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (IDYES != MessageBox(NULL, 2538c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Are you sure you want to remove\n" 2539c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "this package from your computer?", 2540c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "Please confirm", 2541c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_YESNO | MB_ICONQUESTION)) 2542c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 2543c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2544c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hkey_root = HKEY_LOCAL_MACHINE; 2545c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou cp = ""; 2546c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou for (i = 0; i < nLines; ++i) { 2547c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Ignore duplicate lines */ 2548c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (strcmp(cp, lines[i])) { 2549c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int ign; 2550c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou cp = lines[i]; 2551c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Parse the lines */ 2552c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (2 == sscanf(cp, "%d Root Key: %s", &ign, &buffer)) { 2553c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (strcmp(buffer, "HKEY_CURRENT_USER")==0) 2554c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou hkey_root = HKEY_CURRENT_USER; 2555c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else { 2556c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou // HKLM - check they have permissions. 2557c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!HasLocalMachinePrivs()) { 2558c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(GetFocus(), 2559c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "You do not seem to have sufficient access rights\n" 2560c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "on this machine to uninstall this software", 2561c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou NULL, 2562c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_OK | MB_ICONSTOP); 2563c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; /* Error */ 2564c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2565c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2566c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else if (2 == sscanf(cp, "%d Made Dir: %s", &ign, &buffer)) { 2567c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (MyRemoveDirectory(cp)) 2568c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++nDirs; 2569c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else { 2570c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int code = GetLastError(); 2571c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (code != 2 && code != 3) { /* file or path not found */ 2572c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++nErrors; 2573c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2574c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2575c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else if (2 == sscanf(cp, "%d File Copy: %s", &ign, &buffer)) { 2576c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (MyDeleteFile(cp)) 2577c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++nFiles; 2578c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else { 2579c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int code = GetLastError(); 2580c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (code != 2 && code != 3) { /* file or path not found */ 2581c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++nErrors; 2582c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2583c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2584c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else if (2 == sscanf(cp, "%d File Overwrite: %s", &ign, &buffer)) { 2585c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (MyDeleteFile(cp)) 2586c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++nFiles; 2587c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else { 2588c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou int code = GetLastError(); 2589c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (code != 2 && code != 3) { /* file or path not found */ 2590c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++nErrors; 2591c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2592c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2593c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else if (2 == sscanf(cp, "%d Reg DB Key: %s", &ign, &buffer)) { 2594c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DeleteRegistryKey(cp); 2595c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else if (2 == sscanf(cp, "%d Reg DB Value: %s", &ign, &buffer)) { 2596c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou DeleteRegistryValue(cp); 2597c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else if (2 == sscanf(cp, "%d Run Script: %s", &ign, &buffer)) { 2598c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou Run_RemoveScript(cp); 2599c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2600c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2601c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2602c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2603c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (DeleteFile(argv[2])) { 2604c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++nFiles; 2605c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } else { 2606c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++nErrors; 2607c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SystemError(GetLastError(), argv[2]); 2608c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2609c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (nErrors) 2610c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(buffer, 2611c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "%d files and %d directories removed\n" 2612c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou "%d files or directories could not be removed", 2613c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou nFiles, nDirs, nErrors); 2614c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else 2615c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou wsprintf(buffer, "%d files and %d directories removed", 2616c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou nFiles, nDirs); 2617c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MessageBox(NULL, buffer, "Uninstall Finished!", 2618c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou MB_OK | MB_ICONINFORMATION); 2619c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou remove_exe(); 2620c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 0; 2621bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2622bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2623bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, 2624c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou LPSTR lpszCmdLine, INT nCmdShow) 2625bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2626c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou extern int __argc; 2627c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou extern char **__argv; 2628c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou char *basename; 2629c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2630c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou GetModuleFileName(NULL, modulename, sizeof(modulename)); 2631c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2632c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Map the executable file to memory */ 2633c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou arc_data = MapExistingFile(modulename, &arc_size); 2634c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!arc_data) { 2635c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SystemError(GetLastError(), "Could not open archive"); 2636c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; 2637c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2638c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2639c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* OK. So this program can act as installer (self-extracting 2640c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * zip-file, or as uninstaller when started with '-u logfile' 2641c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * command line flags. 2642c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * 2643c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * The installer is usually started without command line flags, 2644c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * and the uninstaller is usually started with the '-u logfile' 2645c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * flag. What to do if some innocent user double-clicks the 2646c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * exe-file? 2647c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou * The following implements a defensive strategy... 2648c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou */ 2649c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2650c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Try to extract the configuration data into a temporary file */ 2651c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (ExtractInstallData(arc_data, arc_size, &exe_size, 2652c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou &ini_file, &pre_install_script)) 2653c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return DoInstall(); 2654c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2655c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (!ini_file && __argc > 1) { 2656c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return DoUninstall(__argc, __argv); 2657c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou } 2658c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2659c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2660c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou basename = strrchr(modulename, '\\'); 2661c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (basename) 2662c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou ++basename; 2663c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou 2664c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou /* Last guess about the purpose of this program */ 2665c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou if (basename && (0 == strncmp(basename, "Remove", 6))) 2666c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SystemError(0, "This program is normally started by windows"); 2667c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou else 2668c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou SystemError(0, "Setup program invalid or damaged"); 2669c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou return 1; 2670bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2671