1bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 265e4cb10d9d9964f30bc72561bf0e86833328a3bSteve Dower IMPORTANT NOTE: IF THIS FILE IS CHANGED, PCBUILD\BDIST_WININST.VCXPROJ MUST 365e4cb10d9d9964f30bc72561bf0e86833328a3bSteve Dower BE REBUILT AS WELL. 4d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller 565e4cb10d9d9964f30bc72561bf0e86833328a3bSteve Dower IF CHANGES TO THIS FILE ARE CHECKED IN, THE RECOMPILED BINARIES MUST BE 665e4cb10d9d9964f30bc72561bf0e86833328a3bSteve Dower CHECKED IN AS WELL! 7d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller*/ 8d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller 9d1d92ea59a48f333efbdbc05feabc4d5d5445fb8Thomas Heller/* 10bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Written by Thomas Heller, May 2000 11bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 12bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * $Id$ 13bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 14bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 15bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 16bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Windows Installer program for distutils. 17bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 18bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * (a kind of self-extracting zip-file) 19bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 20bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * At runtime, the exefile has appended: 21bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - compressed setup-data in ini-format, containing the following sections: 227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * [metadata] 237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * author=Greg Ward 247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * author_email=gward@python.net 257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * description=Python Distribution Utilities 267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * licence=Python 277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * name=Distutils 287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * url=http://www.python.org/sigs/distutils-sig/ 297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * version=0.9pre 30bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * [Setup] 327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * info= text to be displayed in the edit-box 337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * title= to be displayed by this program 347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * target_version = if present, python version required 357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * pyc_compile = if 0, do not compile py to pyc 367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * pyo_compile = if 0, do not compile py to pyo 37bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 38bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - a struct meta_data_hdr, describing the above 39bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - a zip-file, containing the modules to be installed. 40bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * for the format see http://www.pkware.com/appnote.html 41bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 42bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * What does this program do? 43bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - the setup-data is uncompressed and written to a temporary file. 44bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - setup-data is queried with GetPrivateProfile... calls 45bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - [metadata] - info is displayed in the dialog box 46bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - The registry is searched for installations of python 47bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - The user can select the python version to use. 48bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - The python-installation directory (sys.prefix) is displayed 49bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - When the start-button is pressed, files from the zip-archive 50bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * are extracted to the file system. All .py filenames are stored 51bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * in a list. 52bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 53bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 54bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Includes now an uninstaller. 55bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 56bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 57bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 58bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * To Do: 59bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 60bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * display some explanation when no python version is found 61bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * instead showing the user an empty listbox to select something from. 62bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 63bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Finish the code so that we can use other python installations 6442da663e6fe7ecbb89b17d596c76812a91bb99a4Ezio Melotti * additionally to those found in the registry, 65bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * and then #define USE_OTHER_PYTHON_VERSIONS 66bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 67bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - install a help-button, which will display something meaningful 68bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * to the poor user. 69bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * text to the user 70bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - should there be a possibility to display a README file 71bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * before starting the installation (if one is present in the archive) 72bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - more comments about what the code does(?) 73bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 74bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * - evolve this into a full blown installer (???) 75bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 76bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 77bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <windows.h> 78bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <commctrl.h> 79bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <imagehlp.h> 80bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <objbase.h> 81bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <shlobj.h> 82bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <objidl.h> 83bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include "resource.h" 84bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 85bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <stdio.h> 86bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <stdlib.h> 87bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <stdarg.h> 88bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <string.h> 89bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <time.h> 909f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <sys/types.h> 919f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <sys/stat.h> 929f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <malloc.h> 939f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <io.h> 949f2e3be4e86f95b33e9e307ecf115e72ae73b5e1Thomas Heller#include <fcntl.h> 95bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 96bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include "archive.h" 97bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 98bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Only for debugging! 99bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller static int dprintf(char *fmt, ...) 100bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller { 101bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller char Buffer[4096]; 102bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller va_list marker; 103bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller int result; 104bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 105bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller va_start(marker, fmt); 106bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller result = wvsprintf(Buffer, fmt, marker); 107bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller OutputDebugString(Buffer); 108bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller return result; 109bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller } 110bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller*/ 111bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 112bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Bah: global variables */ 113bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerFILE *logfile; 114bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 115bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar modulename[MAX_PATH]; 116891f2631f576dfc515627074cccb07e0ffdff156Mark Hammondwchar_t wmodulename[MAX_PATH]; 117bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 118bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerHWND hwndMain; 119bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerHWND hDialog; 120bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrouchar *ini_file; /* Full pathname of ini-file */ 122bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* From ini-file */ 1237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrouchar info[4096]; /* [Setup] info= */ 1247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrouchar title[80]; /* [Setup] title=, contains package name 1257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou including version: "Distutils-1.0.1" */ 1267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrouchar target_version[10]; /* [Setup] target_version=, required python 1277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou version or empty string */ 1287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrouchar build_info[80]; /* [Setup] build_info=, distutils version 1297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou and build date */ 1307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 1317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrouchar meta_name[80]; /* package name without version like 1327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 'Distutils' */ 133bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar install_script[MAX_PATH]; 134a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerchar *pre_install_script; /* run before we install a single file */ 135bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 13681ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimeschar user_access_control[10]; // one of 'auto', 'force', otherwise none. 137bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrouint py_major, py_minor; /* Python version selected for installation */ 139bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrouchar *arc_data; /* memory mapped archive */ 1417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine PitrouDWORD arc_size; /* number of bytes in archive */ 1427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine 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 15013925008dc11f2a235627dc8c0440c0ce99171d9Ezio MelottiBOOL success; /* Installation successful? */ 151a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerchar *failure_reason = NULL; 152bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 153bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerHANDLE hBitmap; 154bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar *bitmap_bytes; 155bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 156332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dowerstatic const char *REGISTRY_SUFFIX_6432 = 1574347881414c2923fe3d7f14b66671e57578ad103Steve Dower#ifdef _WIN64 158332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower ""; 159332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower#else 160332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower "-32"; 161332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower#endif 162332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower 163bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 164bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define WM_NUMFILES WM_USER+1 165bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* wParam: 0, lParam: total number of files */ 166bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define WM_NEXTFILE WM_USER+2 167bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* wParam: number of this file */ 168bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* lParam: points to pathname */ 169bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 170bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL notify(int code, char *fmt, ...); 171bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 172bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Note: If scheme.prefix is nonempty, it must end with a '\'! */ 173bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Note: purelib must be the FIRST entry! */ 174bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerSCHEME old_scheme[] = { 1757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "PURELIB", "" }, 1767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "PLATLIB", "" }, 1777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */ 1787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "SCRIPTS", "Scripts\\" }, 1797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "DATA", "" }, 1807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { NULL, NULL }, 181bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 182bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 183bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerSCHEME new_scheme[] = { 1847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "PURELIB", "Lib\\site-packages\\" }, 1857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "PLATLIB", "Lib\\site-packages\\" }, 1867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */ 1877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "SCRIPTS", "Scripts\\" }, 1887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { "DATA", "" }, 1897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { NULL, NULL }, 190bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 191bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 192bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void unescape(char *dst, char *src, unsigned size) 193bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 1947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *eon; 1957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char ch; 1967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 1977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (src && *src && (size > 2)) { 1987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (*src == '\\') { 1997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (*++src) { 2007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case 'n': 2017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++src; 2027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *dst++ = '\r'; 2037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *dst++ = '\n'; 2047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou size -= 2; 2057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 2067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case 'r': 2077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++src; 2087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *dst++ = '\r'; 2097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou --size; 2107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 2117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case '0': case '1': case '2': case '3': 2127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ch = (char)strtol(src, &eon, 8); 2137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ch == '\n') { 2147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *dst++ = '\r'; 2157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou --size; 2167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 2177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *dst++ = ch; 2187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou --size; 2197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou src = eon; 2207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 2217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else { 2227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *dst++ = *src++; 2237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou --size; 2247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 2257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 2267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *dst = '\0'; 227bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 228bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 229bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic struct tagFile { 2307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *path; 2317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct tagFile *next; 232bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} *file_list = NULL; 233bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 234a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic void set_failure_reason(char *reason) 235a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 236a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller if (failure_reason) 2377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(failure_reason); 238a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller failure_reason = strdup(reason); 239a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller success = FALSE; 240a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 241a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic char *get_failure_reason() 242a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 243a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller if (!failure_reason) 2447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return "Installation failed."; 245a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller return failure_reason; 246a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 247a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 248bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void add_to_filelist(char *path) 249bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct tagFile *p; 2517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou p = (struct tagFile *)malloc(sizeof(struct tagFile)); 2527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou p->path = strdup(path); 2537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou p->next = file_list; 2547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou file_list = p; 255bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 256bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 257bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic int do_compile_files(int (__cdecl * PyRun_SimpleString)(char *), 2587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int optimize) 259bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 2607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct tagFile *p; 2617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int total, n; 2627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char Buffer[MAX_PATH + 64]; 2637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int errors = 0; 2647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 2657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou total = 0; 2667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou p = file_list; 2677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (p) { 2687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++total; 2697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou p = p->next; 2707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 2717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETRANGE, 0, 2727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MAKELPARAM(0, total)); 2737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, 0, 0); 2747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 2757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou n = 0; 2767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou p = file_list; 2777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (p) { 2787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++n; 2797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(Buffer, 2807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "import py_compile; py_compile.compile (r'%s')", 2817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou p->path); 2827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (PyRun_SimpleString(Buffer)) { 2837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++errors; 2847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 2857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* We send the notification even if the files could not 2867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * be created so that the uninstaller will remove them 2877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * in case they are created later. 2887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou */ 2897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(Buffer, "%s%c", p->path, optimize ? 'o' : 'c'); 2907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou notify(FILE_CREATED, Buffer); 2917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 2927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, n, 0); 2937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hDialog, IDC_INFO, p->path); 2947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou p = p->next; 2957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 2967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return errors; 297bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 298bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 299bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define DECLPROC(dll, result, name, args)\ 300bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller typedef result (*__PROC__##name) args;\ 301bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller result (*name)args = (__PROC__##name)GetProcAddress(dll, #name) 302bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 303bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 304bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define DECLVAR(dll, type, name)\ 305bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller type *name = (type*)GetProcAddress(dll, #name) 306bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 307bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellertypedef void PyObject; 308bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 309891f2631f576dfc515627074cccb07e0ffdff156Mark Hammond// Convert a "char *" string to "whcar_t *", or NULL on error. 310891f2631f576dfc515627074cccb07e0ffdff156Mark Hammond// Result string must be free'd 311891f2631f576dfc515627074cccb07e0ffdff156Mark Hammondwchar_t *widen_string(char *src) 312891f2631f576dfc515627074cccb07e0ffdff156Mark Hammond{ 3137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wchar_t *result; 3147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD dest_cch; 3157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int src_len = strlen(src) + 1; // include NULL term in all ops 3167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* use MultiByteToWideChar() to see how much we need. */ 3177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* NOTE: this will include the null-term in the length */ 3187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou dest_cch = MultiByteToWideChar(CP_ACP, 0, src, src_len, NULL, 0); 3197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // alloc the buffer 3207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = (wchar_t *)malloc(dest_cch * sizeof(wchar_t)); 3217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result==NULL) 3227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 3237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* do the conversion */ 3247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (0==MultiByteToWideChar(CP_ACP, 0, src, src_len, result, dest_cch)) { 3257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(result); 3267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 3277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 3287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return result; 329891f2631f576dfc515627074cccb07e0ffdff156Mark Hammond} 330bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 331bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 332bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Returns number of files which failed to compile, 333bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * -1 if python could not be loaded at all 334bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 335bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic int compile_filelist(HINSTANCE hPython, BOOL optimize_flag) 336bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 3377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, void, Py_Initialize, (void)); 3387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, void, Py_SetProgramName, (wchar_t *)); 3397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, void, Py_Finalize, (void)); 3407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, int, PyRun_SimpleString, (char *)); 3417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, PySys_GetObject, (char *)); 3427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLVAR(hPython, int, Py_OptimizeFlag); 343bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 3447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int errors = 0; 3457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct tagFile *p = file_list; 346bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 3477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!p) 3487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 349bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 3507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!Py_Initialize || !Py_SetProgramName || !Py_Finalize) 3517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return -1; 352bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 3537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!PyRun_SimpleString || !PySys_GetObject || !Py_OptimizeFlag) 3547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return -1; 355bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 3567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *Py_OptimizeFlag = optimize_flag ? 1 : 0; 3577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_SetProgramName(wmodulename); 3587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_Initialize(); 359bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 3607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou errors += do_compile_files(PyRun_SimpleString, optimize_flag); 3617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_Finalize(); 362bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 3637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return errors; 364bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 365bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 366bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellertypedef PyObject *(*PyCFunction)(PyObject *, PyObject *); 367bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 368bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstruct PyMethodDef { 3697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *ml_name; 3707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PyCFunction ml_meth; 3717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int ml_flags; 3727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *ml_doc; 373bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 374bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellertypedef struct PyMethodDef PyMethodDef; 375bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 37681ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// XXX - all of these are potentially fragile! We load and unload 3777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou// the Python DLL multiple times - so storing functions pointers 37881ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// is dangerous (although things *look* OK at present) 37981ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// Better might be to roll prepare_script_environment() into 38081ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// LoadPythonDll(), and create a new UnloadPythonDLL() which also 38181ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// clears the global pointers. 382bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid *(*g_Py_BuildValue)(char *, ...); 383bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint (*g_PyArg_ParseTuple)(PyObject *, char *, ...); 38481ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian HeimesPyObject * (*g_PyLong_FromVoidPtr)(void *); 385bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 386bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerPyObject *g_PyExc_ValueError; 387bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerPyObject *g_PyExc_OSError; 388bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 389bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerPyObject *(*g_PyErr_Format)(PyObject *, char *, ...); 390bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 391bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define DEF_CSIDL(name) { name, #name } 392bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 393bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstruct { 3947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int nFolder; 3957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *name; 396bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} csidl_names[] = { 3977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Startup menu for all users. 3987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NT only */ 3997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_COMMON_STARTMENU), 4007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Startup menu. */ 4017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_STARTMENU), 402bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 403bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* DEF_CSIDL(CSIDL_COMMON_APPDATA), */ 404bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* DEF_CSIDL(CSIDL_LOCAL_APPDATA), */ 4057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Repository for application-specific data. 4067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Needs Internet Explorer 4.0 */ 4077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_APPDATA), 4087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 4097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* The desktop for all users. 4107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NT only */ 4117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_COMMON_DESKTOPDIRECTORY), 4127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* The desktop. */ 4137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_DESKTOPDIRECTORY), 4147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 4157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Startup folder for all users. 4167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NT only */ 4177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_COMMON_STARTUP), 4187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Startup folder. */ 4197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_STARTUP), 4207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 4217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Programs item in the start menu for all users. 4227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NT only */ 4237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_COMMON_PROGRAMS), 4247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Program item in the user's start menu. */ 4257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_PROGRAMS), 426bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 427bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* DEF_CSIDL(CSIDL_PROGRAM_FILES_COMMON), */ 428bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* DEF_CSIDL(CSIDL_PROGRAM_FILES), */ 429bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 4307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Virtual folder containing fonts. */ 4317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DEF_CSIDL(CSIDL_FONTS), 432bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 433bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 434bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define DIM(a) (sizeof(a) / sizeof((a)[0])) 435bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 436bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic PyObject *FileCreated(PyObject *self, PyObject *args) 437bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 4387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *path; 4397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!g_PyArg_ParseTuple(args, "s", &path)) 4407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 4417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou notify(FILE_CREATED, path); 4427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return g_Py_BuildValue(""); 443bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 444bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 445bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic PyObject *DirectoryCreated(PyObject *self, PyObject *args) 446bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 4477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *path; 4487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!g_PyArg_ParseTuple(args, "s", &path)) 4497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 4507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou notify(DIR_CREATED, path); 4517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return g_Py_BuildValue(""); 452bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 453bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 454bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic PyObject *GetSpecialFolderPath(PyObject *self, PyObject *args) 455bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 4567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *name; 4577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char lpszPath[MAX_PATH]; 4587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int i; 4597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou static HRESULT (WINAPI *My_SHGetSpecialFolderPath)(HWND hwnd, 4607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LPTSTR lpszPath, 4617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int nFolder, 4627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou BOOL fCreate); 4637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 4647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!My_SHGetSpecialFolderPath) { 4657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HINSTANCE hLib = LoadLibrary("shell32.dll"); 4667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!hLib) { 4677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 4687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "function not available"); 4697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 4707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 4717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou My_SHGetSpecialFolderPath = (BOOL (WINAPI *)(HWND, LPTSTR, 4727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int, BOOL)) 4737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetProcAddress(hLib, 4747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "SHGetSpecialFolderPathA"); 4757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 4767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 4777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!g_PyArg_ParseTuple(args, "s", &name)) 4787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 4797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 4807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!My_SHGetSpecialFolderPath) { 4817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, "function not available"); 4827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 4837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 4847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 4857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou for (i = 0; i < DIM(csidl_names); ++i) { 4867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (0 == strcmpi(csidl_names[i].name, name)) { 4877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int nFolder; 4887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou nFolder = csidl_names[i].nFolder; 4897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (My_SHGetSpecialFolderPath(NULL, lpszPath, 4907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou nFolder, 0)) 4917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return g_Py_BuildValue("s", lpszPath); 4927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else { 4937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 4947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "no such folder (%s)", name); 4957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 4967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 4977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 4987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 4997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou }; 5007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_ValueError, "unknown CSIDL (%s)", name); 5017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 502bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 503bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 504bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic PyObject *CreateShortcut(PyObject *self, PyObject *args) 505bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 5067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *path; /* path and filename */ 5077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *description; 5087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *filename; 5097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *arguments = NULL; 5117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *iconpath = NULL; 5127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int iconindex = 0; 5137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *workdir = NULL; 5147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou WCHAR wszFilename[MAX_PATH]; 5167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou IShellLink *ps1 = NULL; 5187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou IPersistFile *pPf = NULL; 5197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HRESULT hr; 5217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = CoInitialize(NULL); 5237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 5247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 5257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "CoInitialize failed, error 0x%x", hr); 5267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 5277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!g_PyArg_ParseTuple(args, "sss|sssi", 5307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &path, &description, &filename, 5317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &arguments, &workdir, &iconpath, &iconindex)) 5327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 5337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = CoCreateInstance(&CLSID_ShellLink, 5357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 5367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CLSCTX_INPROC_SERVER, 5377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &IID_IShellLink, 5387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &ps1); 5397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 5407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 5417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "CoCreateInstance failed, error 0x%x", hr); 5427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 5437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = ps1->lpVtbl->QueryInterface(ps1, &IID_IPersistFile, 5467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (void **)&pPf); 5477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 5487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 5497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "QueryInterface(IPersistFile) error 0x%x", hr); 5507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 5517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = ps1->lpVtbl->SetPath(ps1, path); 5557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 5567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 5577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "SetPath() failed, error 0x%x", hr); 5587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 5597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = ps1->lpVtbl->SetDescription(ps1, description); 5627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 5637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 5647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "SetDescription() failed, error 0x%x", hr); 5657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 5667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (arguments) { 5697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = ps1->lpVtbl->SetArguments(ps1, arguments); 5707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 5717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 5727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "SetArguments() error 0x%x", hr); 5737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 5747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (iconpath) { 5787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = ps1->lpVtbl->SetIconLocation(ps1, iconpath, iconindex); 5797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 5807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 5817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "SetIconLocation() error 0x%x", hr); 5827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 5837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (workdir) { 5877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = ps1->lpVtbl->SetWorkingDirectory(ps1, workdir); 5887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 5897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 5907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "SetWorkingDirectory() error 0x%x", hr); 5917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 5927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 5947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MultiByteToWideChar(CP_ACP, 0, 5967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou filename, -1, 5977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wszFilename, MAX_PATH); 5987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 5997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hr = pPf->lpVtbl->Save(pPf, wszFilename, TRUE); 6007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (FAILED(hr)) { 6017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format(g_PyExc_OSError, 6027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Failed to create shortcut '%s' - error 0x%x", filename, hr); 6037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto error; 6047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 6057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 6067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou pPf->lpVtbl->Release(pPf); 6077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ps1->lpVtbl->Release(ps1); 6087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CoUninitialize(); 6097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return g_Py_BuildValue(""); 6107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 611bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller error: 6127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (pPf) 6137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou pPf->lpVtbl->Release(pPf); 614bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 6157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ps1) 6167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ps1->lpVtbl->Release(ps1); 617bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 6187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CoUninitialize(); 619bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 6207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 621bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 622bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 623a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic PyObject *PyMessageBox(PyObject *self, PyObject *args) 624a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 6257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int rc; 6267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *text, *caption; 6277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int flags; 6287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!g_PyArg_ParseTuple(args, "ssi", &text, &caption, &flags)) 6297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 6307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou rc = MessageBox(GetFocus(), text, caption, flags); 6317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return g_Py_BuildValue("i", rc); 632a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 633a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 634f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammondstatic PyObject *GetRootHKey(PyObject *self) 635f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond{ 6367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return g_PyLong_FromVoidPtr(hkey_root); 637f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond} 638f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond 639bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#define METH_VARARGS 0x0001 640f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond#define METH_NOARGS 0x0004 641f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammondtypedef PyObject *(*PyCFunction)(PyObject *, PyObject *); 642bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 643bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerPyMethodDef meth[] = { 6447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou {"create_shortcut", CreateShortcut, METH_VARARGS, NULL}, 6457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou {"get_special_folder_path", GetSpecialFolderPath, METH_VARARGS, NULL}, 6467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou {"get_root_hkey", (PyCFunction)GetRootHKey, METH_NOARGS, NULL}, 6477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou {"file_created", FileCreated, METH_VARARGS, NULL}, 6487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou {"directory_created", DirectoryCreated, METH_VARARGS, NULL}, 6497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou {"message_box", PyMessageBox, METH_VARARGS, NULL}, 650bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller}; 651bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 65248340390ac23a66cc2251a12d8690207726b85beThomas Hellerstatic HINSTANCE LoadPythonDll(char *fname) 65348340390ac23a66cc2251a12d8690207726b85beThomas Heller{ 6547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char fullpath[_MAX_PATH]; 6557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LONG size = sizeof(fullpath); 6567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char subkey_name[80]; 6577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char buffer[260 + 12]; 6587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HINSTANCE h; 6597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 6607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* make sure PYTHONHOME is set, to that sys.path is initialized correctly */ 6617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(buffer, "PYTHONHOME=%s", python_dir); 6627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou _putenv(buffer); 6637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou h = LoadLibrary(fname); 6647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (h) 6657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return h; 6667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(subkey_name, 667332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower "SOFTWARE\\Python\\PythonCore\\%d.%d%s\\InstallPath", 668332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower py_major, py_minor, REGISTRY_SUFFIX_6432); 6697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ERROR_SUCCESS != RegQueryValue(HKEY_CURRENT_USER, subkey_name, 6707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fullpath, &size) && 6717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ERROR_SUCCESS != RegQueryValue(HKEY_LOCAL_MACHINE, subkey_name, 6727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fullpath, &size)) 6737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 6747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcat(fullpath, "\\"); 6757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcat(fullpath, fname); 676332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower // We use LOAD_WITH_ALTERED_SEARCH_PATH to ensure any dependent DLLs 677332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower // next to the Python DLL (eg, the CRT DLL) are also loaded. 678332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower return LoadLibraryEx(fullpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); 67948340390ac23a66cc2251a12d8690207726b85beThomas Heller} 68048340390ac23a66cc2251a12d8690207726b85beThomas Heller 681a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic int prepare_script_environment(HINSTANCE hPython) 682a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 6837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PyObject *mod; 6847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, PyImport_ImportModule, (char *)); 6857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, int, PyObject_SetAttrString, (PyObject *, char *, PyObject *)); 6867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, PyObject_GetAttrString, (PyObject *, char *)); 6877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, PyCFunction_New, (PyMethodDef *, PyObject *)); 6887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...)); 6897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...)); 6907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *)); 6917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, PyLong_FromVoidPtr, (void *)); 6927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!PyImport_ImportModule || !PyObject_GetAttrString || 6937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou !PyObject_SetAttrString || !PyCFunction_New) 6947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; 6957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format) 6967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; 6977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 6987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou mod = PyImport_ImportModule("builtins"); 6997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (mod) { 7007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int i; 7017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyExc_ValueError = PyObject_GetAttrString(mod, "ValueError"); 7027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyExc_OSError = PyObject_GetAttrString(mod, "OSError"); 7037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou for (i = 0; i < DIM(meth); ++i) { 7047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PyObject_SetAttrString(mod, meth[i].ml_name, 7057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PyCFunction_New(&meth[i], NULL)); 7067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 7077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 7087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_Py_BuildValue = Py_BuildValue; 7097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyArg_ParseTuple = PyArg_ParseTuple; 7107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyErr_Format = PyErr_Format; 7117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou g_PyLong_FromVoidPtr = PyLong_FromVoidPtr; 7127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 714a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 715a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 716bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 717bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * This function returns one of the following error codes: 718bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 1 if the Python-dll does not export the functions we need 719bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 2 if no install-script is specified in pathname 720bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 3 if the install-script file could not be opened 721b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter * the return value of PyRun_SimpleString() or Py_FinalizeEx() otherwise, 722bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * which is 0 if everything is ok, -1 if an exception had occurred 723bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * in the install-script. 724bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 725bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 726bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic int 7276d0e9757d1f00402c736bc289bd5f4fd7e626afaMark Hammonddo_run_installscript(HINSTANCE hPython, char *pathname, int argc, char **argv) 728bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 7297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int fh, result, i; 7307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou static wchar_t *wargv[256]; 7317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, void, Py_Initialize, (void)); 7327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, int, PySys_SetArgv, (int, wchar_t **)); 7337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, int, PyRun_SimpleString, (char *)); 734b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter DECLPROC(hPython, int, Py_FinalizeEx, (void)); 7357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...)); 7367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, PyCFunction_New, 7377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (PyMethodDef *, PyObject *)); 7387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...)); 7397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *)); 7407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!Py_Initialize || !PySys_SetArgv 742b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter || !PyRun_SimpleString || !Py_FinalizeEx) 7437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; 7447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format) 7467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; 7477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!PyCFunction_New || !PyArg_ParseTuple || !PyErr_Format) 7497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; 7507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (pathname == NULL || pathname[0] == '\0') 7527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 2; 7537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 754daf455554bc21b6b5df0a016ab5fa639d36cc595Victor Stinner fh = open(pathname, _O_RDONLY | O_NOINHERIT); 7557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (-1 == fh) { 7567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(stderr, "Could not open postinstall-script %s\n", 7577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou pathname); 7587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 3; 7597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 7607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hDialog, IDC_INFO, "Running Script..."); 7627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_Initialize(); 7647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou prepare_script_environment(hPython); 7667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // widen the argv array for py3k. 7677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou memset(wargv, 0, sizeof(wargv)); 7687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou for (i=0;i<argc;i++) 7697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wargv[i] = argv[i] ? widen_string(argv[i]) : NULL; 7707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PySys_SetArgv(argc, wargv); 7717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // free the strings we just widened. 7727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou for (i=0;i<argc;i++) 7737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (wargv[i]) 7747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(wargv[i]); 7757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = 3; 7777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { 7787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct _stat statbuf; 7797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if(0 == _fstat(fh, &statbuf)) { 7807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *script = alloca(statbuf.st_size + 5); 7817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int n = read(fh, script, statbuf.st_size); 7827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (n > 0) { 7837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou script[n] = '\n'; 7847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou script[n+1] = 0; 7857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = PyRun_SimpleString(script); 7867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 7877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 7887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 789b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter if (Py_FinalizeEx() < 0) { 790b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter result = -1; 791b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter } 7927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 7937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou close(fh); 7947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return result; 7956d0e9757d1f00402c736bc289bd5f4fd7e626afaMark Hammond} 796bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 7976d0e9757d1f00402c736bc289bd5f4fd7e626afaMark Hammondstatic int 7986d0e9757d1f00402c736bc289bd5f4fd7e626afaMark Hammondrun_installscript(char *pathname, int argc, char **argv, char **pOutput) 7996d0e9757d1f00402c736bc289bd5f4fd7e626afaMark Hammond{ 8007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HINSTANCE hPython; 8017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int result = 1; 8027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int out_buf_size; 8037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HANDLE redirected, old_stderr, old_stdout; 8047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *tempname; 8057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 8067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *pOutput = NULL; 8077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 8087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou tempname = tempnam(NULL, NULL); 8097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // We use a static CRT while the Python version we load uses 81013925008dc11f2a235627dc8c0440c0ce99171d9Ezio Melotti // the CRT from one of various possible DLLs. As a result we 8117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // need to redirect the standard handles using the API rather 8127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // than the CRT. 8137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou redirected = CreateFile( 8147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou tempname, 8157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GENERIC_WRITE | GENERIC_READ, 8167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE_SHARE_READ, 8177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 8187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CREATE_ALWAYS, 8197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 8207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL); 8217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou old_stdout = GetStdHandle(STD_OUTPUT_HANDLE); 8227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou old_stderr = GetStdHandle(STD_ERROR_HANDLE); 8237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetStdHandle(STD_OUTPUT_HANDLE, redirected); 8247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetStdHandle(STD_ERROR_HANDLE, redirected); 8257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 8267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hPython = LoadPythonDll(pythondll); 8277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hPython) { 8287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = do_run_installscript(hPython, pathname, argc, argv); 8297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FreeLibrary(hPython); 8307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else { 8317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(stderr, "*** Could not load Python ***"); 8327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 8337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetStdHandle(STD_OUTPUT_HANDLE, old_stdout); 8347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetStdHandle(STD_ERROR_HANDLE, old_stderr); 8357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou out_buf_size = min(GetFileSize(redirected, NULL), 4096); 8367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *pOutput = malloc(out_buf_size+1); 8377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (*pOutput) { 8387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD nread = 0; 8397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetFilePointer(redirected, 0, 0, FILE_BEGIN); 8407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ReadFile(redirected, *pOutput, out_buf_size, &nread, NULL); 8417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (*pOutput)[nread] = '\0'; 8427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 8437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CloseHandle(redirected); 8447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DeleteFile(tempname); 8457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return result; 846bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 847bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 848a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic int do_run_simple_script(HINSTANCE hPython, char *script) 849a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 8507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int rc; 8517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, void, Py_Initialize, (void)); 8527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, void, Py_SetProgramName, (wchar_t *)); 853b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter DECLPROC(hPython, int, Py_FinalizeEx, (void)); 8547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, int, PyRun_SimpleString, (char *)); 8557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DECLPROC(hPython, void, PyErr_Print, (void)); 8567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 857b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter if (!Py_Initialize || !Py_SetProgramName || !Py_FinalizeEx || 8587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou !PyRun_SimpleString || !PyErr_Print) 8597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return -1; 8607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 8617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_SetProgramName(wmodulename); 8627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_Initialize(); 8637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou prepare_script_environment(hPython); 8647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou rc = PyRun_SimpleString(script); 8657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (rc) 8667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PyErr_Print(); 867b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter if (Py_FinalizeEx() < 0) { 868b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter rc = -1; 869b4ce1fc31be5614d527d77c55018281ebbcd70abMartin Panter } 8707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return rc; 871a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 872a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 873a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic int run_simple_script(char *script) 874a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller{ 8757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int rc; 8767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HINSTANCE hPython; 8777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *tempname = tempnam(NULL, NULL); 8787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // Redirect output using win32 API - see comments above... 8797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HANDLE redirected = CreateFile( 8807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou tempname, 8817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GENERIC_WRITE | GENERIC_READ, 8827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE_SHARE_READ, 8837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 8847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CREATE_ALWAYS, 8857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 8867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL); 8877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HANDLE old_stdout = GetStdHandle(STD_OUTPUT_HANDLE); 8887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HANDLE old_stderr = GetStdHandle(STD_ERROR_HANDLE); 8897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetStdHandle(STD_OUTPUT_HANDLE, redirected); 8907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetStdHandle(STD_ERROR_HANDLE, redirected); 8917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 8927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hPython = LoadPythonDll(pythondll); 8937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!hPython) { 8947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char reason[128]; 8957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(reason, "Can't load Python for pre-install script (%d)", GetLastError()); 8967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou set_failure_reason(reason); 8977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return -1; 8987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 8997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou rc = do_run_simple_script(hPython, script); 9007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FreeLibrary(hPython); 9017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetStdHandle(STD_OUTPUT_HANDLE, old_stdout); 9027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetStdHandle(STD_ERROR_HANDLE, old_stderr); 9037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* We only care about the output when we fail. If the script works 9047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou OK, then we discard it 9057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou */ 9067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (rc) { 9077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int err_buf_size; 9087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *err_buf; 9097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou const char *prefix = "Running the pre-installation script failed\r\n"; 9107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int prefix_len = strlen(prefix); 9117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou err_buf_size = GetFileSize(redirected, NULL); 9127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (err_buf_size==INVALID_FILE_SIZE) // an error - let's try anyway... 9137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou err_buf_size = 4096; 9147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou err_buf = malloc(prefix_len + err_buf_size + 1); 9157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (err_buf) { 9167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD n = 0; 9177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(err_buf, prefix); 9187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetFilePointer(redirected, 0, 0, FILE_BEGIN); 9197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ReadFile(redirected, err_buf+prefix_len, err_buf_size, &n, NULL); 9207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou err_buf[prefix_len+n] = '\0'; 9217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou set_failure_reason(err_buf); 9227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(err_buf); 9237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else { 9247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou set_failure_reason("Out of memory!"); 9257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 9267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 9277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CloseHandle(redirected); 9287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DeleteFile(tempname); 9297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return rc; 930a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller} 931a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 932a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller 933bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL SystemError(int error, char *msg) 934bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 9357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char Buffer[1024]; 9367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int n; 9377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 9387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (error) { 9397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LPVOID lpMsgBuf; 9407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FormatMessage( 9417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FORMAT_MESSAGE_ALLOCATE_BUFFER | 9427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FORMAT_MESSAGE_FROM_SYSTEM, 9437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 9447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou error, 9457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 9467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (LPSTR)&lpMsgBuf, 9477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 9487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL 9497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ); 9507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strncpy(Buffer, lpMsgBuf, sizeof(Buffer)); 9517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LocalFree(lpMsgBuf); 9527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else 9537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Buffer[0] = '\0'; 9547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou n = lstrlen(Buffer); 9557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou _snprintf(Buffer+n, sizeof(Buffer)-n, msg); 9567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(hwndMain, Buffer, "Runtime Error", MB_OK | MB_ICONSTOP); 9577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 958bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 959bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 960bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL notify (int code, char *fmt, ...) 961bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 9627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char Buffer[1024]; 9637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou va_list marker; 9647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou BOOL result = TRUE; 9657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int a, b; 9667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *cp; 967bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 9687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou va_start(marker, fmt); 9697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou _vsnprintf(Buffer, sizeof(Buffer), fmt, marker); 970bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 9717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (code) { 972bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Questions */ 9737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case CAN_OVERWRITE: 9747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 975bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 976bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Information notification */ 9777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case DIR_CREATED: 9787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (logfile) 9797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "100 Made Dir: %s\n", fmt); 9807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 9817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 9827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case FILE_CREATED: 9837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (logfile) 9847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "200 File Copy: %s\n", fmt); 9857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto add_to_filelist_label; 9867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 9877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 9887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case FILE_OVERWRITTEN: 9897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (logfile) 9907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "200 File Overwrite: %s\n", fmt); 9917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou add_to_filelist_label: 9927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if ((cp = strrchr(fmt, '.')) && (0 == strcmp (cp, ".py"))) 9937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou add_to_filelist(fmt); 9947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 995bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 996bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Error Messages */ 9977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case ZLIB_ERROR: 9987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), Buffer, "Error", 9997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_OK | MB_ICONWARNING); 10007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 10017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case SYSTEM_ERROR: 10037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SystemError(GetLastError(), Buffer); 10047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 10057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case NUM_FILES: 10077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou a = va_arg(marker, int); 10087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou b = va_arg(marker, int); 10097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendMessage(hDialog, WM_NUMFILES, 0, MAKELPARAM(0, a)); 10107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendMessage(hDialog, WM_NEXTFILE, b,(LPARAM)fmt); 10117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 10127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou va_end(marker); 10137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return result; 1015bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1016bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1017bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic char *MapExistingFile(char *pathname, DWORD *psize) 1018bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 10197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HANDLE hFile, hFileMapping; 10207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD nSizeLow, nSizeHigh; 10217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *data; 10227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hFile = CreateFile(pathname, 10247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GENERIC_READ, FILE_SHARE_READ, NULL, 10257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou OPEN_EXISTING, 10267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE_ATTRIBUTE_NORMAL, NULL); 10277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hFile == INVALID_HANDLE_VALUE) 10287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 10297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou nSizeLow = GetFileSize(hFile, &nSizeHigh); 10307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hFileMapping = CreateFileMapping(hFile, 10317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, PAGE_READONLY, 0, 0, NULL); 10327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CloseHandle(hFile); 10337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 1034b803c6c4b8d6256ac3d69f07f28c5c7024c3d4f5Gregory P. Smith if (hFileMapping == NULL) 10357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 10367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou data = MapViewOfFile(hFileMapping, 10387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE_MAP_READ, 0, 0, 0); 10397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CloseHandle(hFileMapping); 10417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *psize = nSizeLow; 10427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return data; 1043bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1044bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1045bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1046bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void create_bitmap(HWND hwnd) 1047bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 10487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou BITMAPFILEHEADER *bfh; 10497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou BITMAPINFO *bi; 10507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HDC hdc; 1051bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 10527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!bitmap_bytes) 10537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return; 1054bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 10557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hBitmap) 10567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return; 1057bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 10587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hdc = GetDC(hwnd); 1059bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 10607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bfh = (BITMAPFILEHEADER *)bitmap_bytes; 10617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bi = (BITMAPINFO *)(bitmap_bytes + sizeof(BITMAPFILEHEADER)); 1062bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 10637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hBitmap = CreateDIBitmap(hdc, 10647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &bi->bmiHeader, 10657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CBM_INIT, 10667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bitmap_bytes + bfh->bfOffBits, 10677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bi, 10687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DIB_RGB_COLORS); 10697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ReleaseDC(hwnd, hdc); 1070bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1071bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1072a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller/* Extract everything we need to begin the installation. Currently this 1073a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller is the INI filename with install data, and the raw pre-install script 1074a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Heller*/ 1075a19cdad6dc2815f6044c56601e8dd81d9c219631Thomas Hellerstatic BOOL ExtractInstallData(char *data, DWORD size, int *pexe_size, 10767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char **out_ini_file, char **out_preinstall_script) 1077bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 10787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* read the end of central directory record */ 10797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof 10807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (struct eof_cdir)]; 10817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir - 10837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou pe->ofsCDir; 10847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int ofs = arc_start - sizeof (struct meta_data_hdr); 10867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* read meta_data info */ 10887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct meta_data_hdr *pmd = (struct meta_data_hdr *)&data[ofs]; 10897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *src, *dst; 10907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *ini_file; 10917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char tempdir[MAX_PATH]; 10927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* ensure that if we fail, we don't have garbage out pointers */ 10947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *out_ini_file = *out_preinstall_script = NULL; 10957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 10967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (pe->tag != 0x06054b50) { 10977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 10987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 10997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 11007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (pmd->tag != 0x1234567B) { 11017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return SystemError(0, 11027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Invalid cfgdata magic number (see bdist_wininst.py)"); 11037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 11047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ofs < 0) { 11057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 11067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 11077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 11087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (pmd->bitmap_size) { 11097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Store pointer to bitmap bytes */ 11107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bitmap_bytes = (char *)pmd - pmd->uncomp_size - pmd->bitmap_size; 11117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 11127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 11137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *pexe_size = ofs - pmd->uncomp_size - pmd->bitmap_size; 11147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 11157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou src = ((char *)pmd) - pmd->uncomp_size; 11167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ini_file = malloc(MAX_PATH); /* will be returned, so do not free it */ 11177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!ini_file) 11187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 11197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!GetTempPath(sizeof(tempdir), tempdir) 11207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou || !GetTempFileName(tempdir, "~du", 0, ini_file)) { 11217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SystemError(GetLastError(), 11227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Could not create temporary file"); 11237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 11247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 11257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 11267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou dst = map_new_file(CREATE_ALWAYS, ini_file, NULL, pmd->uncomp_size, 11277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 0, NULL/*notify*/); 11287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!dst) 11297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 11307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Up to the first \0 is the INI file data. */ 11317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strncpy(dst, src, pmd->uncomp_size); 11327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou src += strlen(dst) + 1; 11337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Up to next \0 is the pre-install script */ 11347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *out_preinstall_script = strdup(src); 11357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *out_ini_file = ini_file; 11367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou UnmapViewOfFile(dst); 11377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 1138bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1139bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1140bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void PumpMessages(void) 1141bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 11427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MSG msg; 11437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 11447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou TranslateMessage(&msg); 11457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DispatchMessage(&msg); 11467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 1147bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1148bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1149bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerLRESULT CALLBACK 1150bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1151bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 11527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HDC hdc; 11537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HFONT hFont; 11547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int h; 11557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PAINTSTRUCT ps; 11567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (msg) { 11577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_PAINT: 11587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hdc = BeginPaint(hwnd, &ps); 11597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou h = GetSystemMetrics(SM_CYSCREEN) / 10; 11607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hFont = CreateFont(h, 0, 0, 0, 700, TRUE, 11617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 0, 0, 0, 0, 0, 0, "Times Roman"); 11627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hFont = SelectObject(hdc, hFont); 11637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetBkMode(hdc, TRANSPARENT); 11647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou TextOut(hdc, 15, 15, title, strlen(title)); 11657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetTextColor(hdc, RGB(255, 255, 255)); 11667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou TextOut(hdc, 10, 10, title, strlen(title)); 11677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DeleteObject(SelectObject(hdc, hFont)); 11687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou EndPaint(hwnd, &ps); 11697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 11707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 11717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return DefWindowProc(hwnd, msg, wParam, lParam); 1172bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1173bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1174bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic HWND CreateBackground(char *title) 1175bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 11767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou WNDCLASS wc; 11777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HWND hwnd; 11787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char buffer[4096]; 11797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 11807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.style = CS_VREDRAW | CS_HREDRAW; 11817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.lpfnWndProc = WindowProc; 11827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.cbWndExtra = 0; 11837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.cbClsExtra = 0; 11847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.hInstance = GetModuleHandle(NULL); 11857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.hIcon = NULL; 11867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.hCursor = LoadCursor(NULL, IDC_ARROW); 11877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 128)); 11887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.lpszMenuName = NULL; 11897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wc.lpszClassName = "SetupWindowClass"; 11907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 11917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!RegisterClass(&wc)) 11927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(hwndMain, 11937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Could not register window class", 11947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Setup.exe", MB_OK); 11957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 11967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(buffer, "Setup %s", title); 11977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hwnd = CreateWindow("SetupWindowClass", 11987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou buffer, 11997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 12007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 0, 12017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetSystemMetrics(SM_CXFULLSCREEN), 12027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetSystemMetrics(SM_CYFULLSCREEN), 12037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 12047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 12057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetModuleHandle(NULL), 12067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL); 12077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ShowWindow(hwnd, SW_SHOWMAXIMIZED); 12087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou UpdateWindow(hwnd); 12097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return hwnd; 1210bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1211bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1212bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1213bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Center a window on the screen 1214bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1215bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void CenterWindow(HWND hwnd) 1216bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 12177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RECT rc; 12187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int w, h; 12197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetWindowRect(hwnd, &rc); 12217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou w = GetSystemMetrics(SM_CXSCREEN); 12227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou h = GetSystemMetrics(SM_CYSCREEN); 12237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MoveWindow(hwnd, 12247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (w - (rc.right-rc.left))/2, 12257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (h - (rc.bottom-rc.top))/2, 12267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou rc.right-rc.left, rc.bottom-rc.top, FALSE); 1227bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1228bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1229bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#include <prsht.h> 1230bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 123165e4cb10d9d9964f30bc72561bf0e86833328a3bSteve DowerINT_PTR CALLBACK 1232bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerIntroDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1233bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 12347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LPNMHDR lpnm; 12357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char Buffer[4096]; 12367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (msg) { 12387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_INITDIALOG: 12397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou create_bitmap(hwnd); 12407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if(hBitmap) 12417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, 12427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou IMAGE_BITMAP, (LPARAM)hBitmap); 12437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CenterWindow(GetParent(hwnd)); 12447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(Buffer, 12457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "This Wizard will install %s on your computer. " 12467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Click Next to continue " 12477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "or Cancel to exit the Setup Wizard.", 12487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou meta_name); 12497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, Buffer); 12507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_INTRO_TEXT, info); 12517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_BUILD_INFO, build_info); 12527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 12537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_NOTIFY: 12557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou lpnm = (LPNMHDR) lParam; 12567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (lpnm->code) { 12587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_SETACTIVE: 12597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT); 12607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 12617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_WIZNEXT: 12637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 12647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_RESET: 12667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 12677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou default: 12697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 12707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 12717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 12727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 1273bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1274bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1275bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#ifdef USE_OTHER_PYTHON_VERSIONS 1276bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* These are really private variables used to communicate 1277bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * between StatusRoutine and CheckPythonExe 1278bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1279bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerchar bound_image_dll[_MAX_PATH]; 1280bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint bound_image_major; 1281bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint bound_image_minor; 1282bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1283bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL __stdcall StatusRoutine(IMAGEHLP_STATUS_REASON reason, 12847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PSTR ImageName, 12857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PSTR DllName, 12867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ULONG Va, 12877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ULONG Parameter) 1288bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 12897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char fname[_MAX_PATH]; 12907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int int_version; 12917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch(reason) { 12937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindOutOfMemory: 12947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindRvaToVaFailed: 12957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindNoRoomInImage: 12967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindImportProcedureFailed: 12977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 12987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 12997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindImportProcedure: 13007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindForwarder: 13017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindForwarderNOT: 13027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindImageModified: 13037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindExpandFileHeaders: 13047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindImageComplete: 13057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindSymbolsNotUpdated: 13067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindMismatchedSymbols: 13077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindImportModuleFailed: 13087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 13097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case BindImportModule: 13117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (1 == sscanf(DllName, "python%d", &int_version)) { 13127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SearchPath(NULL, DllName, NULL, sizeof(fname), 13137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fname, NULL); 13147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(bound_image_dll, fname); 13157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bound_image_major = int_version / 10; 13167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bound_image_minor = int_version % 10; 13177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou OutputDebugString("BOUND "); 13187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou OutputDebugString(fname); 13197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou OutputDebugString("\n"); 13207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 13217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 13227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 13237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 1324bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1325bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1326bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1327bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1328bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic LPSTR get_sys_prefix(LPSTR exe, LPSTR dll) 1329bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 13307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou void (__cdecl * Py_Initialize)(void); 13317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou void (__cdecl * Py_SetProgramName)(char *); 13327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou void (__cdecl * Py_Finalize)(void); 13337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou void* (__cdecl * PySys_GetObject)(char *); 13347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou void (__cdecl * PySys_SetArgv)(int, char **); 13357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char* (__cdecl * Py_GetPrefix)(void); 13367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char* (__cdecl * Py_GetPath)(void); 13377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HINSTANCE hPython; 13387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LPSTR prefix = NULL; 13397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int (__cdecl * PyRun_SimpleString)(char *); 13407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { 13427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char Buffer[256]; 13437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(Buffer, "PYTHONHOME=%s", exe); 13447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *strrchr(Buffer, '\\') = '\0'; 13457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou// MessageBox(GetFocus(), Buffer, "PYTHONHOME", MB_OK); 13467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou _putenv(Buffer); 13477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou _putenv("PYTHONPATH="); 13487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 13497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hPython = LoadLibrary(dll); 13517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!hPython) 13527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return NULL; 13537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_Initialize = (void (*)(void))GetProcAddress 13547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (hPython,"Py_Initialize"); 13557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PySys_SetArgv = (void (*)(int, char **))GetProcAddress 13577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (hPython,"PySys_SetArgv"); 13587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PyRun_SimpleString = (int (*)(char *))GetProcAddress 13607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (hPython,"PyRun_SimpleString"); 13617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_SetProgramName = (void (*)(char *))GetProcAddress 13637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (hPython,"Py_SetProgramName"); 13647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PySys_GetObject = (void* (*)(char *))GetProcAddress 13667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (hPython,"PySys_GetObject"); 13677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_GetPrefix = (char * (*)(void))GetProcAddress 13697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (hPython,"Py_GetPrefix"); 13707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_GetPath = (char * (*)(void))GetProcAddress 13727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (hPython,"Py_GetPath"); 13737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_Finalize = (void (*)(void))GetProcAddress(hPython, 13757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Py_Finalize"); 13767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_SetProgramName(exe); 13777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_Initialize(); 13787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PySys_SetArgv(1, &exe); 13797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), Py_GetPrefix(), "PREFIX", MB_OK); 13817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), Py_GetPath(), "PATH", MB_OK); 13827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Py_Finalize(); 13847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FreeLibrary(hPython); 13857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 13867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return prefix; 1387bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1388bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1389bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL 1390bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerCheckPythonExe(LPSTR pathname, LPSTR version, int *pmajor, int *pminor) 1391bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 13927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bound_image_dll[0] = '\0'; 13937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!BindImageEx(BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE | BIND_ALL_IMAGES, 13947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou pathname, 13957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 13967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 13977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou StatusRoutine)) 13987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return SystemError(0, "Could not bind image"); 13997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (bound_image_dll[0] == '\0') 14007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return SystemError(0, "Does not seem to be a python executable"); 14017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *pmajor = bound_image_major; 14027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *pminor = bound_image_minor; 14037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (version && *version) { 14047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char core_version[12]; 14057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(core_version, "%d.%d", bound_image_major, bound_image_minor); 14067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (strcmp(version, core_version)) 14077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return SystemError(0, "Wrong Python version"); 14087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 14097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou get_sys_prefix(pathname, bound_image_dll); 14107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 1411bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1412bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1413bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1414bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Browse for other python versions. Insert it into the listbox specified 1415bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * by hwnd. version, if not NULL or empty, is the version required. 1416bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1417bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL GetOtherPythonVersion(HWND hwnd, LPSTR version) 1418bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 14197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char vers_name[_MAX_PATH + 80]; 14207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD itemindex; 14217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou OPENFILENAME of; 14227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char pathname[_MAX_PATH]; 14237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD result; 14247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 14257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(pathname, "python.exe"); 14267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 14277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou memset(&of, 0, sizeof(of)); 14287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.lStructSize = sizeof(OPENFILENAME); 14297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.hwndOwner = GetParent(hwnd); 14307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.hInstance = NULL; 14317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.lpstrFilter = "python.exe\0python.exe\0"; 14327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.lpstrCustomFilter = NULL; 14337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.nMaxCustFilter = 0; 14347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.nFilterIndex = 1; 14357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.lpstrFile = pathname; 14367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.nMaxFile = sizeof(pathname); 14377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.lpstrFileTitle = NULL; 14387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.nMaxFileTitle = 0; 14397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.lpstrInitialDir = NULL; 14407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.lpstrTitle = "Python executable"; 14417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; 14427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou of.lpstrDefExt = "exe"; 14437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 14447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = GetOpenFileName(&of); 14457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result) { 14467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int major, minor; 14477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!CheckPythonExe(pathname, version, &major, &minor)) { 14487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 14497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 14507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *strrchr(pathname, '\\') = '\0'; 14517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(vers_name, "Python Version %d.%d in %s", 14527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou major, minor, pathname); 14537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou itemindex = SendMessage(hwnd, LB_INSERTSTRING, -1, 14547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (LPARAM)(LPSTR)vers_name); 14557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendMessage(hwnd, LB_SETCURSEL, itemindex, 0); 14567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendMessage(hwnd, LB_SETITEMDATA, itemindex, 14577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (LPARAM)(LPSTR)strdup(pathname)); 14587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 14597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 14607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 1461bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1462bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#endif /* USE_OTHER_PYTHON_VERSIONS */ 1463bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1464f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammondtypedef struct _InstalledVersionInfo { 1465f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond char prefix[MAX_PATH+1]; // sys.prefix directory. 1466f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond HKEY hkey; // Is this Python in HKCU or HKLM? 1467f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond} InstalledVersionInfo; 1468f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond 1469bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1470bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1471bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Fill the listbox specified by hwnd with all python versions found 1472bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * in the registry. version, if not NULL or empty, is the version 1473bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * required. 1474bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 1475bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL GetPythonVersions(HWND hwnd, HKEY hkRoot, LPSTR version) 1476bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 14777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD index = 0; 14787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char core_version[80]; 14797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY hKey; 14807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou BOOL result = TRUE; 14817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD bufsize; 14827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 14837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ERROR_SUCCESS != RegOpenKeyEx(hkRoot, 14847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Software\\Python\\PythonCore", 14857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, KEY_READ, &hKey)) 14867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 14877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bufsize = sizeof(core_version); 14887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index, 14897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou core_version, &bufsize, NULL, 14907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, NULL, NULL)) { 14917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char subkey_name[80], vers_name[80]; 14927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int itemindex; 14937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD value_size; 14947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY hk; 14957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 14967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou bufsize = sizeof(core_version); 14977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++index; 14987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (version && *version && strcmp(version, core_version)) 14997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou continue; 15007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 15017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(vers_name, "Python Version %s (found in registry)", 15027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou core_version); 15037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(subkey_name, 15047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Software\\Python\\PythonCore\\%s\\InstallPath", 15057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou core_version); 15067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ERROR_SUCCESS == RegOpenKeyEx(hkRoot, subkey_name, 0, KEY_READ, &hk)) { 15077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou InstalledVersionInfo *ivi = 15087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (InstalledVersionInfo *)malloc(sizeof(InstalledVersionInfo)); 15097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou value_size = sizeof(ivi->prefix); 15107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ivi && 15117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ERROR_SUCCESS == RegQueryValueEx(hk, NULL, NULL, NULL, 15127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ivi->prefix, &value_size)) { 15137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou itemindex = SendMessage(hwnd, LB_ADDSTRING, 0, 15147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (LPARAM)(LPSTR)vers_name); 15157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ivi->hkey = hkRoot; 15167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendMessage(hwnd, LB_SETITEMDATA, itemindex, 15177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (LPARAM)(LPSTR)ivi); 15187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 15197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RegCloseKey(hk); 15207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 15217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 15227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RegCloseKey(hKey); 15237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return result; 1524bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1525bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1526f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond/* Determine if the current user can write to HKEY_LOCAL_MACHINE */ 1527f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark HammondBOOL HasLocalMachinePrivs() 1528f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond{ 15297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY hKey; 15307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD result; 15317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou static char KeyName[] = 15327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; 15337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 15347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 15357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KeyName, 15367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 15377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KEY_CREATE_SUB_KEY, 15387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &hKey); 15397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result==0) 15407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RegCloseKey(hKey); 15417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return result==0; 1542f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond} 1543f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond 1544f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// Check the root registry key to use - either HKLM or HKCU. 1545f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// If Python is installed in HKCU, then our extension also must be installed 1546f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// in HKCU - as Python won't be available for other users, we shouldn't either 1547f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// (and will fail if we are!) 1548f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// If Python is installed in HKLM, then we will also prefer to use HKLM, but 1549f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// this may not be possible - so we silently fall back to HKCU. 1550f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// 1551f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond// We assume hkey_root is already set to where Python itself is installed. 1552f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammondvoid CheckRootKey(HWND hwnd) 1553f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond{ 15547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hkey_root==HKEY_CURRENT_USER) { 15557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ; // as above, always install ourself in HKCU too. 15567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else if (hkey_root==HKEY_LOCAL_MACHINE) { 15577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // Python in HKLM, but we may or may not have permissions there. 15587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // Open the uninstall key with 'create' permissions - if this fails, 15597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // we don't have permission. 15607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!HasLocalMachinePrivs()) 15617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hkey_root = HKEY_CURRENT_USER; 15627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else { 15637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(hwnd, "Don't know Python's installation type", 15647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Strange", MB_OK | MB_ICONSTOP); 15657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Default to wherever they can, but preferring HKLM */ 15667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hkey_root = HasLocalMachinePrivs() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 15677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 1568f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond} 1569f9bfdd850cd00e00c0895b3f73afd019b7a9dfdbMark Hammond 1570bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Return the installation scheme depending on Python version number */ 1571bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerSCHEME *GetScheme(int major, int minor) 1572bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 15737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (major > 2) 15747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return new_scheme; 15757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else if((major == 2) && (minor >= 2)) 15767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return new_scheme; 15777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return old_scheme; 1578bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1579bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 158065e4cb10d9d9964f30bc72561bf0e86833328a3bSteve DowerINT_PTR CALLBACK 1581bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerSelectPythonDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1582bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 15837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LPNMHDR lpnm; 15847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 15857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (msg) { 15867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_INITDIALOG: 15877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hBitmap) 15887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, 15897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou IMAGE_BITMAP, (LPARAM)hBitmap); 15907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST), 15917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY_LOCAL_MACHINE, target_version); 15927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST), 15937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY_CURRENT_USER, target_version); 15947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { /* select the last entry which is the highest python 15957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou version found */ 15967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int count; 15977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou count = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 15987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LB_GETCOUNT, 0, 0); 15997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (count && count != LB_ERR) 16007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, LB_SETCURSEL, 16017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou count-1, 0); 16027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 16037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* If a specific Python version is required, 16047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * display a prominent notice showing this fact. 16057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou */ 16067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (target_version && target_version[0]) { 16077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char buffer[4096]; 16087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(buffer, 16097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Python %s is required for this package. " 16107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Select installation to use:", 16117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou target_version); 16127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, buffer); 16137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 16147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 16157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (count == 0) { 16167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char Buffer[4096]; 16177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *msg; 16187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (target_version && target_version[0]) { 16197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(Buffer, 16207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Python version %s required, which was not found" 16217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou " in the registry.", target_version); 16227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou msg = Buffer; 16237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else 16247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou msg = "No Python installation found in the registry."; 16257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(hwnd, msg, "Cannot install", 16267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_OK | MB_ICONSTOP); 16277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 16287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 16297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou goto UpdateInstallDir; 16307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 16317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 16327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_COMMAND: 16337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (LOWORD(wParam)) { 1634bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1635bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller case IDC_OTHERPYTHON: 1636bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller if (GetOtherPythonVersion(GetDlgItem(hwnd, IDC_VERSIONS_LIST), 1637bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller target_version)) 1638bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller goto UpdateInstallDir; 1639bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller break; 1640bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller*/ 16417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case IDC_VERSIONS_LIST: 16427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (HIWORD(wParam)) { 16437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int id; 16447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case LBN_SELCHANGE: 16457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou UpdateInstallDir: 16467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 16477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PSWIZB_BACK | PSWIZB_NEXT); 16487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 16497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LB_GETCURSEL, 0, 0); 16507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (id == LB_ERR) { 16517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 16527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PSWIZB_BACK); 16537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_PATH, ""); 16547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_INSTALL_PATH, ""); 16557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(python_dir, ""); 16567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(pythondll, ""); 16577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else { 16587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *pbuf; 16597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int result; 16607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou InstalledVersionInfo *ivi; 16617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 16627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PSWIZB_BACK | PSWIZB_NEXT); 16637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Get the python directory */ 16646d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter ivi = (InstalledVersionInfo *) 16657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, 16666d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter IDC_VERSIONS_LIST, 16676d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter LB_GETITEMDATA, 16686d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter id, 16696d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter 0); 16706d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter hkey_root = ivi->hkey; 16716d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter strcpy(python_dir, ivi->prefix); 16726d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter SetDlgItemText(hwnd, IDC_PATH, python_dir); 16736d57fe1c23430d0d51de243a177670b76c37dab5Martin Panter /* retrieve the python version and pythondll to use */ 16747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 16757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LB_GETTEXTLEN, (WPARAM)id, 0); 16767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou pbuf = (char *)malloc(result + 1); 16777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (pbuf) { 16787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* guess the name of the python-dll */ 16797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 16807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LB_GETTEXT, (WPARAM)id, 16817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou (LPARAM)pbuf); 16827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = sscanf(pbuf, "Python Version %d.%d", 16837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &py_major, &py_minor); 16847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result == 2) { 1685bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#ifdef _DEBUG 16867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(pythondll, "python%d%d_d.dll", 16877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou py_major, py_minor); 1688bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#else 16897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(pythondll, "python%d%d.dll", 16907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou py_major, py_minor); 1691bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller#endif 16927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 16937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(pbuf); 16947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else 16957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(pythondll, ""); 16967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* retrieve the scheme for this version */ 16977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { 16987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char install_path[_MAX_PATH]; 16997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SCHEME *scheme = GetScheme(py_major, py_minor); 17007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(install_path, python_dir); 17017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (install_path[strlen(install_path)-1] != '\\') 17027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcat(install_path, "\\"); 17037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcat(install_path, scheme[0].prefix); 17047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_INSTALL_PATH, install_path); 17057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 17067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 17077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 17087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 17097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 17107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 17117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 17127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_NOTIFY: 17137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou lpnm = (LPNMHDR) lParam; 17147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 17157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (lpnm->code) { 17167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int id; 17177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_SETACTIVE: 17187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, 17197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LB_GETCURSEL, 0, 0); 17207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (id == LB_ERR) 17217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 17227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PSWIZB_BACK); 17237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else 17247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 17257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PSWIZB_BACK | PSWIZB_NEXT); 17267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 17277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 17287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_WIZNEXT: 17297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 17307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 17317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_WIZFINISH: 17327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 17337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 17347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_RESET: 17357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 17367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 17377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou default: 17387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 17397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 17407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 17417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 1742bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1743bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1744bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic BOOL OpenLogfile(char *dir) 1745bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 17467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char buffer[_MAX_PATH+1]; 17477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou time_t ltime; 17487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct tm *now; 17497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou long result; 17507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY hKey, hSubkey; 17517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char subkey_name[256]; 17527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou static char KeyName[] = 17537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; 17547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou const char *root_name = (hkey_root==HKEY_LOCAL_MACHINE ? 17557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER"); 17567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DWORD disposition; 17577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 17587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Use Create, as the Uninstall subkey may not exist under HKCU. 17597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Use CreateKeyEx, so we can specify a SAM specifying write access 17607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou */ 17617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegCreateKeyEx(hkey_root, 17627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KeyName, 17637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, /* reserved */ 17647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, /* class */ 17657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, /* options */ 17667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KEY_CREATE_SUB_KEY, /* sam */ 17677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, /* security */ 17687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &hKey, /* result key */ 17697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL); /* disposition */ 17707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result != ERROR_SUCCESS) { 17717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result == ERROR_ACCESS_DENIED) { 17727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* This should no longer be able to happen - we have already 17737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou checked if they have permissions in HKLM, and all users 17747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou should have write access to HKCU. 17757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou */ 17767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), 17777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "You do not seem to have sufficient access rights\n" 17787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "on this machine to install this software", 17797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 17807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_OK | MB_ICONSTOP); 17817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 17827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else { 17837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), KeyName, "Could not open key", MB_OK); 17847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 17857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 17867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 17877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sprintf(buffer, "%s\\%s-wininst.log", dir, meta_name); 17887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou logfile = fopen(buffer, "a"); 178925c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson if (!logfile) { 179025c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson char error[1024]; 179125c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson 179225c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson sprintf(error, "Can't create \"%s\" (%s).\n\n" 179325c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson "Try to execute the installer as administrator.", 179425c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson buffer, strerror(errno)); 179525c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson MessageBox(GetFocus(), error, NULL, MB_OK | MB_ICONSTOP); 179625c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson return FALSE; 179725c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson } 179825c7d3fb2125f964fe5b9317b31de39117072150Benjamin Peterson 17997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou time(<ime); 18007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou now = localtime(<ime); 18017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strftime(buffer, sizeof(buffer), 18027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "*** Installation started %Y/%m/%d %H:%M ***\n", 18037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou localtime(<ime)); 18047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, buffer); 18057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "Source: %s\n", modulename); 18067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Root key must be first entry processed by uninstaller. */ 18087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "999 Root Key: %s\n", root_name); 18097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sprintf(subkey_name, "%s-py%d.%d", meta_name, py_major, py_minor); 18117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegCreateKeyEx(hKey, subkey_name, 18137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, NULL, 0, 18147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KEY_WRITE, 18157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 18167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &hSubkey, 18177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &disposition); 18187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result != ERROR_SUCCESS) 18207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), subkey_name, "Could not create key", MB_OK); 18217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RegCloseKey(hKey); 18237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (disposition == REG_CREATED_NEW_KEY) 18257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "020 Reg DB Key: [%s]%s\n", KeyName, subkey_name); 18267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sprintf(buffer, "Python %d.%d %s", py_major, py_minor, title); 18287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegSetValueEx(hSubkey, "DisplayName", 18307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 18317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou REG_SZ, 18327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou buffer, 18337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strlen(buffer)+1); 18347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result != ERROR_SUCCESS) 18367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK); 18377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n", 18397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KeyName, subkey_name, "DisplayName", buffer); 18407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou { 18427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE *fp; 18437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sprintf(buffer, "%s\\Remove%s.exe", dir, meta_name); 18447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fp = fopen(buffer, "wb"); 18457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fwrite(arc_data, exe_size, 1, fp); 18467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fclose(fp); 18477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sprintf(buffer, "\"%s\\Remove%s.exe\" -u \"%s\\%s-wininst.log\"", 18497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou dir, meta_name, dir, meta_name); 18507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegSetValueEx(hSubkey, "UninstallString", 18527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 18537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou REG_SZ, 18547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou buffer, 18557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strlen(buffer)+1); 18567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result != ERROR_SUCCESS) 18587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK); 18597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n", 18617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KeyName, subkey_name, "UninstallString", buffer); 18627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 18637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 1864bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1865bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1866bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic void CloseLogfile(void) 1867bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 18687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char buffer[_MAX_PATH+1]; 18697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou time_t ltime; 18707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou struct tm *now; 18717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou time(<ime); 18737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou now = localtime(<ime); 18747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strftime(buffer, sizeof(buffer), 18757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "*** Installation finished %Y/%m/%d %H:%M ***\n", 18767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou localtime(<ime)); 18777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, buffer); 18787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (logfile) 18797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fclose(logfile); 1880bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 1881bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 188265e4cb10d9d9964f30bc72561bf0e86833328a3bSteve DowerINT_PTR CALLBACK 1883bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerInstallFilesDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 1884bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 18857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LPNMHDR lpnm; 18867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char Buffer[4096]; 18877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SCHEME *scheme; 18887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 18897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (msg) { 18907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_INITDIALOG: 18917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hBitmap) 18927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, 18937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou IMAGE_BITMAP, (LPARAM)hBitmap); 18947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(Buffer, 18957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Click Next to begin the installation of %s. " 18967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "If you want to review or change any of your " 18977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou " installation settings, click Back. " 18987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Click Cancel to exit the wizard.", 18997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou meta_name); 19007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, Buffer); 19017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_INFO, "Ready to install"); 19027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 19037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_NUMFILES: 19057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, lParam); 19067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PumpMessages(); 19077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 19087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_NEXTFILE: 19107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, wParam, 19117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0); 19127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_INFO, (LPSTR)lParam); 19137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PumpMessages(); 19147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 19157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_NOTIFY: 19177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou lpnm = (LPNMHDR) lParam; 19187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (lpnm->code) { 19207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_SETACTIVE: 19217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 19227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PSWIZB_BACK | PSWIZB_NEXT); 19237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 19247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_WIZFINISH: 19267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 19277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_WIZNEXT: 19297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Handle a Next button click here */ 19307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hDialog = hwnd; 19317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou success = TRUE; 19327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Disable the buttons while we work. Sending CANCELTOCLOSE has 19347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou the effect of disabling the cancel button, which is a) as we 19357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou do everything synchronously we can't cancel, and b) the next 19367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou step is 'finished', when it is too late to cancel anyway. 19377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou The next step being 'Finished' means we also don't need to 19387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou restore the button state back */ 19397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), 0); 19407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendMessage(GetParent(hwnd), PSM_CANCELTOCLOSE, 0, 0); 19417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Make sure the installation directory name ends in a */ 19427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* backslash */ 19437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (python_dir[strlen(python_dir)-1] != '\\') 19447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcat(python_dir, "\\"); 19457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Strip the trailing backslash again */ 19467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou python_dir[strlen(python_dir)-1] = '\0'; 19477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CheckRootKey(hwnd); 19497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!OpenLogfile(python_dir)) 19517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 1952bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 1953bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 1954bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * The scheme we have to use depends on the Python version... 1955bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller if sys.version < "2.2": 1956d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka WINDOWS_SCHEME = { 1957d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'purelib': '$base', 1958d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'platlib': '$base', 1959d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'headers': '$base/Include/$dist_name', 1960d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'scripts': '$base/Scripts', 1961d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'data' : '$base', 1962d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka } 1963bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller else: 1964d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka WINDOWS_SCHEME = { 1965d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'purelib': '$base/Lib/site-packages', 1966d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'platlib': '$base/Lib/site-packages', 1967d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'headers': '$base/Include/$dist_name', 1968d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'scripts': '$base/Scripts', 1969d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka 'data' : '$base', 1970d741a880497b8458ef068c111caa64546166e3ffSerhiy Storchaka } 1971bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller*/ 19727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou scheme = GetScheme(py_major, py_minor); 19737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Run the pre-install script. */ 19747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (pre_install_script && *pre_install_script) { 19757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText (hwnd, IDC_TITLE, 19767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Running pre-installation script"); 19777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou run_simple_script(pre_install_script); 19787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 19797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!success) { 19807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 19817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 19827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Extract all files from the archive */ 19837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, "Installing files..."); 19847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!unzip_archive (scheme, 19857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou python_dir, arc_data, 19867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou arc_size, notify)) 19877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou set_failure_reason("Failed to unzip installation files"); 19887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Compile the py-files */ 19897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (success && pyc_compile) { 19907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int errors; 19917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HINSTANCE hPython; 19927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, 19937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Compiling files to .pyc..."); 19947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 19957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hDialog, IDC_INFO, "Loading python..."); 19967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hPython = LoadPythonDll(pythondll); 19977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hPython) { 19987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou errors = compile_filelist(hPython, FALSE); 19997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FreeLibrary(hPython); 20007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 20017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Compilation errors are intentionally ignored: 20027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * Python2.0 contains a bug which will result 20037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * in sys.path containing garbage under certain 20047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * circumstances, and an error message will only 20057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * confuse the user. 20067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou */ 20077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 20087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (success && pyo_compile) { 20097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int errors; 20107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HINSTANCE hPython; 20117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, 20127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Compiling files to .pyo..."); 20137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hDialog, IDC_INFO, "Loading python..."); 20157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hPython = LoadPythonDll(pythondll); 20167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hPython) { 20177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou errors = compile_filelist(hPython, TRUE); 20187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FreeLibrary(hPython); 20197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 20207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Errors ignored: see above */ 20217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 20227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 20257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_RESET: 20277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 20287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou default: 20307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 20317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 20327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 20337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 2034bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2035bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2036bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 203765e4cb10d9d9964f30bc72561bf0e86833328a3bSteve DowerINT_PTR CALLBACK 2038bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerFinishedDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 2039bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 20407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LPNMHDR lpnm; 20417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (msg) { 20437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_INITDIALOG: 20447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hBitmap) 20457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, 20467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou IMAGE_BITMAP, (LPARAM)hBitmap); 20477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!success) 20487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_INFO, get_failure_reason()); 20497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* async delay: will show the dialog box completely before 20517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou the install_script is started */ 20527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PostMessage(hwnd, WM_USER, 0, 0L); 20537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 20547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_USER: 20567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (success && install_script && install_script[0]) { 20587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char fname[MAX_PATH]; 20597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *buffer; 20607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HCURSOR hCursor; 20617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int result; 20627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *argv[3] = {NULL, "-install", NULL}; 20647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, 20667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Please wait while running postinstall script..."); 20677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(fname, python_dir); 20687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcat(fname, "\\Scripts\\"); 20697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcat(fname, install_script); 20707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (logfile) 20727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(logfile, "300 Run Script: [%s]%s\n", pythondll, fname); 20737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); 20757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou argv[0] = fname; 20777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = run_installscript(fname, 2, argv, &buffer); 20797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (0 != result) { 20807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(stderr, "*** run_installscript: internal error 0x%X ***\n", result); 20817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 20827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (buffer) 20837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_INFO, buffer); 20847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetDlgItemText(hwnd, IDC_TITLE, 20857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Postinstall script finished.\n" 20867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Click the Finish button to exit the Setup wizard."); 20877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(buffer); 20897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetCursor(hCursor); 20907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CloseLogfile(); 20917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 20927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 20947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case WM_NOTIFY: 20967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou lpnm = (LPNMHDR) lParam; 20977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 20987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou switch (lpnm->code) { 20997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_SETACTIVE: /* Enable the Finish button */ 21007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH); 21017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 21027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_WIZNEXT: 21047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 21057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_WIZFINISH: 21077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 21087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou case PSN_RESET: 21107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 21117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou default: 21137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou break; 21147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 21157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 21167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 2117bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2118bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2119bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid RunWizard(HWND hwnd) 2120bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 21217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PROPSHEETPAGE psp = {0}; 21227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HPROPSHEETPAGE ahpsp[4] = {0}; 21237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PROPSHEETHEADER psh = {0}; 21247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Display module information */ 21267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.dwSize = sizeof(psp); 21277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; 21287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.hInstance = GetModuleHandle (NULL); 21297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.lParam = 0; 21307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.pfnDlgProc = IntroDlgProc; 21317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.pszTemplate = MAKEINTRESOURCE(IDD_INTRO); 21327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ahpsp[0] = CreatePropertySheetPage(&psp); 21347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Select python version to use */ 21367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; 21377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.pszTemplate = MAKEINTRESOURCE(IDD_SELECTPYTHON); 21387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.pfnDlgProc = SelectPythonDlgProc; 21397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ahpsp[1] = CreatePropertySheetPage(&psp); 21417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Install the files */ 21437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; 21447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLFILES); 21457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.pfnDlgProc = InstallFilesDlgProc; 21467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ahpsp[2] = CreatePropertySheetPage(&psp); 21487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Show success or failure */ 21507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER; 21517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHED); 21527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psp.pfnDlgProc = FinishedDlgProc; 21537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ahpsp[3] = CreatePropertySheetPage(&psp); 21557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Create the property sheet */ 21577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.dwSize = sizeof(psh); 21587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.hInstance = GetModuleHandle(NULL); 21597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.hwndParent = hwnd; 21607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.phpage = ahpsp; 21617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.dwFlags = PSH_WIZARD/*97*//*|PSH_WATERMARK|PSH_HEADER*/; 21627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.pszbmWatermark = NULL; 21637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.pszbmHeader = NULL; 21647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.nStartPage = 0; 21657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou psh.nPages = 4; 21667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 21677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PropertySheet(&psh); 2168bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2169bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 217081ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// subtly different from HasLocalMachinePrivs(), in that after executing 217181ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// an 'elevated' process, we expect this to return TRUE - but there is no 217281ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// such implication for HasLocalMachinePrivs 217381ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian HeimesBOOL MyIsUserAnAdmin() 217481ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes{ 21757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou typedef BOOL (WINAPI *PFNIsUserAnAdmin)(); 21767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou static PFNIsUserAnAdmin pfnIsUserAnAdmin = NULL; 21777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HMODULE shell32; 21787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // This function isn't guaranteed to be available (and it can't hurt 21797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // to leave the library loaded) 21807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (0 == (shell32=LoadLibrary("shell32.dll"))) 21817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 21827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (0 == (pfnIsUserAnAdmin=(PFNIsUserAnAdmin)GetProcAddress(shell32, "IsUserAnAdmin"))) 21837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 21847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return (*pfnIsUserAnAdmin)(); 218581ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes} 218681ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes 218781ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// Some magic for Vista's UAC. If there is a target_version, and 218881ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// if that target version is installed in the registry under 218981ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// HKLM, and we are not current administrator, then 219081ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// re-execute ourselves requesting elevation. 219181ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// Split into 2 functions - "should we elevate" and "spawn elevated" 219281ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes 219381ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// Returns TRUE if we should spawn an elevated child 219481ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian HeimesBOOL NeedAutoUAC() 219581ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes{ 21967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY hk; 21977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char key_name[80]; 21987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // no Python version info == we can't know yet. 21997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (target_version[0] == '\0') 22007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 22017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // see how python is current installed 22027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(key_name, 22037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Software\\Python\\PythonCore\\%s\\InstallPath", 22047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou target_version); 22057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, 22067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou key_name, 0, KEY_READ, &hk)) 22077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 22087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RegCloseKey(hk); 22097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // Python is installed in HKLM - we must elevate. 22107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 221181ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes} 221281ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes 221381ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// Spawn ourself as an elevated application. On failure, a message is 221481ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// displayed to the user - but this app will always terminate, even 221581ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes// on error. 221681ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimesvoid SpawnUAC() 221781ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes{ 22187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // interesting failure scenario that has been seen: initial executable 22197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // runs from a network drive - but once elevated, that network share 22207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // isn't seen, and ShellExecute fails with SE_ERR_ACCESSDENIED. 22217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int ret = (int)ShellExecute(0, "runas", modulename, "", NULL, 22227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SW_SHOWNORMAL); 22237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ret <= 32) { 22247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char msg[128]; 22257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(msg, "Failed to start elevated process (ShellExecute returned %d)", ret); 22267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(0, msg, "Setup", MB_OK | MB_ICONERROR); 22277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 222881ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes} 222981ee3efededdaba0a7c0b1a3aac07727cebb6fc1Christian Heimes 2230bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint DoInstall(void) 2231bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 22327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char ini_buffer[4096]; 22337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Read installation information */ 22357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPrivateProfileString("Setup", "title", "", ini_buffer, 22367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sizeof(ini_buffer), ini_file); 22377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou unescape(title, ini_buffer, sizeof(title)); 22387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPrivateProfileString("Setup", "info", "", ini_buffer, 22407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sizeof(ini_buffer), ini_file); 22417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou unescape(info, ini_buffer, sizeof(info)); 22427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPrivateProfileString("Setup", "build_info", "", build_info, 22447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sizeof(build_info), ini_file); 22457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou pyc_compile = GetPrivateProfileInt("Setup", "target_compile", 1, 22477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ini_file); 22487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou pyo_compile = GetPrivateProfileInt("Setup", "target_optimize", 1, 22497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ini_file); 22507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPrivateProfileString("Setup", "target_version", "", 22527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou target_version, sizeof(target_version), 22537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ini_file); 22547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPrivateProfileString("metadata", "name", "", 22567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou meta_name, sizeof(meta_name), 22577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ini_file); 22587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPrivateProfileString("Setup", "install_script", "", 22607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou install_script, sizeof(install_script), 22617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ini_file); 22627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetPrivateProfileString("Setup", "user_access_control", "", 22647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou user_access_control, sizeof(user_access_control), ini_file); 22657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 2266332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower strcat(target_version, REGISTRY_SUFFIX_6432); 2267332334f1abdca7d8c55f3e8f59da4ca048b42754Steve Dower 22687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // See if we need to do the Vista UAC magic. 22697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (strcmp(user_access_control, "force")==0) { 227065e4cb10d9d9964f30bc72561bf0e86833328a3bSteve Dower if (!MyIsUserAnAdmin()) { 22717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SpawnUAC(); 22727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 22737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 22747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // already admin - keep going 22757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else if (strcmp(user_access_control, "auto")==0) { 22767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // Check if it looks like we need UAC control, based 22777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // on how Python itself was installed. 227865e4cb10d9d9964f30bc72561bf0e86833328a3bSteve Dower if (!MyIsUserAnAdmin() && NeedAutoUAC()) { 22797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SpawnUAC(); 22807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 22817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 22827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else { 22837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // display a warning about unknown values - only the developer 22847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // of the extension will see it (until they fix it!) 22857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (user_access_control[0] && strcmp(user_access_control, "none") != 0) { 22867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), "Bad user_access_control value", "oops", MB_OK); 22877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // nothing to do. 22887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 22897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 22907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hwndMain = CreateBackground(title); 22927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RunWizard(hwndMain); 22947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 22957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Clean up */ 22967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou UnmapViewOfFile(arc_data); 22977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ini_file) 22987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DeleteFile(ini_file); 22997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (hBitmap) 23017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DeleteObject(hBitmap); 23027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 2304bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2305bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2306bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/*********************** uninstall section ******************************/ 2307bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2308bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerstatic int compare(const void *p1, const void *p2) 2309bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 23107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return strcmp(*(char **)p2, *(char **)p1); 2311bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2312bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2313bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* 2314bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Commit suicide (remove the uninstaller itself). 2315bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 2316bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * Create a batch file to first remove the uninstaller 2317bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * (will succeed after it has finished), then the batch file itself. 2318bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * 2319bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * This technique has been demonstrated by Jeff Richter, 2320bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller * MSJ 1/1996 2321bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller */ 2322bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid remove_exe(void) 2323bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 23247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char exename[_MAX_PATH]; 23257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char batname[_MAX_PATH]; 23267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE *fp; 23277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou STARTUPINFO si; 23287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou PROCESS_INFORMATION pi; 23297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetModuleFileName(NULL, exename, sizeof(exename)); 23317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sprintf(batname, "%s.bat", exename); 23327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fp = fopen(batname, "w"); 23337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(fp, ":Repeat\n"); 23347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(fp, "del \"%s\"\n", exename); 23357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(fp, "if exist \"%s\" goto Repeat\n", exename); 23367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(fp, "del \"%s\"\n", batname); 23377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fclose(fp); 23387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ZeroMemory(&si, sizeof(si)); 23407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou si.cb = sizeof(si); 23417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou si.dwFlags = STARTF_USESHOWWINDOW; 23427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou si.wShowWindow = SW_HIDE; 23437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (CreateProcess(NULL, 23447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou batname, 23457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 23467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 23477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FALSE, 23487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CREATE_SUSPENDED | IDLE_PRIORITY_CLASS, 23497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 23507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "\\", 23517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &si, 23527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &pi)) { 23537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetThreadPriority(pi.hThread, THREAD_PRIORITY_IDLE); 23547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); 23557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); 23567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CloseHandle(pi.hProcess); 23577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ResumeThread(pi.hThread); 23587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou CloseHandle(pi.hThread); 23597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 2360bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2361bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2362bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid DeleteRegistryKey(char *string) 2363bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 23647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *keyname; 23657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *subkeyname; 23667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *delim; 23677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY hKey; 23687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou long result; 23697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *line; 23707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou line = strdup(string); /* so we can change it */ 23727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou keyname = strchr(line, '['); 23747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!keyname) 23757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return; 23767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++keyname; 23777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou subkeyname = strchr(keyname, ']'); 23797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!subkeyname) 23807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return; 23817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *subkeyname++='\0'; 23827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou delim = strchr(subkeyname, '\n'); 23837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (delim) 23847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *delim = '\0'; 23857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegOpenKeyEx(hkey_root, 23877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou keyname, 23887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 23897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KEY_WRITE, 23907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &hKey); 23917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 23927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result != ERROR_SUCCESS) 23937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), string, "Could not open key", MB_OK); 23947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else { 23957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegDeleteKey(hKey, subkeyname); 23967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) 23977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), string, "Could not delete key", MB_OK); 23987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RegCloseKey(hKey); 23997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 24007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(line); 2401bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2402bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2403bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellervoid DeleteRegistryValue(char *string) 2404bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 24057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *keyname; 24067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *valuename; 24077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *value; 24087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou HKEY hKey; 24097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou long result; 24107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *line; 2411bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 24127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou line = strdup(string); /* so we can change it */ 2413bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2414bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Format is 'Reg DB Value: [key]name=value' */ 24157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou keyname = strchr(line, '['); 24167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!keyname) 24177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return; 24187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++keyname; 24197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou valuename = strchr(keyname, ']'); 24207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!valuename) 24217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return; 24227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *valuename++ = '\0'; 24237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou value = strchr(valuename, '='); 24247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!value) 24257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return; 24267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 24277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *value++ = '\0'; 24287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 24297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegOpenKeyEx(hkey_root, 24307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou keyname, 24317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 0, 24327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou KEY_WRITE, 24337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &hKey); 24347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result != ERROR_SUCCESS) 24357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), string, "Could not open key", MB_OK); 24367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else { 24377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou result = RegDeleteValue(hKey, valuename); 24387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) 24397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), string, "Could not delete value", MB_OK); 24407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou RegCloseKey(hKey); 24417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 24427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(line); 2443bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2444bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2445bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL MyDeleteFile(char *line) 2446bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 24477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *pathname = strchr(line, ':'); 24487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!pathname) 24497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 24507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++pathname; 24517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (isspace(*pathname)) 24527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++pathname; 24537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return DeleteFile(pathname); 2454bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2455bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2456bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL MyRemoveDirectory(char *line) 2457bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 24587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *pathname = strchr(line, ':'); 24597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!pathname) 24607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 24617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++pathname; 24627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (isspace(*pathname)) 24637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++pathname; 24647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return RemoveDirectory(pathname); 2465bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2466bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2467bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas HellerBOOL Run_RemoveScript(char *line) 2468bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 24697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *dllname; 24707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *scriptname; 24717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou static char lastscript[MAX_PATH]; 2472bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2473bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* Format is 'Run Scripts: [pythondll]scriptname' */ 2474bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller/* XXX Currently, pythondll carries no path!!! */ 24757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou dllname = strchr(line, '['); 24767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!dllname) 24777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 24787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++dllname; 24797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou scriptname = strchr(dllname, ']'); 24807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!scriptname) 24817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return FALSE; 24827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou *scriptname++ = '\0'; 24837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* this function may be called more than one time with the same 24847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou script, only run it one time */ 24857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (strcmp(lastscript, scriptname)) { 24867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *argv[3] = {NULL, "-remove", NULL}; 24877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *buffer = NULL; 24887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 24897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou argv[0] = scriptname; 24907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 24917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (0 != run_installscript(scriptname, 2, argv, &buffer)) 24927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fprintf(stderr, "*** Could not run installation script ***"); 24937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 24947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (buffer && buffer[0]) 24957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), buffer, "uninstall-script", MB_OK); 24967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou free(buffer); 24977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 24987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou strcpy(lastscript, scriptname); 24997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 25007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return TRUE; 2501bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2502bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2503bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint DoUninstall(int argc, char **argv) 2504bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 25057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou FILE *logfile; 25067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char buffer[4096]; 25077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int nLines = 0; 25087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int i; 25097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *cp; 25107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int nFiles = 0; 25117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int nDirs = 0; 25127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int nErrors = 0; 25137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char **lines; 25147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int lines_buffer_size = 10; 25157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 25167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (argc != 3) { 25177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(NULL, 25187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Wrong number of args", 25197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 25207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_OK); 25217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; /* Error */ 25227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 25237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (strcmp(argv[1], "-u")) { 25247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(NULL, 25257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "2. arg is not -u", 25267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 25277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_OK); 25287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; /* Error */ 25297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 25307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 25317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou logfile = fopen(argv[2], "r"); 25327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!logfile) { 25337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(NULL, 25347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "could not open logfile", 25357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 25367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_OK); 25377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; /* Error */ 25387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 25397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 25407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou lines = (char **)malloc(sizeof(char *) * lines_buffer_size); 25417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!lines) 25427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return SystemError(0, "Out of memory"); 25437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 25447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Read the whole logfile, realloacting the buffer */ 25457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (fgets(buffer, sizeof(buffer), logfile)) { 25467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int len = strlen(buffer); 25477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* remove trailing white space */ 25487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou while (isspace(buffer[len-1])) 25497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou len -= 1; 25507f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou buffer[len] = '\0'; 25517f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou lines[nLines++] = strdup(buffer); 25527f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (nLines >= lines_buffer_size) { 25537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou lines_buffer_size += 10; 25547f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou lines = (char **)realloc(lines, 25557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou sizeof(char *) * lines_buffer_size); 25567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!lines) 25577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return SystemError(0, "Out of memory"); 25587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 25597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 25607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou fclose(logfile); 25617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 25627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Sort all the lines, so that highest 3-digit codes are first */ 25637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou qsort(&lines[0], nLines, sizeof(char *), 25647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou compare); 25657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 25667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (IDYES != MessageBox(NULL, 25677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Are you sure you want to remove\n" 25687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "this package from your computer?", 25697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "Please confirm", 25707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_YESNO | MB_ICONQUESTION)) 25717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 25727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 25737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hkey_root = HKEY_LOCAL_MACHINE; 25747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou cp = ""; 25757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou for (i = 0; i < nLines; ++i) { 25767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Ignore duplicate lines */ 25777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (strcmp(cp, lines[i])) { 25787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int ign; 25797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou cp = lines[i]; 25807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Parse the lines */ 25817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (2 == sscanf(cp, "%d Root Key: %s", &ign, &buffer)) { 25827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (strcmp(buffer, "HKEY_CURRENT_USER")==0) 25837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou hkey_root = HKEY_CURRENT_USER; 25847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else { 25857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou // HKLM - check they have permissions. 25867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!HasLocalMachinePrivs()) { 25877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(GetFocus(), 25887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "You do not seem to have sufficient access rights\n" 25897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "on this machine to uninstall this software", 25907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou NULL, 25917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_OK | MB_ICONSTOP); 25927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; /* Error */ 25937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 25947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 25957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else if (2 == sscanf(cp, "%d Made Dir: %s", &ign, &buffer)) { 25967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (MyRemoveDirectory(cp)) 25977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++nDirs; 25987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else { 25997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int code = GetLastError(); 26007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (code != 2 && code != 3) { /* file or path not found */ 26017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++nErrors; 26027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26047f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else if (2 == sscanf(cp, "%d File Copy: %s", &ign, &buffer)) { 26057f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (MyDeleteFile(cp)) 26067f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++nFiles; 26077f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else { 26087f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int code = GetLastError(); 26097f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (code != 2 && code != 3) { /* file or path not found */ 26107f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++nErrors; 26117f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26127f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26137f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else if (2 == sscanf(cp, "%d File Overwrite: %s", &ign, &buffer)) { 26147f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (MyDeleteFile(cp)) 26157f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++nFiles; 26167f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else { 26177f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou int code = GetLastError(); 26187f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (code != 2 && code != 3) { /* file or path not found */ 26197f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++nErrors; 26207f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26217f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26227f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else if (2 == sscanf(cp, "%d Reg DB Key: %s", &ign, &buffer)) { 26237f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DeleteRegistryKey(cp); 26247f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else if (2 == sscanf(cp, "%d Reg DB Value: %s", &ign, &buffer)) { 26257f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou DeleteRegistryValue(cp); 26267f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else if (2 == sscanf(cp, "%d Run Script: %s", &ign, &buffer)) { 26277f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou Run_RemoveScript(cp); 26287f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26297f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26307f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26317f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26327f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (DeleteFile(argv[2])) { 26337f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++nFiles; 26347f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } else { 26357f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++nErrors; 26367f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SystemError(GetLastError(), argv[2]); 26377f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26387f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (nErrors) 26397f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(buffer, 26407f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "%d files and %d directories removed\n" 26417f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou "%d files or directories could not be removed", 26427f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou nFiles, nDirs, nErrors); 26437f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else 26447f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou wsprintf(buffer, "%d files and %d directories removed", 26457f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou nFiles, nDirs); 26467f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MessageBox(NULL, buffer, "Uninstall Finished!", 26477f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou MB_OK | MB_ICONINFORMATION); 26487f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou remove_exe(); 26497f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 0; 2650bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2651bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller 2652bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Hellerint WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, 26537f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou LPSTR lpszCmdLine, INT nCmdShow) 2654bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller{ 26557f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou extern int __argc; 26567f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou extern char **__argv; 26577f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou char *basename; 26587f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26597f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetModuleFileName(NULL, modulename, sizeof(modulename)); 26607f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou GetModuleFileNameW(NULL, wmodulename, sizeof(wmodulename)/sizeof(wmodulename[0])); 26617f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26627f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Map the executable file to memory */ 26637f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou arc_data = MapExistingFile(modulename, &arc_size); 26647f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!arc_data) { 26657f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SystemError(GetLastError(), "Could not open archive"); 26667f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; 26677f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26687f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26697f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* OK. So this program can act as installer (self-extracting 26707f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * zip-file, or as uninstaller when started with '-u logfile' 26717f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * command line flags. 26727f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * 26737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * The installer is usually started without command line flags, 26747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * and the uninstaller is usually started with the '-u logfile' 26757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * flag. What to do if some innocent user double-clicks the 26767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * exe-file? 26777f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou * The following implements a defensive strategy... 26787f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou */ 26797f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26807f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Try to extract the configuration data into a temporary file */ 26817f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (ExtractInstallData(arc_data, arc_size, &exe_size, 26827f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou &ini_file, &pre_install_script)) 26837f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return DoInstall(); 26847f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26857f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (!ini_file && __argc > 1) { 26867f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return DoUninstall(__argc, __argv); 26877f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou } 26887f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26897f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26907f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou basename = strrchr(modulename, '\\'); 26917f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (basename) 26927f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou ++basename; 26937f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou 26947f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou /* Last guess about the purpose of this program */ 26957f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou if (basename && (0 == strncmp(basename, "Remove", 6))) 26967f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SystemError(0, "This program is normally started by windows"); 26977f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou else 26987f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou SystemError(0, "Setup program invalid or damaged"); 26997f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou return 1; 2700bb4b7d2d68b82803640f6ffbb79a7f694dcbf21cThomas Heller} 2701