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(&ltime);
18007f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou    now = localtime(&ltime);
18017f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou    strftime(buffer, sizeof(buffer),
18027f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou             "*** Installation started %Y/%m/%d %H:%M ***\n",
18037f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou             localtime(&ltime));
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(&ltime);
18737f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou    now = localtime(&ltime);
18747f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou    strftime(buffer, sizeof(buffer),
18757f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou             "*** Installation finished %Y/%m/%d %H:%M ***\n",
18767f14f0d8a0228c50d5b5de2acbfe9a64ebc6749aAntoine Pitrou             localtime(&ltime));
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