Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/PC/bdist_wininst/install.c

    r2 r391  
    1111 * Written by Thomas Heller, May 2000
    1212 *
    13  * $Id: install.c 69095 2009-01-29 12:31:51Z mark.hammond $
     13 * $Id$
    1414 */
    1515
     
    2121 * At runtime, the exefile has appended:
    2222 * - compressed setup-data in ini-format, containing the following sections:
    23  *      [metadata]
    24  *      author=Greg Ward
    25  *      author_email=gward@python.net
    26  *      description=Python Distribution Utilities
    27  *      licence=Python
    28  *      name=Distutils
    29  *      url=http://www.python.org/sigs/distutils-sig/
    30  *      version=0.9pre
     23 *      [metadata]
     24 *      author=Greg Ward
     25 *      author_email=gward@python.net
     26 *      description=Python Distribution Utilities
     27 *      licence=Python
     28 *      name=Distutils
     29 *      url=http://www.python.org/sigs/distutils-sig/
     30 *      version=0.9pre
    3131 *
    32  *      [Setup]
    33  *      info= text to be displayed in the edit-box
    34  *      title= to be displayed by this program
    35  *      target_version = if present, python version required
    36  *      pyc_compile = if 0, do not compile py to pyc
    37  *      pyo_compile = if 0, do not compile py to pyo
     32 *      [Setup]
     33 *      info= text to be displayed in the edit-box
     34 *      title= to be displayed by this program
     35 *      target_version = if present, python version required
     36 *      pyc_compile = if 0, do not compile py to pyc
     37 *      pyo_compile = if 0, do not compile py to pyo
    3838 *
    3939 * - a struct meta_data_hdr, describing the above
     
    6363 *
    6464 * Finish the code so that we can use other python installations
    65  * additionaly to those found in the registry,
     65 * additionally to those found in the registry,
    6666 * and then #define USE_OTHER_PYTHON_VERSIONS
    6767 *
     
    119119HWND hDialog;
    120120
    121 char *ini_file;                 /* Full pathname of ini-file */
     121char *ini_file;                 /* Full pathname of ini-file */
    122122/* From ini-file */
    123 char info[4096];                /* [Setup] info= */
    124 char title[80];                 /* [Setup] title=, contains package name
    125                                    including version: "Distutils-1.0.1" */
    126 char target_version[10];        /* [Setup] target_version=, required python
    127                                    version or empty string */
    128 char build_info[80];            /* [Setup] build_info=, distutils version
    129                                    and build date */
    130 
    131 char meta_name[80];             /* package name without version like
    132                                    'Distutils' */
     123char info[4096];                /* [Setup] info= */
     124char title[80];                 /* [Setup] title=, contains package name
     125                                   including version: "Distutils-1.0.1" */
     126char target_version[10];        /* [Setup] target_version=, required python
     127                                   version or empty string */
     128char build_info[80];            /* [Setup] build_info=, distutils version
     129                                   and build date */
     130
     131char meta_name[80];             /* package name without version like
     132                                   'Distutils' */
    133133char install_script[MAX_PATH];
    134134char *pre_install_script; /* run before we install a single file */
     
    136136char user_access_control[10]; // one of 'auto', 'force', otherwise none.
    137137
    138 int py_major, py_minor;         /* Python version selected for installation */
    139 
    140 char *arc_data;                 /* memory mapped archive */
    141 DWORD arc_size;                 /* number of bytes in archive */
    142 int exe_size;                   /* number of bytes for exe-file portion */
     138int py_major, py_minor;         /* Python version selected for installation */
     139
     140char *arc_data;                 /* memory mapped archive */
     141DWORD arc_size;                 /* number of bytes in archive */
     142int exe_size;                   /* number of bytes for exe-file portion */
    143143char python_dir[MAX_PATH];
    144144char pythondll[MAX_PATH];
     
    148148HKEY hkey_root = (HKEY)-1;
    149149
    150 BOOL success;                   /* Installation successfull? */
     150BOOL success;                   /* Installation successful? */
    151151char *failure_reason = NULL;
    152152
     
    166166/* Note: purelib must be the FIRST entry! */
    167167SCHEME old_scheme[] = {
    168         { "PURELIB", "" },
    169         { "PLATLIB", "" },
    170         { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */
    171         { "SCRIPTS", "Scripts\\" },
    172         { "DATA", "" },
    173         { NULL, NULL },
     168    { "PURELIB", "" },
     169    { "PLATLIB", "" },
     170    { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */
     171    { "SCRIPTS", "Scripts\\" },
     172    { "DATA", "" },
     173    { NULL, NULL },
    174174};
    175175
    176176SCHEME new_scheme[] = {
    177         { "PURELIB", "Lib\\site-packages\\" },
    178         { "PLATLIB", "Lib\\site-packages\\" },
    179         { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */
    180         { "SCRIPTS", "Scripts\\" },
    181         { "DATA", "" },
    182         { NULL, NULL },
     177    { "PURELIB", "Lib\\site-packages\\" },
     178    { "PLATLIB", "Lib\\site-packages\\" },
     179    { "HEADERS", "" }, /* 'Include/dist_name' part already in archive */
     180    { "SCRIPTS", "Scripts\\" },
     181    { "DATA", "" },
     182    { NULL, NULL },
    183183};
    184184
    185185static void unescape(char *dst, char *src, unsigned size)
    186186{
    187         char *eon;
    188         char ch;
    189 
    190         while (src && *src && (size > 2)) {
    191                 if (*src == '\\') {
    192                         switch (*++src) {
    193                         case 'n':
    194                                 ++src;
    195                                 *dst++ = '\r';
    196                                 *dst++ = '\n';
    197                                 size -= 2;
    198                                 break;
    199                         case 'r':
    200                                 ++src;
    201                                 *dst++ = '\r';
    202                                 --size;
    203                                 break;
    204                         case '0': case '1': case '2': case '3':
    205                                 ch = (char)strtol(src, &eon, 8);
    206                                 if (ch == '\n') {
    207                                         *dst++ = '\r';
    208                                         --size;
    209                                 }
    210                                 *dst++ = ch;
    211                                 --size;
    212                                 src = eon;
    213                         }
    214                 } else {
    215                         *dst++ = *src++;
    216                         --size;
    217                 }
    218         }
    219         *dst = '\0';
     187    char *eon;
     188    char ch;
     189
     190    while (src && *src && (size > 2)) {
     191        if (*src == '\\') {
     192            switch (*++src) {
     193            case 'n':
     194                ++src;
     195                *dst++ = '\r';
     196                *dst++ = '\n';
     197                size -= 2;
     198                break;
     199            case 'r':
     200                ++src;
     201                *dst++ = '\r';
     202                --size;
     203                break;
     204            case '0': case '1': case '2': case '3':
     205                ch = (char)strtol(src, &eon, 8);
     206                if (ch == '\n') {
     207                    *dst++ = '\r';
     208                    --size;
     209                }
     210                *dst++ = ch;
     211                --size;
     212                src = eon;
     213            }
     214        } else {
     215            *dst++ = *src++;
     216            --size;
     217        }
     218    }
     219    *dst = '\0';
    220220}
    221221
    222222static struct tagFile {
    223         char *path;
    224         struct tagFile *next;
     223    char *path;
     224    struct tagFile *next;
    225225} *file_list = NULL;
    226226
     
    228228{
    229229    if (failure_reason)
    230         free(failure_reason);
     230    free(failure_reason);
    231231    failure_reason = strdup(reason);
    232232    success = FALSE;
     
    235235{
    236236    if (!failure_reason)
    237         return "Installation failed.";
     237    return "Installation failed.";
    238238    return failure_reason;
    239239}
     
    241241static void add_to_filelist(char *path)
    242242{
    243         struct tagFile *p;
    244         p = (struct tagFile *)malloc(sizeof(struct tagFile));
    245         p->path = strdup(path);
    246         p->next = file_list;
    247         file_list = p;
     243    struct tagFile *p;
     244    p = (struct tagFile *)malloc(sizeof(struct tagFile));
     245    p->path = strdup(path);
     246    p->next = file_list;
     247    file_list = p;
    248248}
    249249
    250250static int do_compile_files(int (__cdecl * PyRun_SimpleString)(char *),
    251                              int optimize)
    252 {
    253         struct tagFile *p;
    254         int total, n;
    255         char Buffer[MAX_PATH + 64];
    256         int errors = 0;
    257 
    258         total = 0;
    259         p = file_list;
    260         while (p) {
    261                 ++total;
    262                 p = p->next;
    263         }
    264         SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETRANGE, 0,
    265                             MAKELPARAM(0, total));
    266         SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, 0, 0);
    267 
    268         n = 0;
    269         p = file_list;
    270         while (p) {
    271                 ++n;
    272                 wsprintf(Buffer,
    273                           "import py_compile; py_compile.compile (r'%s')",
    274                           p->path);
    275                 if (PyRun_SimpleString(Buffer)) {
    276                         ++errors;
    277                 }
    278                 /* We send the notification even if the files could not
    279                 * be created so that the uninstaller will remove them
    280                 * in case they are created later.
    281                 */
    282                 wsprintf(Buffer, "%s%c", p->path, optimize ? 'o' : 'c');
    283                 notify(FILE_CREATED, Buffer);
    284 
    285                 SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, n, 0);
    286                 SetDlgItemText(hDialog, IDC_INFO, p->path);
    287                 p = p->next;
    288         }
    289         return errors;
     251                             int optimize)
     252{
     253    struct tagFile *p;
     254    int total, n;
     255    char Buffer[MAX_PATH + 64];
     256    int errors = 0;
     257
     258    total = 0;
     259    p = file_list;
     260    while (p) {
     261        ++total;
     262        p = p->next;
     263    }
     264    SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETRANGE, 0,
     265                        MAKELPARAM(0, total));
     266    SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, 0, 0);
     267
     268    n = 0;
     269    p = file_list;
     270    while (p) {
     271        ++n;
     272        wsprintf(Buffer,
     273                  "import py_compile; py_compile.compile (r'%s')",
     274                  p->path);
     275        if (PyRun_SimpleString(Buffer)) {
     276            ++errors;
     277        }
     278        /* We send the notification even if the files could not
     279        * be created so that the uninstaller will remove them
     280        * in case they are created later.
     281        */
     282        wsprintf(Buffer, "%s%c", p->path, optimize ? 'o' : 'c');
     283        notify(FILE_CREATED, Buffer);
     284
     285        SendDlgItemMessage(hDialog, IDC_PROGRESS, PBM_SETPOS, n, 0);
     286        SetDlgItemText(hDialog, IDC_INFO, p->path);
     287        p = p->next;
     288    }
     289    return errors;
    290290}
    291291
     
    307307static int compile_filelist(HINSTANCE hPython, BOOL optimize_flag)
    308308{
    309         DECLPROC(hPython, void, Py_Initialize, (void));
    310         DECLPROC(hPython, void, Py_SetProgramName, (char *));
    311         DECLPROC(hPython, void, Py_Finalize, (void));
    312         DECLPROC(hPython, int, PyRun_SimpleString, (char *));
    313         DECLPROC(hPython, PyObject *, PySys_GetObject, (char *));
    314         DECLVAR(hPython, int, Py_OptimizeFlag);
    315 
    316         int errors = 0;
    317         struct tagFile *p = file_list;
    318 
    319         if (!p)
    320                 return 0;
    321 
    322         if (!Py_Initialize || !Py_SetProgramName || !Py_Finalize)
    323                 return -1;
    324 
    325         if (!PyRun_SimpleString || !PySys_GetObject || !Py_OptimizeFlag)
    326                 return -1;
    327 
    328         *Py_OptimizeFlag = optimize_flag ? 1 : 0;
    329         Py_SetProgramName(modulename);
    330         Py_Initialize();
    331 
    332         errors += do_compile_files(PyRun_SimpleString, optimize_flag);
    333         Py_Finalize();
    334 
    335         return errors;
     309    DECLPROC(hPython, void, Py_Initialize, (void));
     310    DECLPROC(hPython, void, Py_SetProgramName, (char *));
     311    DECLPROC(hPython, void, Py_Finalize, (void));
     312    DECLPROC(hPython, int, PyRun_SimpleString, (char *));
     313    DECLPROC(hPython, PyObject *, PySys_GetObject, (char *));
     314    DECLVAR(hPython, int, Py_OptimizeFlag);
     315
     316    int errors = 0;
     317    struct tagFile *p = file_list;
     318
     319    if (!p)
     320        return 0;
     321
     322    if (!Py_Initialize || !Py_SetProgramName || !Py_Finalize)
     323        return -1;
     324
     325    if (!PyRun_SimpleString || !PySys_GetObject || !Py_OptimizeFlag)
     326        return -1;
     327
     328    *Py_OptimizeFlag = optimize_flag ? 1 : 0;
     329    Py_SetProgramName(modulename);
     330    Py_Initialize();
     331
     332    errors += do_compile_files(PyRun_SimpleString, optimize_flag);
     333    Py_Finalize();
     334
     335    return errors;
    336336}
    337337
     
    339339
    340340struct PyMethodDef {
    341         char    *ml_name;
    342         PyCFunction  ml_meth;
    343         int              ml_flags;
    344         char    *ml_doc;
     341    char        *ml_name;
     342    PyCFunction  ml_meth;
     343    int                  ml_flags;
     344    char        *ml_doc;
    345345};
    346346typedef struct PyMethodDef PyMethodDef;
    347347
    348348// XXX - all of these are potentially fragile!  We load and unload
    349 // the Python DLL multiple times - so storing functions pointers 
     349// the Python DLL multiple times - so storing functions pointers
    350350// is dangerous (although things *look* OK at present)
    351351// Better might be to roll prepare_script_environment() into
     
    364364
    365365struct {
    366         int nFolder;
    367         char *name;
     366    int nFolder;
     367    char *name;
    368368} csidl_names[] = {
    369         /* Startup menu for all users.
    370            NT only */
    371         DEF_CSIDL(CSIDL_COMMON_STARTMENU),
    372         /* Startup menu. */
    373         DEF_CSIDL(CSIDL_STARTMENU),
     369    /* Startup menu for all users.
     370       NT only */
     371    DEF_CSIDL(CSIDL_COMMON_STARTMENU),
     372    /* Startup menu. */
     373    DEF_CSIDL(CSIDL_STARTMENU),
    374374
    375375/*    DEF_CSIDL(CSIDL_COMMON_APPDATA), */
    376376/*    DEF_CSIDL(CSIDL_LOCAL_APPDATA), */
    377         /* Repository for application-specific data.
    378            Needs Internet Explorer 4.0 */
    379         DEF_CSIDL(CSIDL_APPDATA),
    380 
    381         /* The desktop for all users.
    382            NT only */
    383         DEF_CSIDL(CSIDL_COMMON_DESKTOPDIRECTORY),
    384         /* The desktop. */
    385         DEF_CSIDL(CSIDL_DESKTOPDIRECTORY),
    386 
    387         /* Startup folder for all users.
    388            NT only */
    389         DEF_CSIDL(CSIDL_COMMON_STARTUP),
    390         /* Startup folder. */
    391         DEF_CSIDL(CSIDL_STARTUP),
    392 
    393         /* Programs item in the start menu for all users.
    394            NT only */
    395         DEF_CSIDL(CSIDL_COMMON_PROGRAMS),
    396         /* Program item in the user's start menu. */
    397         DEF_CSIDL(CSIDL_PROGRAMS),
     377    /* Repository for application-specific data.
     378       Needs Internet Explorer 4.0 */
     379    DEF_CSIDL(CSIDL_APPDATA),
     380
     381    /* The desktop for all users.
     382       NT only */
     383    DEF_CSIDL(CSIDL_COMMON_DESKTOPDIRECTORY),
     384    /* The desktop. */
     385    DEF_CSIDL(CSIDL_DESKTOPDIRECTORY),
     386
     387    /* Startup folder for all users.
     388       NT only */
     389    DEF_CSIDL(CSIDL_COMMON_STARTUP),
     390    /* Startup folder. */
     391    DEF_CSIDL(CSIDL_STARTUP),
     392
     393    /* Programs item in the start menu for all users.
     394       NT only */
     395    DEF_CSIDL(CSIDL_COMMON_PROGRAMS),
     396    /* Program item in the user's start menu. */
     397    DEF_CSIDL(CSIDL_PROGRAMS),
    398398
    399399/*    DEF_CSIDL(CSIDL_PROGRAM_FILES_COMMON), */
    400400/*    DEF_CSIDL(CSIDL_PROGRAM_FILES), */
    401401
    402         /* Virtual folder containing fonts. */
    403         DEF_CSIDL(CSIDL_FONTS),
     402    /* Virtual folder containing fonts. */
     403    DEF_CSIDL(CSIDL_FONTS),
    404404};
    405405
     
    408408static PyObject *FileCreated(PyObject *self, PyObject *args)
    409409{
    410         char *path;
    411         if (!g_PyArg_ParseTuple(args, "s", &path))
    412                 return NULL;
    413         notify(FILE_CREATED, path);
    414         return g_Py_BuildValue("");
     410    char *path;
     411    if (!g_PyArg_ParseTuple(args, "s", &path))
     412        return NULL;
     413    notify(FILE_CREATED, path);
     414    return g_Py_BuildValue("");
    415415}
    416416
    417417static PyObject *DirectoryCreated(PyObject *self, PyObject *args)
    418418{
    419         char *path;
    420         if (!g_PyArg_ParseTuple(args, "s", &path))
    421                 return NULL;
    422         notify(DIR_CREATED, path);
    423         return g_Py_BuildValue("");
     419    char *path;
     420    if (!g_PyArg_ParseTuple(args, "s", &path))
     421        return NULL;
     422    notify(DIR_CREATED, path);
     423    return g_Py_BuildValue("");
    424424}
    425425
    426426static PyObject *GetSpecialFolderPath(PyObject *self, PyObject *args)
    427427{
    428         char *name;
    429         char lpszPath[MAX_PATH];
    430         int i;
    431         static HRESULT (WINAPI *My_SHGetSpecialFolderPath)(HWND hwnd,
    432                                                            LPTSTR lpszPath,
    433                                                            int nFolder,
    434                                                            BOOL fCreate);
    435 
    436         if (!My_SHGetSpecialFolderPath) {
    437                 HINSTANCE hLib = LoadLibrary("shell32.dll");
    438                 if (!hLib) {
    439                         g_PyErr_Format(g_PyExc_OSError,
    440                                        "function not available");
    441                         return NULL;
    442                 }
    443                 My_SHGetSpecialFolderPath = (BOOL (WINAPI *)(HWND, LPTSTR,
    444                                                              int, BOOL))
    445                         GetProcAddress(hLib,
    446                                        "SHGetSpecialFolderPathA");
    447         }
    448 
    449         if (!g_PyArg_ParseTuple(args, "s", &name))
    450                 return NULL;
    451    
    452         if (!My_SHGetSpecialFolderPath) {
    453                 g_PyErr_Format(g_PyExc_OSError, "function not available");
    454                 return NULL;
    455         }
    456 
    457         for (i = 0; i < DIM(csidl_names); ++i) {
    458                 if (0 == strcmpi(csidl_names[i].name, name)) {
    459                         int nFolder;
    460                         nFolder = csidl_names[i].nFolder;
    461                         if (My_SHGetSpecialFolderPath(NULL, lpszPath,
    462                                                       nFolder, 0))
    463                                 return g_Py_BuildValue("s", lpszPath);
    464                         else {
    465                                 g_PyErr_Format(g_PyExc_OSError,
    466                                                "no such folder (%s)", name);
    467                                 return NULL;
    468                         }
    469                
    470                 }
    471         };
    472         g_PyErr_Format(g_PyExc_ValueError, "unknown CSIDL (%s)", name);
    473         return NULL;
     428    char *name;
     429    char lpszPath[MAX_PATH];
     430    int i;
     431    static HRESULT (WINAPI *My_SHGetSpecialFolderPath)(HWND hwnd,
     432                                                       LPTSTR lpszPath,
     433                                                       int nFolder,
     434                                                       BOOL fCreate);
     435
     436    if (!My_SHGetSpecialFolderPath) {
     437        HINSTANCE hLib = LoadLibrary("shell32.dll");
     438        if (!hLib) {
     439            g_PyErr_Format(g_PyExc_OSError,
     440                           "function not available");
     441            return NULL;
     442        }
     443        My_SHGetSpecialFolderPath = (BOOL (WINAPI *)(HWND, LPTSTR,
     444                                                     int, BOOL))
     445            GetProcAddress(hLib,
     446                           "SHGetSpecialFolderPathA");
     447    }
     448
     449    if (!g_PyArg_ParseTuple(args, "s", &name))
     450        return NULL;
     451
     452    if (!My_SHGetSpecialFolderPath) {
     453        g_PyErr_Format(g_PyExc_OSError, "function not available");
     454        return NULL;
     455    }
     456
     457    for (i = 0; i < DIM(csidl_names); ++i) {
     458        if (0 == strcmpi(csidl_names[i].name, name)) {
     459            int nFolder;
     460            nFolder = csidl_names[i].nFolder;
     461            if (My_SHGetSpecialFolderPath(NULL, lpszPath,
     462                                          nFolder, 0))
     463                return g_Py_BuildValue("s", lpszPath);
     464            else {
     465                g_PyErr_Format(g_PyExc_OSError,
     466                               "no such folder (%s)", name);
     467                return NULL;
     468            }
     469
     470        }
     471    };
     472    g_PyErr_Format(g_PyExc_ValueError, "unknown CSIDL (%s)", name);
     473    return NULL;
    474474}
    475475
    476476static PyObject *CreateShortcut(PyObject *self, PyObject *args)
    477477{
    478         char *path; /* path and filename */
    479         char *description;
    480         char *filename;
    481 
    482         char *arguments = NULL;
    483         char *iconpath = NULL;
    484         int iconindex = 0;
    485         char *workdir = NULL;
    486 
    487         WCHAR wszFilename[MAX_PATH];
    488 
    489         IShellLink *ps1 = NULL;
    490         IPersistFile *pPf = NULL;
    491 
    492         HRESULT hr;
    493 
    494         hr = CoInitialize(NULL);
    495         if (FAILED(hr)) {
    496                 g_PyErr_Format(g_PyExc_OSError,
    497                                "CoInitialize failed, error 0x%x", hr);
    498                 goto error;
    499         }
    500 
    501         if (!g_PyArg_ParseTuple(args, "sss|sssi",
    502                                 &path, &description, &filename,
    503                                 &arguments, &workdir, &iconpath, &iconindex))
    504                 return NULL;
    505 
    506         hr = CoCreateInstance(&CLSID_ShellLink,
    507                               NULL,
    508                               CLSCTX_INPROC_SERVER,
    509                               &IID_IShellLink,
    510                               &ps1);
    511         if (FAILED(hr)) {
    512                 g_PyErr_Format(g_PyExc_OSError,
    513                                "CoCreateInstance failed, error 0x%x", hr);
    514                 goto error;
    515         }
    516 
    517         hr = ps1->lpVtbl->QueryInterface(ps1, &IID_IPersistFile,
    518                                         (void **)&pPf);
    519         if (FAILED(hr)) {
    520                 g_PyErr_Format(g_PyExc_OSError,
    521                                "QueryInterface(IPersistFile) error 0x%x", hr);
    522                 goto error;
    523         }
    524 
    525 
    526         hr = ps1->lpVtbl->SetPath(ps1, path);
    527         if (FAILED(hr)) {
    528                 g_PyErr_Format(g_PyExc_OSError,
    529                                "SetPath() failed, error 0x%x", hr);
    530                 goto error;
    531         }
    532 
    533         hr = ps1->lpVtbl->SetDescription(ps1, description);
    534         if (FAILED(hr)) {
    535                 g_PyErr_Format(g_PyExc_OSError,
    536                                "SetDescription() failed, error 0x%x", hr);
    537                 goto error;
    538         }
    539 
    540         if (arguments) {
    541                 hr = ps1->lpVtbl->SetArguments(ps1, arguments);
    542                 if (FAILED(hr)) {
    543                         g_PyErr_Format(g_PyExc_OSError,
    544                                        "SetArguments() error 0x%x", hr);
    545                         goto error;
    546                 }
    547         }
    548 
    549         if (iconpath) {
    550                 hr = ps1->lpVtbl->SetIconLocation(ps1, iconpath, iconindex);
    551                 if (FAILED(hr)) {
    552                         g_PyErr_Format(g_PyExc_OSError,
    553                                        "SetIconLocation() error 0x%x", hr);
    554                         goto error;
    555                 }
    556         }
    557 
    558         if (workdir) {
    559                 hr = ps1->lpVtbl->SetWorkingDirectory(ps1, workdir);
    560                 if (FAILED(hr)) {
    561                         g_PyErr_Format(g_PyExc_OSError,
    562                                        "SetWorkingDirectory() error 0x%x", hr);
    563                         goto error;
    564                 }
    565         }
    566 
    567         MultiByteToWideChar(CP_ACP, 0,
    568                             filename, -1,
    569                             wszFilename, MAX_PATH);
    570                        
    571         hr = pPf->lpVtbl->Save(pPf, wszFilename, TRUE);
    572         if (FAILED(hr)) {
    573                 g_PyErr_Format(g_PyExc_OSError,
    574                                "Failed to create shortcut '%s' - error 0x%x", filename, hr);
    575                 goto error;
    576         }
    577    
    578         pPf->lpVtbl->Release(pPf);
    579         ps1->lpVtbl->Release(ps1);
    580         CoUninitialize();
    581         return g_Py_BuildValue("");
    582    
     478    char *path; /* path and filename */
     479    char *description;
     480    char *filename;
     481
     482    char *arguments = NULL;
     483    char *iconpath = NULL;
     484    int iconindex = 0;
     485    char *workdir = NULL;
     486
     487    WCHAR wszFilename[MAX_PATH];
     488
     489    IShellLink *ps1 = NULL;
     490    IPersistFile *pPf = NULL;
     491
     492    HRESULT hr;
     493
     494    hr = CoInitialize(NULL);
     495    if (FAILED(hr)) {
     496        g_PyErr_Format(g_PyExc_OSError,
     497                       "CoInitialize failed, error 0x%x", hr);
     498        goto error;
     499    }
     500
     501    if (!g_PyArg_ParseTuple(args, "sss|sssi",
     502                            &path, &description, &filename,
     503                            &arguments, &workdir, &iconpath, &iconindex))
     504        return NULL;
     505
     506    hr = CoCreateInstance(&CLSID_ShellLink,
     507                          NULL,
     508                          CLSCTX_INPROC_SERVER,
     509                          &IID_IShellLink,
     510                          &ps1);
     511    if (FAILED(hr)) {
     512        g_PyErr_Format(g_PyExc_OSError,
     513                       "CoCreateInstance failed, error 0x%x", hr);
     514        goto error;
     515    }
     516
     517    hr = ps1->lpVtbl->QueryInterface(ps1, &IID_IPersistFile,
     518                                    (void **)&pPf);
     519    if (FAILED(hr)) {
     520        g_PyErr_Format(g_PyExc_OSError,
     521                       "QueryInterface(IPersistFile) error 0x%x", hr);
     522        goto error;
     523    }
     524
     525
     526    hr = ps1->lpVtbl->SetPath(ps1, path);
     527    if (FAILED(hr)) {
     528        g_PyErr_Format(g_PyExc_OSError,
     529                       "SetPath() failed, error 0x%x", hr);
     530        goto error;
     531    }
     532
     533    hr = ps1->lpVtbl->SetDescription(ps1, description);
     534    if (FAILED(hr)) {
     535        g_PyErr_Format(g_PyExc_OSError,
     536                       "SetDescription() failed, error 0x%x", hr);
     537        goto error;
     538    }
     539
     540    if (arguments) {
     541        hr = ps1->lpVtbl->SetArguments(ps1, arguments);
     542        if (FAILED(hr)) {
     543            g_PyErr_Format(g_PyExc_OSError,
     544                           "SetArguments() error 0x%x", hr);
     545            goto error;
     546        }
     547    }
     548
     549    if (iconpath) {
     550        hr = ps1->lpVtbl->SetIconLocation(ps1, iconpath, iconindex);
     551        if (FAILED(hr)) {
     552            g_PyErr_Format(g_PyExc_OSError,
     553                           "SetIconLocation() error 0x%x", hr);
     554            goto error;
     555        }
     556    }
     557
     558    if (workdir) {
     559        hr = ps1->lpVtbl->SetWorkingDirectory(ps1, workdir);
     560        if (FAILED(hr)) {
     561            g_PyErr_Format(g_PyExc_OSError,
     562                           "SetWorkingDirectory() error 0x%x", hr);
     563            goto error;
     564        }
     565    }
     566
     567    MultiByteToWideChar(CP_ACP, 0,
     568                        filename, -1,
     569                        wszFilename, MAX_PATH);
     570
     571    hr = pPf->lpVtbl->Save(pPf, wszFilename, TRUE);
     572    if (FAILED(hr)) {
     573        g_PyErr_Format(g_PyExc_OSError,
     574                       "Failed to create shortcut '%s' - error 0x%x", filename, hr);
     575        goto error;
     576    }
     577
     578    pPf->lpVtbl->Release(pPf);
     579    ps1->lpVtbl->Release(ps1);
     580    CoUninitialize();
     581    return g_Py_BuildValue("");
     582
    583583  error:
    584         if (pPf)
    585                 pPf->lpVtbl->Release(pPf);
    586 
    587         if (ps1)
    588                 ps1->lpVtbl->Release(ps1);
    589 
    590         CoUninitialize();
    591 
    592         return NULL;
     584    if (pPf)
     585        pPf->lpVtbl->Release(pPf);
     586
     587    if (ps1)
     588        ps1->lpVtbl->Release(ps1);
     589
     590    CoUninitialize();
     591
     592    return NULL;
    593593}
    594594
    595595static PyObject *PyMessageBox(PyObject *self, PyObject *args)
    596596{
    597         int rc;
    598         char *text, *caption;
    599         int flags;
    600         if (!g_PyArg_ParseTuple(args, "ssi", &text, &caption, &flags))
    601                 return NULL;
    602         rc = MessageBox(GetFocus(), text, caption, flags);
    603         return g_Py_BuildValue("i", rc);
     597    int rc;
     598    char *text, *caption;
     599    int flags;
     600    if (!g_PyArg_ParseTuple(args, "ssi", &text, &caption, &flags))
     601        return NULL;
     602    rc = MessageBox(GetFocus(), text, caption, flags);
     603    return g_Py_BuildValue("i", rc);
    604604}
    605605
    606606static PyObject *GetRootHKey(PyObject *self)
    607607{
    608         return g_PyLong_FromVoidPtr(hkey_root);
     608    return g_PyLong_FromVoidPtr(hkey_root);
    609609}
    610610
     
    614614
    615615PyMethodDef meth[] = {
    616         {"create_shortcut", CreateShortcut, METH_VARARGS, NULL},
    617         {"get_special_folder_path", GetSpecialFolderPath, METH_VARARGS, NULL},
    618         {"get_root_hkey", (PyCFunction)GetRootHKey, METH_NOARGS, NULL},
    619         {"file_created", FileCreated, METH_VARARGS, NULL},
    620         {"directory_created", DirectoryCreated, METH_VARARGS, NULL},
    621         {"message_box", PyMessageBox, METH_VARARGS, NULL},
     616    {"create_shortcut", CreateShortcut, METH_VARARGS, NULL},
     617    {"get_special_folder_path", GetSpecialFolderPath, METH_VARARGS, NULL},
     618    {"get_root_hkey", (PyCFunction)GetRootHKey, METH_NOARGS, NULL},
     619    {"file_created", FileCreated, METH_VARARGS, NULL},
     620    {"directory_created", DirectoryCreated, METH_VARARGS, NULL},
     621    {"message_box", PyMessageBox, METH_VARARGS, NULL},
    622622};
    623623
    624624static HINSTANCE LoadPythonDll(char *fname)
    625625{
    626         char fullpath[_MAX_PATH];
    627         LONG size = sizeof(fullpath);
    628         char subkey_name[80];
    629         char buffer[260 + 12];
    630         HINSTANCE h;
    631 
    632         /* make sure PYTHONHOME is set, to that sys.path is initialized correctly */
    633         wsprintf(buffer, "PYTHONHOME=%s", python_dir);
    634         _putenv(buffer);
    635         h = LoadLibrary(fname);
    636         if (h)
    637                 return h;
    638         wsprintf(subkey_name,
    639                 "SOFTWARE\\Python\\PythonCore\\%d.%d\\InstallPath",
    640                 py_major, py_minor);
    641         if (ERROR_SUCCESS != RegQueryValue(HKEY_CURRENT_USER, subkey_name,
    642                                            fullpath, &size) &&
    643             ERROR_SUCCESS != RegQueryValue(HKEY_LOCAL_MACHINE, subkey_name,
    644                                            fullpath, &size))
    645                 return NULL;
    646         strcat(fullpath, "\\");
    647         strcat(fullpath, fname);
    648         return LoadLibrary(fullpath);
     626    char fullpath[_MAX_PATH];
     627    LONG size = sizeof(fullpath);
     628    char subkey_name[80];
     629    char buffer[260 + 12];
     630    HINSTANCE h;
     631
     632    /* make sure PYTHONHOME is set, to that sys.path is initialized correctly */
     633    wsprintf(buffer, "PYTHONHOME=%s", python_dir);
     634    _putenv(buffer);
     635    h = LoadLibrary(fname);
     636    if (h)
     637        return h;
     638    wsprintf(subkey_name,
     639            "SOFTWARE\\Python\\PythonCore\\%d.%d\\InstallPath",
     640            py_major, py_minor);
     641    if (ERROR_SUCCESS != RegQueryValue(HKEY_CURRENT_USER, subkey_name,
     642                                       fullpath, &size) &&
     643        ERROR_SUCCESS != RegQueryValue(HKEY_LOCAL_MACHINE, subkey_name,
     644                                       fullpath, &size))
     645        return NULL;
     646    strcat(fullpath, "\\");
     647    strcat(fullpath, fname);
     648    return LoadLibrary(fullpath);
    649649}
    650650
    651651static int prepare_script_environment(HINSTANCE hPython)
    652652{
    653         PyObject *mod;
    654         DECLPROC(hPython, PyObject *, PyImport_ImportModule, (char *));
    655         DECLPROC(hPython, int, PyObject_SetAttrString, (PyObject *, char *, PyObject *));
    656         DECLPROC(hPython, PyObject *, PyObject_GetAttrString, (PyObject *, char *));
    657         DECLPROC(hPython, PyObject *, PyCFunction_New, (PyMethodDef *, PyObject *));
    658         DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...));
    659         DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...));
    660         DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *));
    661         DECLPROC(hPython, PyObject *, PyLong_FromVoidPtr, (void *));
    662         if (!PyImport_ImportModule || !PyObject_GetAttrString ||
    663             !PyObject_SetAttrString || !PyCFunction_New)
    664                 return 1;
    665         if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format)
    666                 return 1;
    667 
    668         mod = PyImport_ImportModule("__builtin__");
    669         if (mod) {
    670                 int i;
    671                 g_PyExc_ValueError = PyObject_GetAttrString(mod, "ValueError");
    672                 g_PyExc_OSError = PyObject_GetAttrString(mod, "OSError");
    673                 for (i = 0; i < DIM(meth); ++i) {
    674                         PyObject_SetAttrString(mod, meth[i].ml_name,
    675                                                PyCFunction_New(&meth[i], NULL));
    676                 }
    677         }
    678         g_Py_BuildValue = Py_BuildValue;
    679         g_PyArg_ParseTuple = PyArg_ParseTuple;
    680         g_PyErr_Format = PyErr_Format;
    681         g_PyLong_FromVoidPtr = PyLong_FromVoidPtr;
    682 
    683         return 0;
     653    PyObject *mod;
     654    DECLPROC(hPython, PyObject *, PyImport_ImportModule, (char *));
     655    DECLPROC(hPython, int, PyObject_SetAttrString, (PyObject *, char *, PyObject *));
     656    DECLPROC(hPython, PyObject *, PyObject_GetAttrString, (PyObject *, char *));
     657    DECLPROC(hPython, PyObject *, PyCFunction_New, (PyMethodDef *, PyObject *));
     658    DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...));
     659    DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...));
     660    DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *));
     661    DECLPROC(hPython, PyObject *, PyLong_FromVoidPtr, (void *));
     662    if (!PyImport_ImportModule || !PyObject_GetAttrString ||
     663        !PyObject_SetAttrString || !PyCFunction_New)
     664        return 1;
     665    if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format)
     666        return 1;
     667
     668    mod = PyImport_ImportModule("__builtin__");
     669    if (mod) {
     670        int i;
     671        g_PyExc_ValueError = PyObject_GetAttrString(mod, "ValueError");
     672        g_PyExc_OSError = PyObject_GetAttrString(mod, "OSError");
     673        for (i = 0; i < DIM(meth); ++i) {
     674            PyObject_SetAttrString(mod, meth[i].ml_name,
     675                                   PyCFunction_New(&meth[i], NULL));
     676        }
     677    }
     678    g_Py_BuildValue = Py_BuildValue;
     679    g_PyArg_ParseTuple = PyArg_ParseTuple;
     680    g_PyErr_Format = PyErr_Format;
     681    g_PyLong_FromVoidPtr = PyLong_FromVoidPtr;
     682
     683    return 0;
    684684}
    685685
     
    697697do_run_installscript(HINSTANCE hPython, char *pathname, int argc, char **argv)
    698698{
    699         int fh, result;
    700         DECLPROC(hPython, void, Py_Initialize, (void));
    701         DECLPROC(hPython, int, PySys_SetArgv, (int, char **));
    702         DECLPROC(hPython, int, PyRun_SimpleString, (char *));
    703         DECLPROC(hPython, void, Py_Finalize, (void));
    704         DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...));
    705         DECLPROC(hPython, PyObject *, PyCFunction_New,
    706                 (PyMethodDef *, PyObject *));
    707         DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...));
    708         DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *));
    709 
    710         if (!Py_Initialize || !PySys_SetArgv
    711             || !PyRun_SimpleString || !Py_Finalize)
    712                 return 1;
    713        
    714         if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format)
    715                 return 1;
    716 
    717         if (!PyCFunction_New || !PyArg_ParseTuple || !PyErr_Format)
    718                 return 1;
    719 
    720         if (pathname == NULL || pathname[0] == '\0')
    721                 return 2;
    722 
    723         fh = open(pathname, _O_RDONLY);
    724         if (-1 == fh) {
    725                 fprintf(stderr, "Could not open postinstall-script %s\n",
    726                         pathname);
    727                 return 3;
    728         }
    729 
    730         SetDlgItemText(hDialog, IDC_INFO, "Running Script...");
    731 
    732         Py_Initialize();
    733 
    734         prepare_script_environment(hPython);
    735         PySys_SetArgv(argc, argv);
    736         result = 3;
    737         {
    738                 struct _stat statbuf;
    739                 if(0 == _fstat(fh, &statbuf)) {
    740                         char *script = alloca(statbuf.st_size + 5);
    741                         int n = read(fh, script, statbuf.st_size);
    742                         if (n > 0) {
    743                                 script[n] = '\n';
    744                                 script[n+1] = 0;
    745                                 result = PyRun_SimpleString(script);
    746                         }
    747                 }
    748         }
    749         Py_Finalize();
    750 
    751         close(fh);
    752         return result;
     699    int fh, result;
     700    DECLPROC(hPython, void, Py_Initialize, (void));
     701    DECLPROC(hPython, int, PySys_SetArgv, (int, char **));
     702    DECLPROC(hPython, int, PyRun_SimpleString, (char *));
     703    DECLPROC(hPython, void, Py_Finalize, (void));
     704    DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...));
     705    DECLPROC(hPython, PyObject *, PyCFunction_New,
     706            (PyMethodDef *, PyObject *));
     707    DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...));
     708    DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *));
     709
     710    if (!Py_Initialize || !PySys_SetArgv
     711        || !PyRun_SimpleString || !Py_Finalize)
     712        return 1;
     713
     714    if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format)
     715        return 1;
     716
     717    if (!PyCFunction_New || !PyArg_ParseTuple || !PyErr_Format)
     718        return 1;
     719
     720    if (pathname == NULL || pathname[0] == '\0')
     721        return 2;
     722
     723    fh = open(pathname, _O_RDONLY);
     724    if (-1 == fh) {
     725        fprintf(stderr, "Could not open postinstall-script %s\n",
     726            pathname);
     727        return 3;
     728    }
     729
     730    SetDlgItemText(hDialog, IDC_INFO, "Running Script...");
     731
     732    Py_Initialize();
     733
     734    prepare_script_environment(hPython);
     735    PySys_SetArgv(argc, argv);
     736    result = 3;
     737    {
     738        struct _stat statbuf;
     739        if(0 == _fstat(fh, &statbuf)) {
     740            char *script = alloca(statbuf.st_size + 5);
     741            int n = read(fh, script, statbuf.st_size);
     742            if (n > 0) {
     743                script[n] = '\n';
     744                script[n+1] = 0;
     745                result = PyRun_SimpleString(script);
     746            }
     747        }
     748    }
     749    Py_Finalize();
     750
     751    close(fh);
     752    return result;
    753753}
    754754
     
    756756run_installscript(char *pathname, int argc, char **argv, char **pOutput)
    757757{
    758         HINSTANCE hPython;
    759         int result = 1;
    760         int out_buf_size;
    761         HANDLE redirected, old_stderr, old_stdout;
    762         char *tempname;
    763 
    764         *pOutput = NULL;
    765 
    766         tempname = tempnam(NULL, NULL);
    767         // We use a static CRT while the Python version we load uses
    768         // the CRT from one of various possibile DLLs.  As a result we
    769         // need to redirect the standard handles using the API rather
    770         // than the CRT.
    771         redirected = CreateFile(
    772                                         tempname,
    773                                         GENERIC_WRITE | GENERIC_READ,
    774                                         FILE_SHARE_READ,
    775                                         NULL,
    776                                         CREATE_ALWAYS,
    777                                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
    778                                         NULL);
    779         old_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
    780         old_stderr = GetStdHandle(STD_ERROR_HANDLE);
    781         SetStdHandle(STD_OUTPUT_HANDLE, redirected);
    782         SetStdHandle(STD_ERROR_HANDLE, redirected);
    783 
    784         hPython = LoadPythonDll(pythondll);
    785         if (hPython) {
    786                 result = do_run_installscript(hPython, pathname, argc, argv);
    787                 FreeLibrary(hPython);
    788         } else {
    789                 fprintf(stderr, "*** Could not load Python ***");
    790         }
    791         SetStdHandle(STD_OUTPUT_HANDLE, old_stdout);
    792         SetStdHandle(STD_ERROR_HANDLE, old_stderr);
    793         out_buf_size = min(GetFileSize(redirected, NULL), 4096);
    794         *pOutput = malloc(out_buf_size+1);
    795         if (*pOutput) {
    796                 DWORD nread = 0;
    797                 SetFilePointer(redirected, 0, 0, FILE_BEGIN);
    798                 ReadFile(redirected, *pOutput, out_buf_size, &nread, NULL);
    799                 (*pOutput)[nread] = '\0';
    800         }
    801         CloseHandle(redirected);
    802         DeleteFile(tempname);
    803         return result;
     758    HINSTANCE hPython;
     759    int result = 1;
     760    int out_buf_size;
     761    HANDLE redirected, old_stderr, old_stdout;
     762    char *tempname;
     763
     764    *pOutput = NULL;
     765
     766    tempname = tempnam(NULL, NULL);
     767    // We use a static CRT while the Python version we load uses
     768    // the CRT from one of various possible DLLs.  As a result we
     769    // need to redirect the standard handles using the API rather
     770    // than the CRT.
     771    redirected = CreateFile(
     772                                    tempname,
     773                                    GENERIC_WRITE | GENERIC_READ,
     774                                    FILE_SHARE_READ,
     775                                    NULL,
     776                                    CREATE_ALWAYS,
     777                                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
     778                                    NULL);
     779    old_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
     780    old_stderr = GetStdHandle(STD_ERROR_HANDLE);
     781    SetStdHandle(STD_OUTPUT_HANDLE, redirected);
     782    SetStdHandle(STD_ERROR_HANDLE, redirected);
     783
     784    hPython = LoadPythonDll(pythondll);
     785    if (hPython) {
     786        result = do_run_installscript(hPython, pathname, argc, argv);
     787        FreeLibrary(hPython);
     788    } else {
     789        fprintf(stderr, "*** Could not load Python ***");
     790    }
     791    SetStdHandle(STD_OUTPUT_HANDLE, old_stdout);
     792    SetStdHandle(STD_ERROR_HANDLE, old_stderr);
     793    out_buf_size = min(GetFileSize(redirected, NULL), 4096);
     794    *pOutput = malloc(out_buf_size+1);
     795    if (*pOutput) {
     796        DWORD nread = 0;
     797        SetFilePointer(redirected, 0, 0, FILE_BEGIN);
     798        ReadFile(redirected, *pOutput, out_buf_size, &nread, NULL);
     799        (*pOutput)[nread] = '\0';
     800    }
     801    CloseHandle(redirected);
     802    DeleteFile(tempname);
     803    return result;
    804804}
    805805
    806806static int do_run_simple_script(HINSTANCE hPython, char *script)
    807807{
    808         int rc;
    809         DECLPROC(hPython, void, Py_Initialize, (void));
    810         DECLPROC(hPython, void, Py_SetProgramName, (char *));
    811         DECLPROC(hPython, void, Py_Finalize, (void));
    812         DECLPROC(hPython, int, PyRun_SimpleString, (char *));
    813         DECLPROC(hPython, void, PyErr_Print, (void));
    814 
    815         if (!Py_Initialize || !Py_SetProgramName || !Py_Finalize ||
    816             !PyRun_SimpleString || !PyErr_Print)
    817                 return -1;
    818 
    819         Py_SetProgramName(modulename);
    820         Py_Initialize();
    821         prepare_script_environment(hPython);
    822         rc = PyRun_SimpleString(script);
    823         if (rc)
    824                 PyErr_Print();
    825         Py_Finalize();
    826         return rc;
     808    int rc;
     809    DECLPROC(hPython, void, Py_Initialize, (void));
     810    DECLPROC(hPython, void, Py_SetProgramName, (char *));
     811    DECLPROC(hPython, void, Py_Finalize, (void));
     812    DECLPROC(hPython, int, PyRun_SimpleString, (char *));
     813    DECLPROC(hPython, void, PyErr_Print, (void));
     814
     815    if (!Py_Initialize || !Py_SetProgramName || !Py_Finalize ||
     816        !PyRun_SimpleString || !PyErr_Print)
     817        return -1;
     818
     819    Py_SetProgramName(modulename);
     820    Py_Initialize();
     821    prepare_script_environment(hPython);
     822    rc = PyRun_SimpleString(script);
     823    if (rc)
     824        PyErr_Print();
     825    Py_Finalize();
     826    return rc;
    827827}
    828828
    829829static int run_simple_script(char *script)
    830830{
    831         int rc;
    832         HINSTANCE hPython;
    833         char *tempname = tempnam(NULL, NULL);
    834         // Redirect output using win32 API - see comments above...
    835         HANDLE redirected = CreateFile(
    836                                         tempname,
    837                                         GENERIC_WRITE | GENERIC_READ,
    838                                         FILE_SHARE_READ,
    839                                         NULL,
    840                                         CREATE_ALWAYS,
    841                                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
    842                                         NULL);
    843         HANDLE old_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
    844         HANDLE old_stderr = GetStdHandle(STD_ERROR_HANDLE);
    845         SetStdHandle(STD_OUTPUT_HANDLE, redirected);
    846         SetStdHandle(STD_ERROR_HANDLE, redirected);
    847 
    848         hPython = LoadPythonDll(pythondll);
    849         if (!hPython) {
    850                 char reason[128];
    851                 wsprintf(reason, "Can't load Python for pre-install script (%d)", GetLastError());
    852                 set_failure_reason(reason);
    853                 return -1;
    854         }
    855         rc = do_run_simple_script(hPython, script);
    856         FreeLibrary(hPython);
    857         SetStdHandle(STD_OUTPUT_HANDLE, old_stdout);
    858         SetStdHandle(STD_ERROR_HANDLE, old_stderr);
    859         /* We only care about the output when we fail.  If the script works
    860            OK, then we discard it
    861         */
    862         if (rc) {
    863                 int err_buf_size;
    864                 char *err_buf;
    865                 const char *prefix = "Running the pre-installation script failed\r\n";
    866                 int prefix_len = strlen(prefix);
    867                 err_buf_size = GetFileSize(redirected, NULL);
    868                 if (err_buf_size==INVALID_FILE_SIZE) // an error - let's try anyway...
    869                         err_buf_size = 4096;
    870                 err_buf = malloc(prefix_len + err_buf_size + 1);
    871                 if (err_buf) {
    872                         DWORD n = 0;
    873                         strcpy(err_buf, prefix);
    874                         SetFilePointer(redirected, 0, 0, FILE_BEGIN);
    875                         ReadFile(redirected, err_buf+prefix_len, err_buf_size, &n, NULL);
    876                         err_buf[prefix_len+n] = '\0';
    877                         set_failure_reason(err_buf);
    878                         free(err_buf);
    879                 } else {
    880                         set_failure_reason("Out of memory!");
    881                 }
    882         }
    883         CloseHandle(redirected);
    884         DeleteFile(tempname);
    885         return rc;
     831    int rc;
     832    HINSTANCE hPython;
     833    char *tempname = tempnam(NULL, NULL);
     834    // Redirect output using win32 API - see comments above...
     835    HANDLE redirected = CreateFile(
     836                                    tempname,
     837                                    GENERIC_WRITE | GENERIC_READ,
     838                                    FILE_SHARE_READ,
     839                                    NULL,
     840                                    CREATE_ALWAYS,
     841                                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
     842                                    NULL);
     843    HANDLE old_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
     844    HANDLE old_stderr = GetStdHandle(STD_ERROR_HANDLE);
     845    SetStdHandle(STD_OUTPUT_HANDLE, redirected);
     846    SetStdHandle(STD_ERROR_HANDLE, redirected);
     847
     848    hPython = LoadPythonDll(pythondll);
     849    if (!hPython) {
     850        char reason[128];
     851        wsprintf(reason, "Can't load Python for pre-install script (%d)", GetLastError());
     852        set_failure_reason(reason);
     853        return -1;
     854    }
     855    rc = do_run_simple_script(hPython, script);
     856    FreeLibrary(hPython);
     857    SetStdHandle(STD_OUTPUT_HANDLE, old_stdout);
     858    SetStdHandle(STD_ERROR_HANDLE, old_stderr);
     859    /* We only care about the output when we fail.  If the script works
     860       OK, then we discard it
     861    */
     862    if (rc) {
     863        int err_buf_size;
     864        char *err_buf;
     865        const char *prefix = "Running the pre-installation script failed\r\n";
     866        int prefix_len = strlen(prefix);
     867        err_buf_size = GetFileSize(redirected, NULL);
     868        if (err_buf_size==INVALID_FILE_SIZE) // an error - let's try anyway...
     869            err_buf_size = 4096;
     870        err_buf = malloc(prefix_len + err_buf_size + 1);
     871        if (err_buf) {
     872            DWORD n = 0;
     873            strcpy(err_buf, prefix);
     874            SetFilePointer(redirected, 0, 0, FILE_BEGIN);
     875            ReadFile(redirected, err_buf+prefix_len, err_buf_size, &n, NULL);
     876            err_buf[prefix_len+n] = '\0';
     877            set_failure_reason(err_buf);
     878            free(err_buf);
     879        } else {
     880            set_failure_reason("Out of memory!");
     881        }
     882    }
     883    CloseHandle(redirected);
     884    DeleteFile(tempname);
     885    return rc;
    886886}
    887887
     
    889889static BOOL SystemError(int error, char *msg)
    890890{
    891         char Buffer[1024];
    892         int n;
    893 
    894         if (error) {
    895                 LPVOID lpMsgBuf;
    896                 FormatMessage(
    897                         FORMAT_MESSAGE_ALLOCATE_BUFFER |
    898                         FORMAT_MESSAGE_FROM_SYSTEM,
    899                         NULL,
    900                         error,
    901                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    902                         (LPSTR)&lpMsgBuf,
    903                         0,
    904                         NULL
    905                         );
    906                 strncpy(Buffer, lpMsgBuf, sizeof(Buffer));
    907                 LocalFree(lpMsgBuf);
    908         } else
    909                 Buffer[0] = '\0';
    910         n = lstrlen(Buffer);
    911         _snprintf(Buffer+n, sizeof(Buffer)-n, msg);
    912         MessageBox(hwndMain, Buffer, "Runtime Error", MB_OK | MB_ICONSTOP);
    913         return FALSE;
     891    char Buffer[1024];
     892    int n;
     893
     894    if (error) {
     895        LPVOID lpMsgBuf;
     896        FormatMessage(
     897            FORMAT_MESSAGE_ALLOCATE_BUFFER |
     898            FORMAT_MESSAGE_FROM_SYSTEM,
     899            NULL,
     900            error,
     901            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     902            (LPSTR)&lpMsgBuf,
     903            0,
     904            NULL
     905            );
     906        strncpy(Buffer, lpMsgBuf, sizeof(Buffer));
     907        LocalFree(lpMsgBuf);
     908    } else
     909        Buffer[0] = '\0';
     910    n = lstrlen(Buffer);
     911    _snprintf(Buffer+n, sizeof(Buffer)-n, msg);
     912    MessageBox(hwndMain, Buffer, "Runtime Error", MB_OK | MB_ICONSTOP);
     913    return FALSE;
    914914}
    915915
    916916static BOOL notify (int code, char *fmt, ...)
    917917{
    918         char Buffer[1024];
    919         va_list marker;
    920         BOOL result = TRUE;
    921         int a, b;
    922         char *cp;
    923 
    924         va_start(marker, fmt);
    925         _vsnprintf(Buffer, sizeof(Buffer), fmt, marker);
    926 
    927         switch (code) {
     918    char Buffer[1024];
     919    va_list marker;
     920    BOOL result = TRUE;
     921    int a, b;
     922    char *cp;
     923
     924    va_start(marker, fmt);
     925    _vsnprintf(Buffer, sizeof(Buffer), fmt, marker);
     926
     927    switch (code) {
    928928/* Questions */
    929         case CAN_OVERWRITE:
    930                 break;
     929    case CAN_OVERWRITE:
     930        break;
    931931
    932932/* Information notification */
    933         case DIR_CREATED:
    934                 if (logfile)
    935                         fprintf(logfile, "100 Made Dir: %s\n", fmt);
    936                 break;
    937 
    938         case FILE_CREATED:
    939                 if (logfile)
    940                         fprintf(logfile, "200 File Copy: %s\n", fmt);
    941                 goto add_to_filelist_label;
    942                 break;
    943 
    944         case FILE_OVERWRITTEN:
    945                 if (logfile)
    946                         fprintf(logfile, "200 File Overwrite: %s\n", fmt);
    947           add_to_filelist_label:
    948                 if ((cp = strrchr(fmt, '.')) && (0 == strcmp (cp, ".py")))
    949                         add_to_filelist(fmt);
    950                 break;
     933    case DIR_CREATED:
     934        if (logfile)
     935            fprintf(logfile, "100 Made Dir: %s\n", fmt);
     936        break;
     937
     938    case FILE_CREATED:
     939        if (logfile)
     940            fprintf(logfile, "200 File Copy: %s\n", fmt);
     941        goto add_to_filelist_label;
     942        break;
     943
     944    case FILE_OVERWRITTEN:
     945        if (logfile)
     946            fprintf(logfile, "200 File Overwrite: %s\n", fmt);
     947      add_to_filelist_label:
     948        if ((cp = strrchr(fmt, '.')) && (0 == strcmp (cp, ".py")))
     949            add_to_filelist(fmt);
     950        break;
    951951
    952952/* Error Messages */
    953         case ZLIB_ERROR:
    954                 MessageBox(GetFocus(), Buffer, "Error",
    955                             MB_OK | MB_ICONWARNING);
    956                 break;
    957 
    958         case SYSTEM_ERROR:
    959                 SystemError(GetLastError(), Buffer);
    960                 break;
    961 
    962         case NUM_FILES:
    963                 a = va_arg(marker, int);
    964                 b = va_arg(marker, int);
    965                 SendMessage(hDialog, WM_NUMFILES, 0, MAKELPARAM(0, a));
    966                 SendMessage(hDialog, WM_NEXTFILE, b,(LPARAM)fmt);
    967         }
    968         va_end(marker);
    969    
    970         return result;
     953    case ZLIB_ERROR:
     954        MessageBox(GetFocus(), Buffer, "Error",
     955                    MB_OK | MB_ICONWARNING);
     956        break;
     957
     958    case SYSTEM_ERROR:
     959        SystemError(GetLastError(), Buffer);
     960        break;
     961
     962    case NUM_FILES:
     963        a = va_arg(marker, int);
     964        b = va_arg(marker, int);
     965        SendMessage(hDialog, WM_NUMFILES, 0, MAKELPARAM(0, a));
     966        SendMessage(hDialog, WM_NEXTFILE, b,(LPARAM)fmt);
     967    }
     968    va_end(marker);
     969
     970    return result;
    971971}
    972972
    973973static char *MapExistingFile(char *pathname, DWORD *psize)
    974974{
    975         HANDLE hFile, hFileMapping;
    976         DWORD nSizeLow, nSizeHigh;
    977         char *data;
    978 
    979         hFile = CreateFile(pathname,
    980                             GENERIC_READ, FILE_SHARE_READ, NULL,
    981                             OPEN_EXISTING,
    982                             FILE_ATTRIBUTE_NORMAL, NULL);
    983         if (hFile == INVALID_HANDLE_VALUE)
    984                 return NULL;
    985         nSizeLow = GetFileSize(hFile, &nSizeHigh);
    986         hFileMapping = CreateFileMapping(hFile,
    987                                           NULL, PAGE_READONLY, 0, 0, NULL);
    988         CloseHandle(hFile);
    989 
    990         if (hFileMapping == INVALID_HANDLE_VALUE)
    991                 return NULL;
    992    
    993         data = MapViewOfFile(hFileMapping,
    994                               FILE_MAP_READ, 0, 0, 0);
    995 
    996         CloseHandle(hFileMapping);
    997         *psize = nSizeLow;
    998         return data;
     975    HANDLE hFile, hFileMapping;
     976    DWORD nSizeLow, nSizeHigh;
     977    char *data;
     978
     979    hFile = CreateFile(pathname,
     980                        GENERIC_READ, FILE_SHARE_READ, NULL,
     981                        OPEN_EXISTING,
     982                        FILE_ATTRIBUTE_NORMAL, NULL);
     983    if (hFile == INVALID_HANDLE_VALUE)
     984        return NULL;
     985    nSizeLow = GetFileSize(hFile, &nSizeHigh);
     986    hFileMapping = CreateFileMapping(hFile,
     987                                      NULL, PAGE_READONLY, 0, 0, NULL);
     988    CloseHandle(hFile);
     989
     990    if (hFileMapping == INVALID_HANDLE_VALUE)
     991        return NULL;
     992
     993    data = MapViewOfFile(hFileMapping,
     994                          FILE_MAP_READ, 0, 0, 0);
     995
     996    CloseHandle(hFileMapping);
     997    *psize = nSizeLow;
     998    return data;
    999999}
    10001000
     
    10021002static void create_bitmap(HWND hwnd)
    10031003{
    1004         BITMAPFILEHEADER *bfh;
    1005         BITMAPINFO *bi;
    1006         HDC hdc;
    1007 
    1008         if (!bitmap_bytes)
    1009                 return;
    1010 
    1011         if (hBitmap)
    1012                 return;
    1013 
    1014         hdc = GetDC(hwnd);
    1015 
    1016         bfh = (BITMAPFILEHEADER *)bitmap_bytes;
    1017         bi = (BITMAPINFO *)(bitmap_bytes + sizeof(BITMAPFILEHEADER));
    1018 
    1019         hBitmap = CreateDIBitmap(hdc,
    1020                                 &bi->bmiHeader,
    1021                                 CBM_INIT,
    1022                                 bitmap_bytes + bfh->bfOffBits,
    1023                                 bi,
    1024                                 DIB_RGB_COLORS);
    1025         ReleaseDC(hwnd, hdc);
     1004    BITMAPFILEHEADER *bfh;
     1005    BITMAPINFO *bi;
     1006    HDC hdc;
     1007
     1008    if (!bitmap_bytes)
     1009        return;
     1010
     1011    if (hBitmap)
     1012        return;
     1013
     1014    hdc = GetDC(hwnd);
     1015
     1016    bfh = (BITMAPFILEHEADER *)bitmap_bytes;
     1017    bi = (BITMAPINFO *)(bitmap_bytes + sizeof(BITMAPFILEHEADER));
     1018
     1019    hBitmap = CreateDIBitmap(hdc,
     1020                            &bi->bmiHeader,
     1021                            CBM_INIT,
     1022                            bitmap_bytes + bfh->bfOffBits,
     1023                            bi,
     1024                            DIB_RGB_COLORS);
     1025    ReleaseDC(hwnd, hdc);
    10261026}
    10271027
     
    10301030*/
    10311031static BOOL ExtractInstallData(char *data, DWORD size, int *pexe_size,
    1032                                char **out_ini_file, char **out_preinstall_script)
    1033 {
    1034         /* read the end of central directory record */
    1035         struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof
    1036                                                        (struct eof_cdir)];
    1037    
    1038         int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir -
    1039                 pe->ofsCDir;
    1040 
    1041         int ofs = arc_start - sizeof (struct meta_data_hdr);
    1042 
    1043         /* read meta_data info */
    1044         struct meta_data_hdr *pmd = (struct meta_data_hdr *)&data[ofs];
    1045         char *src, *dst;
    1046         char *ini_file;
    1047         char tempdir[MAX_PATH];
    1048 
    1049         /* ensure that if we fail, we don't have garbage out pointers */
    1050         *out_ini_file = *out_preinstall_script = NULL;
    1051 
    1052         if (pe->tag != 0x06054b50) {
    1053                 return FALSE;
    1054         }
    1055 
    1056         if (pmd->tag != 0x1234567B) {
    1057                 return SystemError(0,
    1058                            "Invalid cfgdata magic number (see bdist_wininst.py)");
    1059         }
    1060         if (ofs < 0) {
    1061                 return FALSE;
    1062         }
    1063 
    1064         if (pmd->bitmap_size) {
    1065                 /* Store pointer to bitmap bytes */
    1066                 bitmap_bytes = (char *)pmd - pmd->uncomp_size - pmd->bitmap_size;
    1067         }
    1068 
    1069         *pexe_size = ofs - pmd->uncomp_size - pmd->bitmap_size;
    1070 
    1071         src = ((char *)pmd) - pmd->uncomp_size;
    1072         ini_file = malloc(MAX_PATH); /* will be returned, so do not free it */
    1073         if (!ini_file)
    1074                 return FALSE;
    1075         if (!GetTempPath(sizeof(tempdir), tempdir)
    1076             || !GetTempFileName(tempdir, "~du", 0, ini_file)) {
    1077                 SystemError(GetLastError(),
    1078                              "Could not create temporary file");
    1079                 return FALSE;
    1080         }
    1081    
    1082         dst = map_new_file(CREATE_ALWAYS, ini_file, NULL, pmd->uncomp_size,
    1083                             0, 0, NULL/*notify*/);
    1084         if (!dst)
    1085                 return FALSE;
    1086         /* Up to the first \0 is the INI file data. */
    1087         strncpy(dst, src, pmd->uncomp_size);
    1088         src += strlen(dst) + 1;
    1089         /* Up to next \0 is the pre-install script */
    1090         *out_preinstall_script = strdup(src);
    1091         *out_ini_file = ini_file;
    1092         UnmapViewOfFile(dst);
    1093         return TRUE;
     1032                               char **out_ini_file, char **out_preinstall_script)
     1033{
     1034    /* read the end of central directory record */
     1035    struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof
     1036                                                   (struct eof_cdir)];
     1037
     1038    int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir -
     1039        pe->ofsCDir;
     1040
     1041    int ofs = arc_start - sizeof (struct meta_data_hdr);
     1042
     1043    /* read meta_data info */
     1044    struct meta_data_hdr *pmd = (struct meta_data_hdr *)&data[ofs];
     1045    char *src, *dst;
     1046    char *ini_file;
     1047    char tempdir[MAX_PATH];
     1048
     1049    /* ensure that if we fail, we don't have garbage out pointers */
     1050    *out_ini_file = *out_preinstall_script = NULL;
     1051
     1052    if (pe->tag != 0x06054b50) {
     1053        return FALSE;
     1054    }
     1055
     1056    if (pmd->tag != 0x1234567B) {
     1057        return SystemError(0,
     1058                   "Invalid cfgdata magic number (see bdist_wininst.py)");
     1059    }
     1060    if (ofs < 0) {
     1061        return FALSE;
     1062    }
     1063
     1064    if (pmd->bitmap_size) {
     1065        /* Store pointer to bitmap bytes */
     1066        bitmap_bytes = (char *)pmd - pmd->uncomp_size - pmd->bitmap_size;
     1067    }
     1068
     1069    *pexe_size = ofs - pmd->uncomp_size - pmd->bitmap_size;
     1070
     1071    src = ((char *)pmd) - pmd->uncomp_size;
     1072    ini_file = malloc(MAX_PATH); /* will be returned, so do not free it */
     1073    if (!ini_file)
     1074        return FALSE;
     1075    if (!GetTempPath(sizeof(tempdir), tempdir)
     1076        || !GetTempFileName(tempdir, "~du", 0, ini_file)) {
     1077        SystemError(GetLastError(),
     1078                     "Could not create temporary file");
     1079        return FALSE;
     1080    }
     1081
     1082    dst = map_new_file(CREATE_ALWAYS, ini_file, NULL, pmd->uncomp_size,
     1083                        0, 0, NULL/*notify*/);
     1084    if (!dst)
     1085        return FALSE;
     1086    /* Up to the first \0 is the INI file data. */
     1087    strncpy(dst, src, pmd->uncomp_size);
     1088    src += strlen(dst) + 1;
     1089    /* Up to next \0 is the pre-install script */
     1090    *out_preinstall_script = strdup(src);
     1091    *out_ini_file = ini_file;
     1092    UnmapViewOfFile(dst);
     1093    return TRUE;
    10941094}
    10951095
    10961096static void PumpMessages(void)
    10971097{
    1098         MSG msg;
    1099         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
    1100                 TranslateMessage(&msg);
    1101                 DispatchMessage(&msg);
    1102         }
     1098    MSG msg;
     1099    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
     1100        TranslateMessage(&msg);
     1101        DispatchMessage(&msg);
     1102    }
    11031103}
    11041104
     
    11061106WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    11071107{
    1108         HDC hdc;
    1109         HFONT hFont;
    1110         int h;
    1111         PAINTSTRUCT ps;
    1112         switch (msg) {
    1113         case WM_PAINT:
    1114                 hdc = BeginPaint(hwnd, &ps);
    1115                 h = GetSystemMetrics(SM_CYSCREEN) / 10;
    1116                 hFont = CreateFont(h, 0, 0, 0, 700, TRUE,
    1117                                     0, 0, 0, 0, 0, 0, 0, "Times Roman");
    1118                 hFont = SelectObject(hdc, hFont);
    1119                 SetBkMode(hdc, TRANSPARENT);
    1120                 TextOut(hdc, 15, 15, title, strlen(title));
    1121                 SetTextColor(hdc, RGB(255, 255, 255));
    1122                 TextOut(hdc, 10, 10, title, strlen(title));
    1123                 DeleteObject(SelectObject(hdc, hFont));
    1124                 EndPaint(hwnd, &ps);
    1125                 return 0;
    1126         }
    1127         return DefWindowProc(hwnd, msg, wParam, lParam);
     1108    HDC hdc;
     1109    HFONT hFont;
     1110    int h;
     1111    PAINTSTRUCT ps;
     1112    switch (msg) {
     1113    case WM_PAINT:
     1114        hdc = BeginPaint(hwnd, &ps);
     1115        h = GetSystemMetrics(SM_CYSCREEN) / 10;
     1116        hFont = CreateFont(h, 0, 0, 0, 700, TRUE,
     1117                            0, 0, 0, 0, 0, 0, 0, "Times Roman");
     1118        hFont = SelectObject(hdc, hFont);
     1119        SetBkMode(hdc, TRANSPARENT);
     1120        TextOut(hdc, 15, 15, title, strlen(title));
     1121        SetTextColor(hdc, RGB(255, 255, 255));
     1122        TextOut(hdc, 10, 10, title, strlen(title));
     1123        DeleteObject(SelectObject(hdc, hFont));
     1124        EndPaint(hwnd, &ps);
     1125        return 0;
     1126    }
     1127    return DefWindowProc(hwnd, msg, wParam, lParam);
    11281128}
    11291129
    11301130static HWND CreateBackground(char *title)
    11311131{
    1132         WNDCLASS wc;
    1133         HWND hwnd;
    1134         char buffer[4096];
    1135 
    1136         wc.style = CS_VREDRAW | CS_HREDRAW;
    1137         wc.lpfnWndProc = WindowProc;
    1138         wc.cbWndExtra = 0;
    1139         wc.cbClsExtra = 0;
    1140         wc.hInstance = GetModuleHandle(NULL);
    1141         wc.hIcon = NULL;
    1142         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    1143         wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 128));
    1144         wc.lpszMenuName = NULL;
    1145         wc.lpszClassName = "SetupWindowClass";
    1146 
    1147         if (!RegisterClass(&wc))
    1148                 MessageBox(hwndMain,
    1149                             "Could not register window class",
    1150                             "Setup.exe", MB_OK);
    1151 
    1152         wsprintf(buffer, "Setup %s", title);
    1153         hwnd = CreateWindow("SetupWindowClass",
    1154                              buffer,
    1155                              0,
    1156                              0, 0,
    1157                              GetSystemMetrics(SM_CXFULLSCREEN),
    1158                              GetSystemMetrics(SM_CYFULLSCREEN),
    1159                              NULL,
    1160                              NULL,
    1161                              GetModuleHandle(NULL),
    1162                              NULL);
    1163         ShowWindow(hwnd, SW_SHOWMAXIMIZED);
    1164         UpdateWindow(hwnd);
    1165         return hwnd;
     1132    WNDCLASS wc;
     1133    HWND hwnd;
     1134    char buffer[4096];
     1135
     1136    wc.style = CS_VREDRAW | CS_HREDRAW;
     1137    wc.lpfnWndProc = WindowProc;
     1138    wc.cbWndExtra = 0;
     1139    wc.cbClsExtra = 0;
     1140    wc.hInstance = GetModuleHandle(NULL);
     1141    wc.hIcon = NULL;
     1142    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
     1143    wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 128));
     1144    wc.lpszMenuName = NULL;
     1145    wc.lpszClassName = "SetupWindowClass";
     1146
     1147    if (!RegisterClass(&wc))
     1148        MessageBox(hwndMain,
     1149                    "Could not register window class",
     1150                    "Setup.exe", MB_OK);
     1151
     1152    wsprintf(buffer, "Setup %s", title);
     1153    hwnd = CreateWindow("SetupWindowClass",
     1154                         buffer,
     1155                         0,
     1156                         0, 0,
     1157                         GetSystemMetrics(SM_CXFULLSCREEN),
     1158                         GetSystemMetrics(SM_CYFULLSCREEN),
     1159                         NULL,
     1160                         NULL,
     1161                         GetModuleHandle(NULL),
     1162                         NULL);
     1163    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
     1164    UpdateWindow(hwnd);
     1165    return hwnd;
    11661166}
    11671167
     
    11711171static void CenterWindow(HWND hwnd)
    11721172{
    1173         RECT rc;
    1174         int w, h;
    1175 
    1176         GetWindowRect(hwnd, &rc);
    1177         w = GetSystemMetrics(SM_CXSCREEN);
    1178         h = GetSystemMetrics(SM_CYSCREEN);
    1179         MoveWindow(hwnd,
    1180                    (w - (rc.right-rc.left))/2,
    1181                    (h - (rc.bottom-rc.top))/2,
    1182                     rc.right-rc.left, rc.bottom-rc.top, FALSE);
     1173    RECT rc;
     1174    int w, h;
     1175
     1176    GetWindowRect(hwnd, &rc);
     1177    w = GetSystemMetrics(SM_CXSCREEN);
     1178    h = GetSystemMetrics(SM_CYSCREEN);
     1179    MoveWindow(hwnd,
     1180               (w - (rc.right-rc.left))/2,
     1181               (h - (rc.bottom-rc.top))/2,
     1182                rc.right-rc.left, rc.bottom-rc.top, FALSE);
    11831183}
    11841184
     
    11881188IntroDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    11891189{
    1190         LPNMHDR lpnm;
    1191         char Buffer[4096];
    1192 
    1193         switch (msg) {
    1194         case WM_INITDIALOG:
    1195                 create_bitmap(hwnd);
    1196                 if(hBitmap)
    1197                         SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE,
    1198                                            IMAGE_BITMAP, (LPARAM)hBitmap);
    1199                 CenterWindow(GetParent(hwnd));
    1200                 wsprintf(Buffer,
    1201                           "This Wizard will install %s on your computer. "
    1202                           "Click Next to continue "
    1203                           "or Cancel to exit the Setup Wizard.",
    1204                           meta_name);
    1205                 SetDlgItemText(hwnd, IDC_TITLE, Buffer);
    1206                 SetDlgItemText(hwnd, IDC_INTRO_TEXT, info);
    1207                 SetDlgItemText(hwnd, IDC_BUILD_INFO, build_info);
    1208                 return FALSE;
    1209 
    1210         case WM_NOTIFY:
    1211                 lpnm = (LPNMHDR) lParam;
    1212 
    1213                 switch (lpnm->code) {
    1214                 case PSN_SETACTIVE:
    1215                         PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT);
    1216                         break;
    1217 
    1218                 case PSN_WIZNEXT:
    1219                         break;
    1220 
    1221                 case PSN_RESET:
    1222                         break;
    1223                
    1224                 default:
    1225                         break;
    1226                 }
    1227         }
    1228         return FALSE;
     1190    LPNMHDR lpnm;
     1191    char Buffer[4096];
     1192
     1193    switch (msg) {
     1194    case WM_INITDIALOG:
     1195        create_bitmap(hwnd);
     1196        if(hBitmap)
     1197            SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE,
     1198                               IMAGE_BITMAP, (LPARAM)hBitmap);
     1199        CenterWindow(GetParent(hwnd));
     1200        wsprintf(Buffer,
     1201                  "This Wizard will install %s on your computer. "
     1202                  "Click Next to continue "
     1203                  "or Cancel to exit the Setup Wizard.",
     1204                  meta_name);
     1205        SetDlgItemText(hwnd, IDC_TITLE, Buffer);
     1206        SetDlgItemText(hwnd, IDC_INTRO_TEXT, info);
     1207        SetDlgItemText(hwnd, IDC_BUILD_INFO, build_info);
     1208        return FALSE;
     1209
     1210    case WM_NOTIFY:
     1211        lpnm = (LPNMHDR) lParam;
     1212
     1213        switch (lpnm->code) {
     1214        case PSN_SETACTIVE:
     1215            PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_NEXT);
     1216            break;
     1217
     1218        case PSN_WIZNEXT:
     1219            break;
     1220
     1221        case PSN_RESET:
     1222            break;
     1223
     1224        default:
     1225            break;
     1226        }
     1227    }
     1228    return FALSE;
    12291229}
    12301230
     
    12381238
    12391239static BOOL __stdcall StatusRoutine(IMAGEHLP_STATUS_REASON reason,
    1240                                     PSTR ImageName,
    1241                                     PSTR DllName,
    1242                                     ULONG Va,
    1243                                     ULONG Parameter)
    1244 {
    1245         char fname[_MAX_PATH];
    1246         int int_version;
    1247 
    1248         switch(reason) {
    1249         case BindOutOfMemory:
    1250         case BindRvaToVaFailed:
    1251         case BindNoRoomInImage:
    1252         case BindImportProcedureFailed:
    1253                 break;
    1254 
    1255         case BindImportProcedure:
    1256         case BindForwarder:
    1257         case BindForwarderNOT:
    1258         case BindImageModified:
    1259         case BindExpandFileHeaders:
    1260         case BindImageComplete:
    1261         case BindSymbolsNotUpdated:
    1262         case BindMismatchedSymbols:
    1263         case BindImportModuleFailed:
    1264                 break;
    1265 
    1266         case BindImportModule:
    1267                 if (1 == sscanf(DllName, "python%d", &int_version)) {
    1268                         SearchPath(NULL, DllName, NULL, sizeof(fname),
    1269                                    fname, NULL);
    1270                         strcpy(bound_image_dll, fname);
    1271                         bound_image_major = int_version / 10;
    1272                         bound_image_minor = int_version % 10;
    1273                         OutputDebugString("BOUND ");
    1274                         OutputDebugString(fname);
    1275                         OutputDebugString("\n");
    1276                 }
    1277                 break;
    1278         }
    1279         return TRUE;
     1240                                    PSTR ImageName,
     1241                                    PSTR DllName,
     1242                                    ULONG Va,
     1243                                    ULONG Parameter)
     1244{
     1245    char fname[_MAX_PATH];
     1246    int int_version;
     1247
     1248    switch(reason) {
     1249    case BindOutOfMemory:
     1250    case BindRvaToVaFailed:
     1251    case BindNoRoomInImage:
     1252    case BindImportProcedureFailed:
     1253        break;
     1254
     1255    case BindImportProcedure:
     1256    case BindForwarder:
     1257    case BindForwarderNOT:
     1258    case BindImageModified:
     1259    case BindExpandFileHeaders:
     1260    case BindImageComplete:
     1261    case BindSymbolsNotUpdated:
     1262    case BindMismatchedSymbols:
     1263    case BindImportModuleFailed:
     1264        break;
     1265
     1266    case BindImportModule:
     1267        if (1 == sscanf(DllName, "python%d", &int_version)) {
     1268            SearchPath(NULL, DllName, NULL, sizeof(fname),
     1269                       fname, NULL);
     1270            strcpy(bound_image_dll, fname);
     1271            bound_image_major = int_version / 10;
     1272            bound_image_minor = int_version % 10;
     1273            OutputDebugString("BOUND ");
     1274            OutputDebugString(fname);
     1275            OutputDebugString("\n");
     1276        }
     1277        break;
     1278    }
     1279    return TRUE;
    12801280}
    12811281
     
    12841284static LPSTR get_sys_prefix(LPSTR exe, LPSTR dll)
    12851285{
    1286         void (__cdecl * Py_Initialize)(void);
    1287         void (__cdecl * Py_SetProgramName)(char *);
    1288         void (__cdecl * Py_Finalize)(void);
    1289         void* (__cdecl * PySys_GetObject)(char *);
    1290         void (__cdecl * PySys_SetArgv)(int, char **);
    1291         char* (__cdecl * Py_GetPrefix)(void);
    1292         char* (__cdecl * Py_GetPath)(void);
    1293         HINSTANCE hPython;
    1294         LPSTR prefix = NULL;
    1295         int (__cdecl * PyRun_SimpleString)(char *);
    1296 
    1297         {
    1298                 char Buffer[256];
    1299                 wsprintf(Buffer, "PYTHONHOME=%s", exe);
    1300                 *strrchr(Buffer, '\\') = '\0';
    1301 //      MessageBox(GetFocus(), Buffer, "PYTHONHOME", MB_OK);
    1302                 _putenv(Buffer);
    1303                 _putenv("PYTHONPATH=");
    1304         }
    1305 
    1306         hPython = LoadLibrary(dll);
    1307         if (!hPython)
    1308                 return NULL;
    1309         Py_Initialize = (void (*)(void))GetProcAddress
    1310                 (hPython,"Py_Initialize");
    1311 
    1312         PySys_SetArgv = (void (*)(int, char **))GetProcAddress
    1313                 (hPython,"PySys_SetArgv");
    1314 
    1315         PyRun_SimpleString = (int (*)(char *))GetProcAddress
    1316                 (hPython,"PyRun_SimpleString");
    1317 
    1318         Py_SetProgramName = (void (*)(char *))GetProcAddress
    1319                 (hPython,"Py_SetProgramName");
    1320 
    1321         PySys_GetObject = (void* (*)(char *))GetProcAddress
    1322                 (hPython,"PySys_GetObject");
    1323 
    1324         Py_GetPrefix = (char * (*)(void))GetProcAddress
    1325                 (hPython,"Py_GetPrefix");
    1326 
    1327         Py_GetPath = (char * (*)(void))GetProcAddress
    1328                 (hPython,"Py_GetPath");
    1329 
    1330         Py_Finalize = (void (*)(void))GetProcAddress(hPython,
    1331                                                       "Py_Finalize");
    1332         Py_SetProgramName(exe);
    1333         Py_Initialize();
    1334         PySys_SetArgv(1, &exe);
    1335 
    1336         MessageBox(GetFocus(), Py_GetPrefix(), "PREFIX", MB_OK);
    1337         MessageBox(GetFocus(), Py_GetPath(), "PATH", MB_OK);
    1338 
    1339         Py_Finalize();
    1340         FreeLibrary(hPython);
    1341 
    1342         return prefix;
     1286    void (__cdecl * Py_Initialize)(void);
     1287    void (__cdecl * Py_SetProgramName)(char *);
     1288    void (__cdecl * Py_Finalize)(void);
     1289    void* (__cdecl * PySys_GetObject)(char *);
     1290    void (__cdecl * PySys_SetArgv)(int, char **);
     1291    char* (__cdecl * Py_GetPrefix)(void);
     1292    char* (__cdecl * Py_GetPath)(void);
     1293    HINSTANCE hPython;
     1294    LPSTR prefix = NULL;
     1295    int (__cdecl * PyRun_SimpleString)(char *);
     1296
     1297    {
     1298        char Buffer[256];
     1299        wsprintf(Buffer, "PYTHONHOME=%s", exe);
     1300        *strrchr(Buffer, '\\') = '\0';
     1301//      MessageBox(GetFocus(), Buffer, "PYTHONHOME", MB_OK);
     1302                _putenv(Buffer);
     1303                _putenv("PYTHONPATH=");
     1304    }
     1305
     1306    hPython = LoadLibrary(dll);
     1307    if (!hPython)
     1308        return NULL;
     1309    Py_Initialize = (void (*)(void))GetProcAddress
     1310        (hPython,"Py_Initialize");
     1311
     1312    PySys_SetArgv = (void (*)(int, char **))GetProcAddress
     1313        (hPython,"PySys_SetArgv");
     1314
     1315    PyRun_SimpleString = (int (*)(char *))GetProcAddress
     1316        (hPython,"PyRun_SimpleString");
     1317
     1318    Py_SetProgramName = (void (*)(char *))GetProcAddress
     1319        (hPython,"Py_SetProgramName");
     1320
     1321    PySys_GetObject = (void* (*)(char *))GetProcAddress
     1322        (hPython,"PySys_GetObject");
     1323
     1324    Py_GetPrefix = (char * (*)(void))GetProcAddress
     1325        (hPython,"Py_GetPrefix");
     1326
     1327    Py_GetPath = (char * (*)(void))GetProcAddress
     1328        (hPython,"Py_GetPath");
     1329
     1330    Py_Finalize = (void (*)(void))GetProcAddress(hPython,
     1331                                                  "Py_Finalize");
     1332    Py_SetProgramName(exe);
     1333    Py_Initialize();
     1334    PySys_SetArgv(1, &exe);
     1335
     1336    MessageBox(GetFocus(), Py_GetPrefix(), "PREFIX", MB_OK);
     1337    MessageBox(GetFocus(), Py_GetPath(), "PATH", MB_OK);
     1338
     1339    Py_Finalize();
     1340    FreeLibrary(hPython);
     1341
     1342    return prefix;
    13431343}
    13441344
     
    13461346CheckPythonExe(LPSTR pathname, LPSTR version, int *pmajor, int *pminor)
    13471347{
    1348         bound_image_dll[0] = '\0';
    1349         if (!BindImageEx(BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE | BIND_ALL_IMAGES,
    1350                         pathname,
    1351                         NULL,
    1352                         NULL,
    1353                         StatusRoutine))
    1354                 return SystemError(0, "Could not bind image");
    1355         if (bound_image_dll[0] == '\0')
    1356                 return SystemError(0, "Does not seem to be a python executable");
    1357         *pmajor = bound_image_major;
    1358         *pminor = bound_image_minor;
    1359         if (version && *version) {
    1360                 char core_version[12];
    1361                 wsprintf(core_version, "%d.%d", bound_image_major, bound_image_minor);
    1362                 if (strcmp(version, core_version))
    1363                         return SystemError(0, "Wrong Python version");
    1364         }
    1365         get_sys_prefix(pathname, bound_image_dll);
    1366         return TRUE;
     1348    bound_image_dll[0] = '\0';
     1349    if (!BindImageEx(BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE | BIND_ALL_IMAGES,
     1350                    pathname,
     1351                    NULL,
     1352                    NULL,
     1353                    StatusRoutine))
     1354        return SystemError(0, "Could not bind image");
     1355    if (bound_image_dll[0] == '\0')
     1356        return SystemError(0, "Does not seem to be a python executable");
     1357    *pmajor = bound_image_major;
     1358    *pminor = bound_image_minor;
     1359    if (version && *version) {
     1360        char core_version[12];
     1361        wsprintf(core_version, "%d.%d", bound_image_major, bound_image_minor);
     1362        if (strcmp(version, core_version))
     1363            return SystemError(0, "Wrong Python version");
     1364    }
     1365    get_sys_prefix(pathname, bound_image_dll);
     1366    return TRUE;
    13671367}
    13681368
     
    13731373static BOOL GetOtherPythonVersion(HWND hwnd, LPSTR version)
    13741374{
    1375         char vers_name[_MAX_PATH + 80];
    1376         DWORD itemindex;
    1377         OPENFILENAME of;
    1378         char pathname[_MAX_PATH];
    1379         DWORD result;
    1380 
    1381         strcpy(pathname, "python.exe");
    1382 
    1383         memset(&of, 0, sizeof(of));
    1384         of.lStructSize = sizeof(OPENFILENAME);
    1385         of.hwndOwner = GetParent(hwnd);
    1386         of.hInstance = NULL;
    1387         of.lpstrFilter = "python.exe\0python.exe\0";
    1388         of.lpstrCustomFilter = NULL;
    1389         of.nMaxCustFilter = 0;
    1390         of.nFilterIndex = 1;
    1391         of.lpstrFile = pathname;
    1392         of.nMaxFile = sizeof(pathname);
    1393         of.lpstrFileTitle = NULL;
    1394         of.nMaxFileTitle = 0;
    1395         of.lpstrInitialDir = NULL;
    1396         of.lpstrTitle = "Python executable";
    1397         of.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
    1398         of.lpstrDefExt = "exe";
    1399 
    1400         result = GetOpenFileName(&of);
    1401         if (result) {
    1402                 int major, minor;
    1403                 if (!CheckPythonExe(pathname, version, &major, &minor)) {
    1404                         return FALSE;
    1405                 }
    1406                 *strrchr(pathname, '\\') = '\0';
    1407                 wsprintf(vers_name, "Python Version %d.%d in %s",
    1408                           major, minor, pathname);
    1409                 itemindex = SendMessage(hwnd, LB_INSERTSTRING, -1,
    1410                                         (LPARAM)(LPSTR)vers_name);
    1411                 SendMessage(hwnd, LB_SETCURSEL, itemindex, 0);
    1412                 SendMessage(hwnd, LB_SETITEMDATA, itemindex,
    1413                             (LPARAM)(LPSTR)strdup(pathname));
    1414                 return TRUE;
    1415         }
    1416         return FALSE;
     1375    char vers_name[_MAX_PATH + 80];
     1376    DWORD itemindex;
     1377    OPENFILENAME of;
     1378    char pathname[_MAX_PATH];
     1379    DWORD result;
     1380
     1381    strcpy(pathname, "python.exe");
     1382
     1383    memset(&of, 0, sizeof(of));
     1384    of.lStructSize = sizeof(OPENFILENAME);
     1385    of.hwndOwner = GetParent(hwnd);
     1386    of.hInstance = NULL;
     1387    of.lpstrFilter = "python.exe\0python.exe\0";
     1388    of.lpstrCustomFilter = NULL;
     1389    of.nMaxCustFilter = 0;
     1390    of.nFilterIndex = 1;
     1391    of.lpstrFile = pathname;
     1392    of.nMaxFile = sizeof(pathname);
     1393    of.lpstrFileTitle = NULL;
     1394    of.nMaxFileTitle = 0;
     1395    of.lpstrInitialDir = NULL;
     1396    of.lpstrTitle = "Python executable";
     1397    of.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
     1398    of.lpstrDefExt = "exe";
     1399
     1400    result = GetOpenFileName(&of);
     1401    if (result) {
     1402        int major, minor;
     1403        if (!CheckPythonExe(pathname, version, &major, &minor)) {
     1404            return FALSE;
     1405        }
     1406        *strrchr(pathname, '\\') = '\0';
     1407        wsprintf(vers_name, "Python Version %d.%d in %s",
     1408                  major, minor, pathname);
     1409        itemindex = SendMessage(hwnd, LB_INSERTSTRING, -1,
     1410                                (LPARAM)(LPSTR)vers_name);
     1411        SendMessage(hwnd, LB_SETCURSEL, itemindex, 0);
     1412        SendMessage(hwnd, LB_SETITEMDATA, itemindex,
     1413                    (LPARAM)(LPSTR)strdup(pathname));
     1414        return TRUE;
     1415    }
     1416    return FALSE;
    14171417}
    14181418#endif /* USE_OTHER_PYTHON_VERSIONS */
     
    14311431static BOOL GetPythonVersions(HWND hwnd, HKEY hkRoot, LPSTR version)
    14321432{
    1433         DWORD index = 0;
    1434         char core_version[80];
    1435         HKEY hKey;
    1436         BOOL result = TRUE;
    1437         DWORD bufsize;
    1438 
    1439         if (ERROR_SUCCESS != RegOpenKeyEx(hkRoot,
    1440                                            "Software\\Python\\PythonCore",
    1441                                            0,   KEY_READ, &hKey))
    1442                 return FALSE;
    1443         bufsize = sizeof(core_version);
    1444         while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index,
    1445                                               core_version, &bufsize, NULL,
    1446                                               NULL, NULL, NULL)) {
    1447                 char subkey_name[80], vers_name[80];
    1448                 int itemindex;
    1449                 DWORD value_size;
    1450                 HKEY hk;
    1451 
    1452                 bufsize = sizeof(core_version);
    1453                 ++index;
    1454                 if (version && *version && strcmp(version, core_version))
    1455                         continue;
    1456 
    1457                 wsprintf(vers_name, "Python Version %s (found in registry)",
    1458                           core_version);
    1459                 wsprintf(subkey_name,
    1460                           "Software\\Python\\PythonCore\\%s\\InstallPath",
    1461                           core_version);
    1462                 if (ERROR_SUCCESS == RegOpenKeyEx(hkRoot, subkey_name, 0, KEY_READ, &hk)) {
    1463                         InstalledVersionInfo *ivi =
    1464                               (InstalledVersionInfo *)malloc(sizeof(InstalledVersionInfo));
    1465                         value_size = sizeof(ivi->prefix);
    1466                         if (ivi &&
    1467                             ERROR_SUCCESS == RegQueryValueEx(hk, NULL, NULL, NULL,
    1468                                                              ivi->prefix, &value_size)) {
    1469                                 itemindex = SendMessage(hwnd, LB_ADDSTRING, 0,
    1470                                                         (LPARAM)(LPSTR)vers_name);
    1471                                 ivi->hkey = hkRoot;
    1472                                 SendMessage(hwnd, LB_SETITEMDATA, itemindex,
    1473                                             (LPARAM)(LPSTR)ivi);
    1474                         }
    1475                         RegCloseKey(hk);
    1476                 }
    1477         }
    1478         RegCloseKey(hKey);
    1479         return result;
     1433    DWORD index = 0;
     1434    char core_version[80];
     1435    HKEY hKey;
     1436    BOOL result = TRUE;
     1437    DWORD bufsize;
     1438
     1439    if (ERROR_SUCCESS != RegOpenKeyEx(hkRoot,
     1440                                       "Software\\Python\\PythonCore",
     1441                                       0,       KEY_READ, &hKey))
     1442        return FALSE;
     1443    bufsize = sizeof(core_version);
     1444    while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index,
     1445                                          core_version, &bufsize, NULL,
     1446                                          NULL, NULL, NULL)) {
     1447        char subkey_name[80], vers_name[80];
     1448        int itemindex;
     1449        DWORD value_size;
     1450        HKEY hk;
     1451
     1452        bufsize = sizeof(core_version);
     1453        ++index;
     1454        if (version && *version && strcmp(version, core_version))
     1455            continue;
     1456
     1457        wsprintf(vers_name, "Python Version %s (found in registry)",
     1458                  core_version);
     1459        wsprintf(subkey_name,
     1460                  "Software\\Python\\PythonCore\\%s\\InstallPath",
     1461                  core_version);
     1462        if (ERROR_SUCCESS == RegOpenKeyEx(hkRoot, subkey_name, 0, KEY_READ, &hk)) {
     1463            InstalledVersionInfo *ivi =
     1464                  (InstalledVersionInfo *)malloc(sizeof(InstalledVersionInfo));
     1465            value_size = sizeof(ivi->prefix);
     1466            if (ivi &&
     1467                ERROR_SUCCESS == RegQueryValueEx(hk, NULL, NULL, NULL,
     1468                                                 ivi->prefix, &value_size)) {
     1469                itemindex = SendMessage(hwnd, LB_ADDSTRING, 0,
     1470                                        (LPARAM)(LPSTR)vers_name);
     1471                ivi->hkey = hkRoot;
     1472                SendMessage(hwnd, LB_SETITEMDATA, itemindex,
     1473                            (LPARAM)(LPSTR)ivi);
     1474            }
     1475            RegCloseKey(hk);
     1476        }
     1477    }
     1478    RegCloseKey(hKey);
     1479    return result;
    14801480}
    14811481
     
    14831483BOOL HasLocalMachinePrivs()
    14841484{
    1485                 HKEY hKey;
    1486                 DWORD result;
    1487                 static char KeyName[] =
    1488                         "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
    1489 
    1490                 result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    1491                                           KeyName,
    1492                                           0,
    1493                                           KEY_CREATE_SUB_KEY,
    1494                                           &hKey);
    1495                 if (result==0)
    1496                         RegCloseKey(hKey);
    1497                 return result==0;
     1485                HKEY hKey;
     1486                DWORD result;
     1487                static char KeyName[] =
     1488                        "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
     1489
     1490                result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
     1491                                          KeyName,
     1492                                          0,
     1493                                          KEY_CREATE_SUB_KEY,
     1494                                          &hKey);
     1495                if (result==0)
     1496                        RegCloseKey(hKey);
     1497                return result==0;
    14981498}
    14991499
     
    15081508void CheckRootKey(HWND hwnd)
    15091509{
    1510         if (hkey_root==HKEY_CURRENT_USER) {
    1511                 ; // as above, always install ourself in HKCU too.
    1512         } else if (hkey_root==HKEY_LOCAL_MACHINE) {
    1513                 // Python in HKLM, but we may or may not have permissions there.
    1514                 // Open the uninstall key with 'create' permissions - if this fails,
    1515                 // we don't have permission.
    1516                 if (!HasLocalMachinePrivs())
    1517                         hkey_root = HKEY_CURRENT_USER;
    1518         } else {
    1519                 MessageBox(hwnd, "Don't know Python's installation type",
    1520                                    "Strange", MB_OK | MB_ICONSTOP);
    1521                 /* Default to wherever they can, but preferring HKLM */
    1522                 hkey_root = HasLocalMachinePrivs() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    1523         }
     1510    if (hkey_root==HKEY_CURRENT_USER) {
     1511        ; // as above, always install ourself in HKCU too.
     1512    } else if (hkey_root==HKEY_LOCAL_MACHINE) {
     1513        // Python in HKLM, but we may or may not have permissions there.
     1514        // Open the uninstall key with 'create' permissions - if this fails,
     1515        // we don't have permission.
     1516        if (!HasLocalMachinePrivs())
     1517            hkey_root = HKEY_CURRENT_USER;
     1518    } else {
     1519        MessageBox(hwnd, "Don't know Python's installation type",
     1520                           "Strange", MB_OK | MB_ICONSTOP);
     1521        /* Default to wherever they can, but preferring HKLM */
     1522        hkey_root = HasLocalMachinePrivs() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
     1523    }
    15241524}
    15251525
     
    15271527SCHEME *GetScheme(int major, int minor)
    15281528{
    1529         if (major > 2)
    1530                 return new_scheme;
    1531         else if((major == 2) && (minor >= 2))
    1532                 return new_scheme;
    1533         return old_scheme;
     1529    if (major > 2)
     1530        return new_scheme;
     1531    else if((major == 2) && (minor >= 2))
     1532        return new_scheme;
     1533    return old_scheme;
    15341534}
    15351535
     
    15371537SelectPythonDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    15381538{
    1539         LPNMHDR lpnm;
    1540 
    1541         switch (msg) {
    1542         case WM_INITDIALOG:
    1543                 if (hBitmap)
    1544                         SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE,
    1545                                            IMAGE_BITMAP, (LPARAM)hBitmap);
    1546                 GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST),
    1547                                    HKEY_LOCAL_MACHINE, target_version);
    1548                 GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST),
    1549                                    HKEY_CURRENT_USER, target_version);
    1550                 {       /* select the last entry which is the highest python
    1551                            version found */
    1552                         int count;
    1553                         count = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
    1554                                                     LB_GETCOUNT, 0, 0);
    1555                         if (count && count != LB_ERR)
    1556                                 SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, LB_SETCURSEL,
    1557                                                     count-1, 0);
    1558            
    1559                         /* If a specific Python version is required,
    1560                         * display a prominent notice showing this fact.
    1561                         */
    1562                         if (target_version && target_version[0]) {
    1563                                 char buffer[4096];
    1564                                 wsprintf(buffer,
    1565                                         "Python %s is required for this package. "
    1566                                         "Select installation to use:",
    1567                                         target_version);
    1568                                 SetDlgItemText(hwnd, IDC_TITLE, buffer);
    1569                         }
    1570 
    1571                         if (count == 0) {
    1572                                 char Buffer[4096];
    1573                                 char *msg;
    1574                                 if (target_version && target_version[0]) {
    1575                                         wsprintf(Buffer,
    1576                                                 "Python version %s required, which was not found"
    1577                                                 " in the registry.", target_version);
    1578                                         msg = Buffer;
    1579                                 } else
    1580                                         msg = "No Python installation found in the registry.";
    1581                                 MessageBox(hwnd, msg, "Cannot install",
    1582                                            MB_OK | MB_ICONSTOP);
    1583                         }
    1584                 }
    1585                 goto UpdateInstallDir;
    1586                 break;
    1587 
    1588         case WM_COMMAND:
    1589                 switch (LOWORD(wParam)) {
     1539    LPNMHDR lpnm;
     1540
     1541    switch (msg) {
     1542    case WM_INITDIALOG:
     1543        if (hBitmap)
     1544            SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE,
     1545                               IMAGE_BITMAP, (LPARAM)hBitmap);
     1546        GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST),
     1547                           HKEY_LOCAL_MACHINE, target_version);
     1548        GetPythonVersions(GetDlgItem(hwnd, IDC_VERSIONS_LIST),
     1549                           HKEY_CURRENT_USER, target_version);
     1550        {               /* select the last entry which is the highest python
     1551                   version found */
     1552            int count;
     1553            count = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
     1554                                        LB_GETCOUNT, 0, 0);
     1555            if (count && count != LB_ERR)
     1556                SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST, LB_SETCURSEL,
     1557                                    count-1, 0);
     1558
     1559            /* If a specific Python version is required,
     1560            * display a prominent notice showing this fact.
     1561            */
     1562            if (target_version && target_version[0]) {
     1563                char buffer[4096];
     1564                wsprintf(buffer,
     1565                        "Python %s is required for this package. "
     1566                        "Select installation to use:",
     1567                        target_version);
     1568                SetDlgItemText(hwnd, IDC_TITLE, buffer);
     1569            }
     1570
     1571            if (count == 0) {
     1572                char Buffer[4096];
     1573                char *msg;
     1574                if (target_version && target_version[0]) {
     1575                    wsprintf(Buffer,
     1576                            "Python version %s required, which was not found"
     1577                            " in the registry.", target_version);
     1578                    msg = Buffer;
     1579                } else
     1580                    msg = "No Python installation found in the registry.";
     1581                MessageBox(hwnd, msg, "Cannot install",
     1582                           MB_OK | MB_ICONSTOP);
     1583            }
     1584        }
     1585        goto UpdateInstallDir;
     1586        break;
     1587
     1588    case WM_COMMAND:
     1589        switch (LOWORD(wParam)) {
    15901590/*
    15911591  case IDC_OTHERPYTHON:
     
    15951595  break;
    15961596*/
    1597                 case IDC_VERSIONS_LIST:
    1598                         switch (HIWORD(wParam)) {
    1599                                 int id;
    1600                         case LBN_SELCHANGE:
    1601                           UpdateInstallDir:
    1602                                 PropSheet_SetWizButtons(GetParent(hwnd),
    1603                                                         PSWIZB_BACK | PSWIZB_NEXT);
    1604                                 id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
    1605                                                         LB_GETCURSEL, 0, 0);
    1606                                 if (id == LB_ERR) {
    1607                                         PropSheet_SetWizButtons(GetParent(hwnd),
    1608                                                                 PSWIZB_BACK);
    1609                                         SetDlgItemText(hwnd, IDC_PATH, "");
    1610                                         SetDlgItemText(hwnd, IDC_INSTALL_PATH, "");
    1611                                         strcpy(python_dir, "");
    1612                                         strcpy(pythondll, "");
    1613                                 } else {
    1614                                         char *pbuf;
    1615                                         int result;
    1616                                         InstalledVersionInfo *ivi;
    1617                                         PropSheet_SetWizButtons(GetParent(hwnd),
    1618                                                                 PSWIZB_BACK | PSWIZB_NEXT);
    1619                                         /* Get the python directory */
    1620                     ivi = (InstalledVersionInfo *)
    1621                                 SendDlgItemMessage(hwnd,
    1622                                                                         IDC_VERSIONS_LIST,
    1623                                                                         LB_GETITEMDATA,
    1624                                                                         id,
    1625                                                                         0);
    1626                     hkey_root = ivi->hkey;
    1627                                         strcpy(python_dir, ivi->prefix);
    1628                                         SetDlgItemText(hwnd, IDC_PATH, python_dir);
    1629                                         /* retrieve the python version and pythondll to use */
    1630                                         result = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
    1631                                                                      LB_GETTEXTLEN, (WPARAM)id, 0);
    1632                                         pbuf = (char *)malloc(result + 1);
    1633                                         if (pbuf) {
    1634                                                 /* guess the name of the python-dll */
    1635                                                 SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
    1636                                                                     LB_GETTEXT, (WPARAM)id,
    1637                                                                     (LPARAM)pbuf);
    1638                                                 result = sscanf(pbuf, "Python Version %d.%d",
    1639                                                                 &py_major, &py_minor);
    1640                                                 if (result == 2) {
     1597        case IDC_VERSIONS_LIST:
     1598            switch (HIWORD(wParam)) {
     1599                int id;
     1600            case LBN_SELCHANGE:
     1601              UpdateInstallDir:
     1602                PropSheet_SetWizButtons(GetParent(hwnd),
     1603                                        PSWIZB_BACK | PSWIZB_NEXT);
     1604                id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
     1605                                        LB_GETCURSEL, 0, 0);
     1606                if (id == LB_ERR) {
     1607                    PropSheet_SetWizButtons(GetParent(hwnd),
     1608                                            PSWIZB_BACK);
     1609                    SetDlgItemText(hwnd, IDC_PATH, "");
     1610                    SetDlgItemText(hwnd, IDC_INSTALL_PATH, "");
     1611                    strcpy(python_dir, "");
     1612                    strcpy(pythondll, "");
     1613                } else {
     1614                    char *pbuf;
     1615                    int result;
     1616                    InstalledVersionInfo *ivi;
     1617                    PropSheet_SetWizButtons(GetParent(hwnd),
     1618                                            PSWIZB_BACK | PSWIZB_NEXT);
     1619                    /* Get the python directory */
     1620            ivi = (InstalledVersionInfo *)
     1621                        SendDlgItemMessage(hwnd,
     1622                                                                IDC_VERSIONS_LIST,
     1623                                                                LB_GETITEMDATA,
     1624                                                                id,
     1625                                                                0);
     1626            hkey_root = ivi->hkey;
     1627                                strcpy(python_dir, ivi->prefix);
     1628                                SetDlgItemText(hwnd, IDC_PATH, python_dir);
     1629                                /* retrieve the python version and pythondll to use */
     1630                    result = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
     1631                                                 LB_GETTEXTLEN, (WPARAM)id, 0);
     1632                    pbuf = (char *)malloc(result + 1);
     1633                    if (pbuf) {
     1634                        /* guess the name of the python-dll */
     1635                        SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
     1636                                            LB_GETTEXT, (WPARAM)id,
     1637                                            (LPARAM)pbuf);
     1638                        result = sscanf(pbuf, "Python Version %d.%d",
     1639                                        &py_major, &py_minor);
     1640                        if (result == 2) {
    16411641#ifdef _DEBUG
    1642                                                         wsprintf(pythondll, "python%d%d_d.dll",
    1643                                                                 py_major, py_minor);
     1642                            wsprintf(pythondll, "python%d%d_d.dll",
     1643                                    py_major, py_minor);
    16441644#else
    1645                                                         wsprintf(pythondll, "python%d%d.dll",
    1646                                                                 py_major, py_minor);
     1645                            wsprintf(pythondll, "python%d%d.dll",
     1646                                    py_major, py_minor);
    16471647#endif
    1648                                                 }
    1649                                                 free(pbuf);
    1650                                         } else
    1651                                                 strcpy(pythondll, "");
    1652                                         /* retrieve the scheme for this version */
    1653                                         {
    1654                                                 char install_path[_MAX_PATH];
    1655                                                 SCHEME *scheme = GetScheme(py_major, py_minor);
    1656                                                 strcpy(install_path, python_dir);
    1657                                                 if (install_path[strlen(install_path)-1] != '\\')
    1658                                                         strcat(install_path, "\\");
    1659                                                 strcat(install_path, scheme[0].prefix);
    1660                                                 SetDlgItemText(hwnd, IDC_INSTALL_PATH, install_path);
    1661                                         }
    1662                                 }
    1663                         }
    1664                         break;
    1665                 }
    1666                 return 0;
    1667 
    1668         case WM_NOTIFY:
    1669                 lpnm = (LPNMHDR) lParam;
    1670 
    1671                 switch (lpnm->code) {
    1672                         int id;
    1673                 case PSN_SETACTIVE:
    1674                         id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
    1675                                                 LB_GETCURSEL, 0, 0);
    1676                         if (id == LB_ERR)
    1677                                 PropSheet_SetWizButtons(GetParent(hwnd),
    1678                                                         PSWIZB_BACK);
    1679                         else
    1680                                 PropSheet_SetWizButtons(GetParent(hwnd),
    1681                                                         PSWIZB_BACK | PSWIZB_NEXT);
    1682                         break;
    1683 
    1684                 case PSN_WIZNEXT:
    1685                         break;
    1686 
    1687                 case PSN_WIZFINISH:
    1688                         break;
    1689 
    1690                 case PSN_RESET:
    1691                         break;
    1692                
    1693                 default:
    1694                         break;
    1695                 }
    1696         }
    1697         return 0;
     1648                        }
     1649                        free(pbuf);
     1650                    } else
     1651                        strcpy(pythondll, "");
     1652                    /* retrieve the scheme for this version */
     1653                    {
     1654                        char install_path[_MAX_PATH];
     1655                        SCHEME *scheme = GetScheme(py_major, py_minor);
     1656                        strcpy(install_path, python_dir);
     1657                        if (install_path[strlen(install_path)-1] != '\\')
     1658                            strcat(install_path, "\\");
     1659                        strcat(install_path, scheme[0].prefix);
     1660                        SetDlgItemText(hwnd, IDC_INSTALL_PATH, install_path);
     1661                    }
     1662                }
     1663            }
     1664            break;
     1665        }
     1666        return 0;
     1667
     1668    case WM_NOTIFY:
     1669        lpnm = (LPNMHDR) lParam;
     1670
     1671        switch (lpnm->code) {
     1672            int id;
     1673        case PSN_SETACTIVE:
     1674            id = SendDlgItemMessage(hwnd, IDC_VERSIONS_LIST,
     1675                                    LB_GETCURSEL, 0, 0);
     1676            if (id == LB_ERR)
     1677                PropSheet_SetWizButtons(GetParent(hwnd),
     1678                                        PSWIZB_BACK);
     1679            else
     1680                PropSheet_SetWizButtons(GetParent(hwnd),
     1681                                        PSWIZB_BACK | PSWIZB_NEXT);
     1682            break;
     1683
     1684        case PSN_WIZNEXT:
     1685            break;
     1686
     1687        case PSN_WIZFINISH:
     1688            break;
     1689
     1690        case PSN_RESET:
     1691            break;
     1692
     1693        default:
     1694            break;
     1695        }
     1696    }
     1697    return 0;
    16981698}
    16991699
    17001700static BOOL OpenLogfile(char *dir)
    17011701{
    1702         char buffer[_MAX_PATH+1];
    1703         time_t ltime;
    1704         struct tm *now;
    1705         long result;
    1706         HKEY hKey, hSubkey;
    1707         char subkey_name[256];
    1708         static char KeyName[] =
    1709                 "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
    1710         const char *root_name = (hkey_root==HKEY_LOCAL_MACHINE ?
    1711                                 "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER");
    1712         DWORD disposition;
    1713 
    1714         /* Use Create, as the Uninstall subkey may not exist under HKCU.
    1715            Use CreateKeyEx, so we can specify a SAM specifying write access
    1716         */
    1717                 result = RegCreateKeyEx(hkey_root,
    1718                               KeyName,
    1719                               0, /* reserved */
    1720                               NULL, /* class */
    1721                               0, /* options */
    1722                               KEY_CREATE_SUB_KEY, /* sam */
    1723                               NULL, /* security */
    1724                               &hKey, /* result key */
    1725                               NULL); /* disposition */
    1726         if (result != ERROR_SUCCESS) {
    1727                 if (result == ERROR_ACCESS_DENIED) {
    1728                         /* This should no longer be able to happen - we have already
    1729                            checked if they have permissions in HKLM, and all users
    1730                            should have write access to HKCU.
    1731                         */
    1732                         MessageBox(GetFocus(),
    1733                                    "You do not seem to have sufficient access rights\n"
    1734                                    "on this machine to install this software",
    1735                                    NULL,
    1736                                    MB_OK | MB_ICONSTOP);
    1737                         return FALSE;
    1738                 } else {
    1739                         MessageBox(GetFocus(), KeyName, "Could not open key", MB_OK);
    1740                 }
    1741         }
    1742 
    1743         sprintf(buffer, "%s\\%s-wininst.log", dir, meta_name);
    1744         logfile = fopen(buffer, "a");
    1745         time(&ltime);
    1746         now = localtime(&ltime);
    1747         strftime(buffer, sizeof(buffer),
    1748                 "*** Installation started %Y/%m/%d %H:%M ***\n",
    1749                 localtime(&ltime));
    1750         fprintf(logfile, buffer);
    1751         fprintf(logfile, "Source: %s\n", modulename);
    1752 
    1753         /* Root key must be first entry processed by uninstaller. */
    1754         fprintf(logfile, "999 Root Key: %s\n", root_name);
    1755 
    1756         sprintf(subkey_name, "%s-py%d.%d", meta_name, py_major, py_minor);
    1757 
    1758         result = RegCreateKeyEx(hKey, subkey_name,
    1759                                 0, NULL, 0,
    1760                                 KEY_WRITE,
    1761                                 NULL,
    1762                                 &hSubkey,
    1763                                 &disposition);
    1764 
    1765         if (result != ERROR_SUCCESS)
    1766                 MessageBox(GetFocus(), subkey_name, "Could not create key", MB_OK);
    1767 
    1768         RegCloseKey(hKey);
    1769 
    1770         if (disposition == REG_CREATED_NEW_KEY)
    1771                 fprintf(logfile, "020 Reg DB Key: [%s]%s\n", KeyName, subkey_name);
    1772 
    1773         sprintf(buffer, "Python %d.%d %s", py_major, py_minor, title);
    1774 
    1775         result = RegSetValueEx(hSubkey, "DisplayName",
    1776                                0,
    1777                                REG_SZ,
    1778                                buffer,
    1779                                strlen(buffer)+1);
    1780 
    1781         if (result != ERROR_SUCCESS)
    1782                 MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK);
    1783 
    1784         fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n",
    1785                 KeyName, subkey_name, "DisplayName", buffer);
    1786 
    1787         {
    1788                 FILE *fp;
    1789                 sprintf(buffer, "%s\\Remove%s.exe", dir, meta_name);
    1790                 fp = fopen(buffer, "wb");
    1791                 fwrite(arc_data, exe_size, 1, fp);
    1792                 fclose(fp);
    1793 
    1794                 sprintf(buffer, "\"%s\\Remove%s.exe\" -u \"%s\\%s-wininst.log\"",
    1795                         dir, meta_name, dir, meta_name);
    1796 
    1797                 result = RegSetValueEx(hSubkey, "UninstallString",
    1798                                        0,
    1799                                        REG_SZ,
    1800                                        buffer,
    1801                                        strlen(buffer)+1);
    1802        
    1803                 if (result != ERROR_SUCCESS)
    1804                         MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK);
    1805 
    1806                 fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n",
    1807                         KeyName, subkey_name, "UninstallString", buffer);
    1808         }
    1809         return TRUE;
     1702    char buffer[_MAX_PATH+1];
     1703    time_t ltime;
     1704    struct tm *now;
     1705    long result;
     1706    HKEY hKey, hSubkey;
     1707    char subkey_name[256];
     1708    static char KeyName[] =
     1709        "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
     1710    const char *root_name = (hkey_root==HKEY_LOCAL_MACHINE ?
     1711                            "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER");
     1712    DWORD disposition;
     1713
     1714    /* Use Create, as the Uninstall subkey may not exist under HKCU.
     1715       Use CreateKeyEx, so we can specify a SAM specifying write access
     1716    */
     1717        result = RegCreateKeyEx(hkey_root,
     1718                      KeyName,
     1719                      0, /* reserved */
     1720                  NULL, /* class */
     1721                  0, /* options */
     1722                  KEY_CREATE_SUB_KEY, /* sam */
     1723                  NULL, /* security */
     1724                  &hKey, /* result key */
     1725                  NULL); /* disposition */
     1726    if (result != ERROR_SUCCESS) {
     1727        if (result == ERROR_ACCESS_DENIED) {
     1728            /* This should no longer be able to happen - we have already
     1729               checked if they have permissions in HKLM, and all users
     1730               should have write access to HKCU.
     1731            */
     1732            MessageBox(GetFocus(),
     1733                       "You do not seem to have sufficient access rights\n"
     1734                       "on this machine to install this software",
     1735                       NULL,
     1736                       MB_OK | MB_ICONSTOP);
     1737            return FALSE;
     1738        } else {
     1739            MessageBox(GetFocus(), KeyName, "Could not open key", MB_OK);
     1740        }
     1741    }
     1742
     1743    sprintf(buffer, "%s\\%s-wininst.log", dir, meta_name);
     1744    logfile = fopen(buffer, "a");
     1745    time(&ltime);
     1746    now = localtime(&ltime);
     1747    strftime(buffer, sizeof(buffer),
     1748            "*** Installation started %Y/%m/%d %H:%M ***\n",
     1749            localtime(&ltime));
     1750    fprintf(logfile, buffer);
     1751    fprintf(logfile, "Source: %s\n", modulename);
     1752
     1753    /* Root key must be first entry processed by uninstaller. */
     1754    fprintf(logfile, "999 Root Key: %s\n", root_name);
     1755
     1756    sprintf(subkey_name, "%s-py%d.%d", meta_name, py_major, py_minor);
     1757
     1758    result = RegCreateKeyEx(hKey, subkey_name,
     1759                            0, NULL, 0,
     1760                            KEY_WRITE,
     1761                            NULL,
     1762                            &hSubkey,
     1763                            &disposition);
     1764
     1765    if (result != ERROR_SUCCESS)
     1766        MessageBox(GetFocus(), subkey_name, "Could not create key", MB_OK);
     1767
     1768    RegCloseKey(hKey);
     1769
     1770    if (disposition == REG_CREATED_NEW_KEY)
     1771        fprintf(logfile, "020 Reg DB Key: [%s]%s\n", KeyName, subkey_name);
     1772
     1773    sprintf(buffer, "Python %d.%d %s", py_major, py_minor, title);
     1774
     1775    result = RegSetValueEx(hSubkey, "DisplayName",
     1776                           0,
     1777                           REG_SZ,
     1778                           buffer,
     1779                           strlen(buffer)+1);
     1780
     1781    if (result != ERROR_SUCCESS)
     1782        MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK);
     1783
     1784    fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n",
     1785        KeyName, subkey_name, "DisplayName", buffer);
     1786
     1787    {
     1788        FILE *fp;
     1789        sprintf(buffer, "%s\\Remove%s.exe", dir, meta_name);
     1790        fp = fopen(buffer, "wb");
     1791        fwrite(arc_data, exe_size, 1, fp);
     1792        fclose(fp);
     1793
     1794        sprintf(buffer, "\"%s\\Remove%s.exe\" -u \"%s\\%s-wininst.log\"",
     1795            dir, meta_name, dir, meta_name);
     1796
     1797        result = RegSetValueEx(hSubkey, "UninstallString",
     1798                               0,
     1799                               REG_SZ,
     1800                               buffer,
     1801                               strlen(buffer)+1);
     1802
     1803        if (result != ERROR_SUCCESS)
     1804            MessageBox(GetFocus(), buffer, "Could not set key value", MB_OK);
     1805
     1806        fprintf(logfile, "040 Reg DB Value: [%s\\%s]%s=%s\n",
     1807            KeyName, subkey_name, "UninstallString", buffer);
     1808    }
     1809    return TRUE;
    18101810}
    18111811
    18121812static void CloseLogfile(void)
    18131813{
    1814         char buffer[_MAX_PATH+1];
    1815         time_t ltime;
    1816         struct tm *now;
    1817 
    1818         time(&ltime);
    1819         now = localtime(&ltime);
    1820         strftime(buffer, sizeof(buffer),
    1821                 "*** Installation finished %Y/%m/%d %H:%M ***\n",
    1822                 localtime(&ltime));
    1823         fprintf(logfile, buffer);
    1824         if (logfile)
    1825                 fclose(logfile);
     1814    char buffer[_MAX_PATH+1];
     1815    time_t ltime;
     1816    struct tm *now;
     1817
     1818    time(&ltime);
     1819    now = localtime(&ltime);
     1820    strftime(buffer, sizeof(buffer),
     1821            "*** Installation finished %Y/%m/%d %H:%M ***\n",
     1822            localtime(&ltime));
     1823    fprintf(logfile, buffer);
     1824    if (logfile)
     1825        fclose(logfile);
    18261826}
    18271827
     
    18291829InstallFilesDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    18301830{
    1831         LPNMHDR lpnm;
    1832         char Buffer[4096];
    1833         SCHEME *scheme;
    1834 
    1835         switch (msg) {
    1836         case WM_INITDIALOG:
    1837                 if (hBitmap)
    1838                         SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE,
    1839                                            IMAGE_BITMAP, (LPARAM)hBitmap);
    1840                 wsprintf(Buffer,
    1841                           "Click Next to begin the installation of %s. "
    1842                           "If you want to review or change any of your "
    1843                           " installation settings, click Back. "
    1844                           "Click Cancel to exit the wizard.",
    1845                           meta_name);
    1846                 SetDlgItemText(hwnd, IDC_TITLE, Buffer);
    1847                 SetDlgItemText(hwnd, IDC_INFO, "Ready to install");
    1848                 break;
    1849 
    1850         case WM_NUMFILES:
    1851                 SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, lParam);
    1852                 PumpMessages();
    1853                 return TRUE;
    1854 
    1855         case WM_NEXTFILE:
    1856                 SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, wParam,
    1857                                     0);
    1858                 SetDlgItemText(hwnd, IDC_INFO, (LPSTR)lParam);
    1859                 PumpMessages();
    1860                 return TRUE;
    1861 
    1862         case WM_NOTIFY:
    1863                 lpnm = (LPNMHDR) lParam;
    1864 
    1865                 switch (lpnm->code) {
    1866                 case PSN_SETACTIVE:
    1867                         PropSheet_SetWizButtons(GetParent(hwnd),
    1868                                                 PSWIZB_BACK | PSWIZB_NEXT);
    1869                         break;
    1870 
    1871                 case PSN_WIZFINISH:
    1872                         break;
    1873 
    1874                 case PSN_WIZNEXT:
    1875                         /* Handle a Next button click here */
    1876                         hDialog = hwnd;
    1877                         success = TRUE;
    1878 
    1879                         /* Disable the buttons while we work.  Sending CANCELTOCLOSE has
    1880                           the effect of disabling the cancel button, which is a) as we
    1881                           do everything synchronously we can't cancel, and b) the next
    1882                           step is 'finished', when it is too late to cancel anyway.
    1883                           The next step being 'Finished' means we also don't need to
    1884                           restore the button state back */
    1885                         PropSheet_SetWizButtons(GetParent(hwnd), 0);
    1886                         SendMessage(GetParent(hwnd), PSM_CANCELTOCLOSE, 0, 0);
    1887                         /* Make sure the installation directory name ends in a */
    1888                         /* backslash */
    1889                         if (python_dir[strlen(python_dir)-1] != '\\')
    1890                                 strcat(python_dir, "\\");
    1891                         /* Strip the trailing backslash again */
    1892                         python_dir[strlen(python_dir)-1] = '\0';
    1893            
    1894                         CheckRootKey(hwnd);
    1895            
    1896                         if (!OpenLogfile(python_dir))
    1897                                 break;
     1831    LPNMHDR lpnm;
     1832    char Buffer[4096];
     1833    SCHEME *scheme;
     1834
     1835    switch (msg) {
     1836    case WM_INITDIALOG:
     1837        if (hBitmap)
     1838            SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE,
     1839                               IMAGE_BITMAP, (LPARAM)hBitmap);
     1840        wsprintf(Buffer,
     1841                  "Click Next to begin the installation of %s. "
     1842                  "If you want to review or change any of your "
     1843                  " installation settings, click Back. "
     1844                  "Click Cancel to exit the wizard.",
     1845                  meta_name);
     1846        SetDlgItemText(hwnd, IDC_TITLE, Buffer);
     1847        SetDlgItemText(hwnd, IDC_INFO, "Ready to install");
     1848        break;
     1849
     1850    case WM_NUMFILES:
     1851        SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, lParam);
     1852        PumpMessages();
     1853        return TRUE;
     1854
     1855    case WM_NEXTFILE:
     1856        SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, wParam,
     1857                            0);
     1858        SetDlgItemText(hwnd, IDC_INFO, (LPSTR)lParam);
     1859        PumpMessages();
     1860        return TRUE;
     1861
     1862    case WM_NOTIFY:
     1863        lpnm = (LPNMHDR) lParam;
     1864
     1865        switch (lpnm->code) {
     1866        case PSN_SETACTIVE:
     1867            PropSheet_SetWizButtons(GetParent(hwnd),
     1868                                    PSWIZB_BACK | PSWIZB_NEXT);
     1869            break;
     1870
     1871        case PSN_WIZFINISH:
     1872            break;
     1873
     1874        case PSN_WIZNEXT:
     1875            /* Handle a Next button click here */
     1876            hDialog = hwnd;
     1877            success = TRUE;
     1878
     1879            /* Disable the buttons while we work.  Sending CANCELTOCLOSE has
     1880              the effect of disabling the cancel button, which is a) as we
     1881              do everything synchronously we can't cancel, and b) the next
     1882              step is 'finished', when it is too late to cancel anyway.
     1883              The next step being 'Finished' means we also don't need to
     1884              restore the button state back */
     1885            PropSheet_SetWizButtons(GetParent(hwnd), 0);
     1886            SendMessage(GetParent(hwnd), PSM_CANCELTOCLOSE, 0, 0);
     1887            /* Make sure the installation directory name ends in a */
     1888            /* backslash */
     1889            if (python_dir[strlen(python_dir)-1] != '\\')
     1890                strcat(python_dir, "\\");
     1891            /* Strip the trailing backslash again */
     1892            python_dir[strlen(python_dir)-1] = '\0';
     1893
     1894            CheckRootKey(hwnd);
     1895
     1896            if (!OpenLogfile(python_dir))
     1897                break;
    18981898
    18991899/*
     
    19161916 }
    19171917*/
    1918                         scheme = GetScheme(py_major, py_minor);
    1919                         /* Run the pre-install script. */
    1920                         if (pre_install_script && *pre_install_script) {
    1921                                 SetDlgItemText (hwnd, IDC_TITLE,
    1922                                                 "Running pre-installation script");
    1923                                 run_simple_script(pre_install_script);
    1924                         }
    1925                         if (!success) {
    1926                                 break;
    1927                         }
    1928                         /* Extract all files from the archive */
    1929                         SetDlgItemText(hwnd, IDC_TITLE, "Installing files...");
    1930                         if (!unzip_archive (scheme,
    1931                                             python_dir, arc_data,
    1932                                             arc_size, notify))
    1933                                 set_failure_reason("Failed to unzip installation files");
    1934                         /* Compile the py-files */
    1935                         if (success && pyc_compile) {
    1936                                 int errors;
    1937                                 HINSTANCE hPython;
    1938                                 SetDlgItemText(hwnd, IDC_TITLE,
    1939                                                 "Compiling files to .pyc...");
    1940 
    1941                                 SetDlgItemText(hDialog, IDC_INFO, "Loading python...");
    1942                                 hPython = LoadPythonDll(pythondll);
    1943                                 if (hPython) {
    1944                                         errors = compile_filelist(hPython, FALSE);
    1945                                         FreeLibrary(hPython);
    1946                                 }
    1947                                 /* Compilation errors are intentionally ignored:
    1948                                 * Python2.0 contains a bug which will result
    1949                                 * in sys.path containing garbage under certain
    1950                                 * circumstances, and an error message will only
    1951                                 * confuse the user.
    1952                                 */
    1953                         }
    1954                         if (success && pyo_compile) {
    1955                                 int errors;
    1956                                 HINSTANCE hPython;
    1957                                 SetDlgItemText(hwnd, IDC_TITLE,
    1958                                                 "Compiling files to .pyo...");
    1959 
    1960                                 SetDlgItemText(hDialog, IDC_INFO, "Loading python...");
    1961                                 hPython = LoadPythonDll(pythondll);
    1962                                 if (hPython) {
    1963                                         errors = compile_filelist(hPython, TRUE);
    1964                                         FreeLibrary(hPython);
    1965                                 }
    1966                                 /* Errors ignored: see above */
    1967                         }
    1968 
    1969 
    1970                         break;
    1971 
    1972                 case PSN_RESET:
    1973                         break;
    1974                
    1975                 default:
    1976                         break;
    1977                 }
    1978         }
    1979         return 0;
     1918            scheme = GetScheme(py_major, py_minor);
     1919            /* Run the pre-install script. */
     1920            if (pre_install_script && *pre_install_script) {
     1921                SetDlgItemText (hwnd, IDC_TITLE,
     1922                                "Running pre-installation script");
     1923                run_simple_script(pre_install_script);
     1924            }
     1925            if (!success) {
     1926                break;
     1927            }
     1928            /* Extract all files from the archive */
     1929            SetDlgItemText(hwnd, IDC_TITLE, "Installing files...");
     1930            if (!unzip_archive (scheme,
     1931                                python_dir, arc_data,
     1932                                arc_size, notify))
     1933                set_failure_reason("Failed to unzip installation files");
     1934            /* Compile the py-files */
     1935            if (success && pyc_compile) {
     1936                int errors;
     1937                HINSTANCE hPython;
     1938                SetDlgItemText(hwnd, IDC_TITLE,
     1939                                "Compiling files to .pyc...");
     1940
     1941                SetDlgItemText(hDialog, IDC_INFO, "Loading python...");
     1942                hPython = LoadPythonDll(pythondll);
     1943                if (hPython) {
     1944                    errors = compile_filelist(hPython, FALSE);
     1945                    FreeLibrary(hPython);
     1946                }
     1947                /* Compilation errors are intentionally ignored:
     1948                * Python2.0 contains a bug which will result
     1949                * in sys.path containing garbage under certain
     1950                * circumstances, and an error message will only
     1951                * confuse the user.
     1952                */
     1953            }
     1954            if (success && pyo_compile) {
     1955                int errors;
     1956                HINSTANCE hPython;
     1957                SetDlgItemText(hwnd, IDC_TITLE,
     1958                                "Compiling files to .pyo...");
     1959
     1960                SetDlgItemText(hDialog, IDC_INFO, "Loading python...");
     1961                hPython = LoadPythonDll(pythondll);
     1962                if (hPython) {
     1963                    errors = compile_filelist(hPython, TRUE);
     1964                    FreeLibrary(hPython);
     1965                }
     1966                /* Errors ignored: see above */
     1967            }
     1968
     1969
     1970            break;
     1971
     1972        case PSN_RESET:
     1973            break;
     1974
     1975        default:
     1976            break;
     1977        }
     1978    }
     1979    return 0;
    19801980}
    19811981
     
    19841984FinishedDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    19851985{
    1986         LPNMHDR lpnm;
    1987 
    1988         switch (msg) {
    1989         case WM_INITDIALOG:
    1990                 if (hBitmap)
    1991                         SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE,
    1992                                            IMAGE_BITMAP, (LPARAM)hBitmap);
    1993                 if (!success)
    1994                         SetDlgItemText(hwnd, IDC_INFO, get_failure_reason());
    1995 
    1996                 /* async delay: will show the dialog box completely before
    1997                    the install_script is started */
    1998                 PostMessage(hwnd, WM_USER, 0, 0L);
    1999                 return TRUE;
    2000 
    2001         case WM_USER:
    2002 
    2003                 if (success && install_script && install_script[0]) {
    2004                         char fname[MAX_PATH];
    2005                         char *buffer;
    2006                         HCURSOR hCursor;
    2007                         int result;
    2008 
    2009                         char *argv[3] = {NULL, "-install", NULL};
    2010 
    2011                         SetDlgItemText(hwnd, IDC_TITLE,
    2012                                         "Please wait while running postinstall script...");
    2013                         strcpy(fname, python_dir);
    2014                         strcat(fname, "\\Scripts\\");
    2015                         strcat(fname, install_script);
    2016 
    2017                         if (logfile)
    2018                                 fprintf(logfile, "300 Run Script: [%s]%s\n", pythondll, fname);
    2019 
    2020                         hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
    2021 
    2022                         argv[0] = fname;
    2023 
    2024                         result = run_installscript(fname, 2, argv, &buffer);
    2025                         if (0 != result) {
    2026                                 fprintf(stderr, "*** run_installscript: internal error 0x%X ***\n", result);
    2027                         }
    2028                         if (buffer)
    2029                                 SetDlgItemText(hwnd, IDC_INFO, buffer);
    2030                         SetDlgItemText(hwnd, IDC_TITLE,
    2031                                         "Postinstall script finished.\n"
    2032                                         "Click the Finish button to exit the Setup wizard.");
    2033 
    2034                         free(buffer);
    2035                         SetCursor(hCursor);
    2036                         CloseLogfile();
    2037                 }
    2038 
    2039                 return TRUE;
    2040 
    2041         case WM_NOTIFY:
    2042                 lpnm = (LPNMHDR) lParam;
    2043 
    2044                 switch (lpnm->code) {
    2045                 case PSN_SETACTIVE: /* Enable the Finish button */
    2046                         PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH);
    2047                         break;
    2048 
    2049                 case PSN_WIZNEXT:
    2050                         break;
    2051 
    2052                 case PSN_WIZFINISH:
    2053                         break;
    2054 
    2055                 case PSN_RESET:
    2056                         break;
    2057                
    2058                 default:
    2059                         break;
    2060                 }
    2061         }
    2062         return 0;
     1986    LPNMHDR lpnm;
     1987
     1988    switch (msg) {
     1989    case WM_INITDIALOG:
     1990        if (hBitmap)
     1991            SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE,
     1992                               IMAGE_BITMAP, (LPARAM)hBitmap);
     1993        if (!success)
     1994            SetDlgItemText(hwnd, IDC_INFO, get_failure_reason());
     1995
     1996        /* async delay: will show the dialog box completely before
     1997           the install_script is started */
     1998        PostMessage(hwnd, WM_USER, 0, 0L);
     1999        return TRUE;
     2000
     2001    case WM_USER:
     2002
     2003        if (success && install_script && install_script[0]) {
     2004            char fname[MAX_PATH];
     2005            char *buffer;
     2006            HCURSOR hCursor;
     2007            int result;
     2008
     2009            char *argv[3] = {NULL, "-install", NULL};
     2010
     2011            SetDlgItemText(hwnd, IDC_TITLE,
     2012                            "Please wait while running postinstall script...");
     2013            strcpy(fname, python_dir);
     2014            strcat(fname, "\\Scripts\\");
     2015            strcat(fname, install_script);
     2016
     2017            if (logfile)
     2018                fprintf(logfile, "300 Run Script: [%s]%s\n", pythondll, fname);
     2019
     2020            hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
     2021
     2022            argv[0] = fname;
     2023
     2024            result = run_installscript(fname, 2, argv, &buffer);
     2025            if (0 != result) {
     2026                fprintf(stderr, "*** run_installscript: internal error 0x%X ***\n", result);
     2027            }
     2028            if (buffer)
     2029                SetDlgItemText(hwnd, IDC_INFO, buffer);
     2030            SetDlgItemText(hwnd, IDC_TITLE,
     2031                            "Postinstall script finished.\n"
     2032                            "Click the Finish button to exit the Setup wizard.");
     2033
     2034            free(buffer);
     2035            SetCursor(hCursor);
     2036            CloseLogfile();
     2037        }
     2038
     2039        return TRUE;
     2040
     2041    case WM_NOTIFY:
     2042        lpnm = (LPNMHDR) lParam;
     2043
     2044        switch (lpnm->code) {
     2045        case PSN_SETACTIVE: /* Enable the Finish button */
     2046            PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_FINISH);
     2047            break;
     2048
     2049        case PSN_WIZNEXT:
     2050            break;
     2051
     2052        case PSN_WIZFINISH:
     2053            break;
     2054
     2055        case PSN_RESET:
     2056            break;
     2057
     2058        default:
     2059            break;
     2060        }
     2061    }
     2062    return 0;
    20632063}
    20642064
    20652065void RunWizard(HWND hwnd)
    20662066{
    2067         PROPSHEETPAGE   psp =       {0};
    2068         HPROPSHEETPAGE  ahpsp[4] =  {0};
    2069         PROPSHEETHEADER psh =       {0};
    2070 
    2071         /* Display module information */
    2072         psp.dwSize =        sizeof(psp);
    2073         psp.dwFlags =       PSP_DEFAULT|PSP_HIDEHEADER;
    2074         psp.hInstance =     GetModuleHandle (NULL);
    2075         psp.lParam =        0;
    2076         psp.pfnDlgProc =    IntroDlgProc;
    2077         psp.pszTemplate =   MAKEINTRESOURCE(IDD_INTRO);
    2078 
    2079         ahpsp[0] =          CreatePropertySheetPage(&psp);
    2080 
    2081         /* Select python version to use */
    2082         psp.dwFlags =       PSP_DEFAULT|PSP_HIDEHEADER;
    2083         psp.pszTemplate =       MAKEINTRESOURCE(IDD_SELECTPYTHON);
    2084         psp.pfnDlgProc =        SelectPythonDlgProc;
    2085 
    2086         ahpsp[1] =              CreatePropertySheetPage(&psp);
    2087 
    2088         /* Install the files */
    2089         psp.dwFlags =       PSP_DEFAULT|PSP_HIDEHEADER;
    2090         psp.pszTemplate =       MAKEINTRESOURCE(IDD_INSTALLFILES);
    2091         psp.pfnDlgProc =        InstallFilesDlgProc;
    2092 
    2093         ahpsp[2] =              CreatePropertySheetPage(&psp);
    2094 
    2095         /* Show success or failure */
    2096         psp.dwFlags =           PSP_DEFAULT|PSP_HIDEHEADER;
    2097         psp.pszTemplate =       MAKEINTRESOURCE(IDD_FINISHED);
    2098         psp.pfnDlgProc =        FinishedDlgProc;
    2099 
    2100         ahpsp[3] =              CreatePropertySheetPage(&psp);
    2101 
    2102         /* Create the property sheet */
    2103         psh.dwSize =            sizeof(psh);
    2104         psh.hInstance =         GetModuleHandle(NULL);
    2105         psh.hwndParent =        hwnd;
    2106         psh.phpage =            ahpsp;
    2107         psh.dwFlags =           PSH_WIZARD/*97*//*|PSH_WATERMARK|PSH_HEADER*/;
    2108                 psh.pszbmWatermark =    NULL;
    2109                 psh.pszbmHeader =       NULL;
    2110                 psh.nStartPage =        0;
    2111                 psh.nPages =            4;
    2112 
    2113                 PropertySheet(&psh);
     2067    PROPSHEETPAGE   psp =       {0};
     2068    HPROPSHEETPAGE  ahpsp[4] =  {0};
     2069    PROPSHEETHEADER psh =       {0};
     2070
     2071    /* Display module information */
     2072    psp.dwSize =        sizeof(psp);
     2073    psp.dwFlags =       PSP_DEFAULT|PSP_HIDEHEADER;
     2074    psp.hInstance =     GetModuleHandle (NULL);
     2075    psp.lParam =        0;
     2076    psp.pfnDlgProc =    IntroDlgProc;
     2077    psp.pszTemplate =   MAKEINTRESOURCE(IDD_INTRO);
     2078
     2079    ahpsp[0] =          CreatePropertySheetPage(&psp);
     2080
     2081    /* Select python version to use */
     2082    psp.dwFlags =       PSP_DEFAULT|PSP_HIDEHEADER;
     2083    psp.pszTemplate =       MAKEINTRESOURCE(IDD_SELECTPYTHON);
     2084    psp.pfnDlgProc =        SelectPythonDlgProc;
     2085
     2086    ahpsp[1] =              CreatePropertySheetPage(&psp);
     2087
     2088    /* Install the files */
     2089    psp.dwFlags =           PSP_DEFAULT|PSP_HIDEHEADER;
     2090    psp.pszTemplate =       MAKEINTRESOURCE(IDD_INSTALLFILES);
     2091    psp.pfnDlgProc =        InstallFilesDlgProc;
     2092
     2093    ahpsp[2] =              CreatePropertySheetPage(&psp);
     2094
     2095    /* Show success or failure */
     2096    psp.dwFlags =           PSP_DEFAULT|PSP_HIDEHEADER;
     2097    psp.pszTemplate =       MAKEINTRESOURCE(IDD_FINISHED);
     2098    psp.pfnDlgProc =        FinishedDlgProc;
     2099
     2100    ahpsp[3] =              CreatePropertySheetPage(&psp);
     2101
     2102    /* Create the property sheet */
     2103    psh.dwSize =            sizeof(psh);
     2104    psh.hInstance =         GetModuleHandle(NULL);
     2105    psh.hwndParent =        hwnd;
     2106    psh.phpage =            ahpsp;
     2107    psh.dwFlags =           PSH_WIZARD/*97*//*|PSH_WATERMARK|PSH_HEADER*/;
     2108        psh.pszbmWatermark =    NULL;
     2109        psh.pszbmHeader =       NULL;
     2110        psh.nStartPage =        0;
     2111        psh.nPages =            4;
     2112
     2113        PropertySheet(&psh);
    21142114}
    21152115
     
    21192119BOOL MyIsUserAnAdmin()
    21202120{
    2121         typedef BOOL (WINAPI *PFNIsUserAnAdmin)();
    2122         static PFNIsUserAnAdmin pfnIsUserAnAdmin = NULL;
    2123         HMODULE shell32;
    2124         // This function isn't guaranteed to be available (and it can't hurt
    2125         // to leave the library loaded)
    2126         if (0 == (shell32=LoadLibrary("shell32.dll")))
    2127                 return FALSE;
    2128         if (0 == (pfnIsUserAnAdmin=(PFNIsUserAnAdmin)GetProcAddress(shell32, "IsUserAnAdmin")))
    2129                 return FALSE;
    2130         return (*pfnIsUserAnAdmin)();
     2121    typedef BOOL (WINAPI *PFNIsUserAnAdmin)();
     2122    static PFNIsUserAnAdmin pfnIsUserAnAdmin = NULL;
     2123    HMODULE shell32;
     2124    // This function isn't guaranteed to be available (and it can't hurt
     2125    // to leave the library loaded)
     2126    if (0 == (shell32=LoadLibrary("shell32.dll")))
     2127        return FALSE;
     2128    if (0 == (pfnIsUserAnAdmin=(PFNIsUserAnAdmin)GetProcAddress(shell32, "IsUserAnAdmin")))
     2129        return FALSE;
     2130    return (*pfnIsUserAnAdmin)();
    21312131}
    21322132
     
    21402140BOOL NeedAutoUAC()
    21412141{
    2142         HKEY hk;
    2143         char key_name[80];
    2144         // no Python version info == we can't know yet.
    2145         if (target_version[0] == '\0')
    2146                 return FALSE;
    2147         // see how python is current installed
    2148         wsprintf(key_name,
    2149                         "Software\\Python\\PythonCore\\%s\\InstallPath",
    2150                         target_version);
    2151         if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    2152                                           key_name, 0, KEY_READ, &hk))
    2153                 return FALSE;
    2154         RegCloseKey(hk);
    2155         // Python is installed in HKLM - we must elevate.
    2156         return TRUE;
     2142    HKEY hk;
     2143    char key_name[80];
     2144    // no Python version info == we can't know yet.
     2145    if (target_version[0] == '\0')
     2146        return FALSE;
     2147    // see how python is current installed
     2148    wsprintf(key_name,
     2149                    "Software\\Python\\PythonCore\\%s\\InstallPath",
     2150                    target_version);
     2151    if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE,
     2152                                      key_name, 0, KEY_READ, &hk))
     2153        return FALSE;
     2154    RegCloseKey(hk);
     2155    // Python is installed in HKLM - we must elevate.
     2156    return TRUE;
    21572157}
    21582158
     
    21602160BOOL PlatformSupportsUAC()
    21612161{
    2162         // Note that win2k does seem to support ShellExecute with 'runas',
    2163         // but does *not* support IsUserAnAdmin - so we just pretend things
    2164         // only work on XP and later.
    2165         BOOL bIsWindowsXPorLater;
    2166         OSVERSIONINFO winverinfo;
    2167         winverinfo.dwOSVersionInfoSize = sizeof(winverinfo);
    2168         if (!GetVersionEx(&winverinfo))
    2169                 return FALSE; // something bad has gone wrong
    2170         bIsWindowsXPorLater =
     2162    // Note that win2k does seem to support ShellExecute with 'runas',
     2163    // but does *not* support IsUserAnAdmin - so we just pretend things
     2164    // only work on XP and later.
     2165    BOOL bIsWindowsXPorLater;
     2166    OSVERSIONINFO winverinfo;
     2167    winverinfo.dwOSVersionInfoSize = sizeof(winverinfo);
     2168    if (!GetVersionEx(&winverinfo))
     2169        return FALSE; // something bad has gone wrong
     2170    bIsWindowsXPorLater =
    21712171       ( (winverinfo.dwMajorVersion > 5) ||
    21722172       ( (winverinfo.dwMajorVersion == 5) && (winverinfo.dwMinorVersion >= 1) ));
    2173         return bIsWindowsXPorLater;
     2173    return bIsWindowsXPorLater;
    21742174}
    21752175
     
    21792179void SpawnUAC()
    21802180{
    2181         // interesting failure scenario that has been seen: initial executable
    2182         // runs from a network drive - but once elevated, that network share
    2183         // isn't seen, and ShellExecute fails with SE_ERR_ACCESSDENIED.
    2184         int ret = (int)ShellExecute(0, "runas", modulename, "", NULL,
    2185                                     SW_SHOWNORMAL);
    2186         if (ret <= 32) {
    2187                 char msg[128];
    2188                 wsprintf(msg, "Failed to start elevated process (ShellExecute returned %d)", ret);
    2189                 MessageBox(0, msg, "Setup", MB_OK | MB_ICONERROR);
    2190         }
     2181    // interesting failure scenario that has been seen: initial executable
     2182    // runs from a network drive - but once elevated, that network share
     2183    // isn't seen, and ShellExecute fails with SE_ERR_ACCESSDENIED.
     2184    int ret = (int)ShellExecute(0, "runas", modulename, "", NULL,
     2185                                SW_SHOWNORMAL);
     2186    if (ret <= 32) {
     2187        char msg[128];
     2188        wsprintf(msg, "Failed to start elevated process (ShellExecute returned %d)", ret);
     2189        MessageBox(0, msg, "Setup", MB_OK | MB_ICONERROR);
     2190    }
    21912191}
    21922192
    21932193int DoInstall(void)
    21942194{
    2195         char ini_buffer[4096];
    2196 
    2197         /* Read installation information */
    2198         GetPrivateProfileString("Setup", "title", "", ini_buffer,
    2199                                 sizeof(ini_buffer), ini_file);
    2200         unescape(title, ini_buffer, sizeof(title));
    2201 
    2202         GetPrivateProfileString("Setup", "info", "", ini_buffer,
    2203                                 sizeof(ini_buffer), ini_file);
    2204         unescape(info, ini_buffer, sizeof(info));
    2205 
    2206         GetPrivateProfileString("Setup", "build_info", "", build_info,
    2207                                 sizeof(build_info), ini_file);
    2208 
    2209         pyc_compile = GetPrivateProfileInt("Setup", "target_compile", 1,
    2210                                             ini_file);
    2211         pyo_compile = GetPrivateProfileInt("Setup", "target_optimize", 1,
    2212                                             ini_file);
    2213 
    2214         GetPrivateProfileString("Setup", "target_version", "",
    2215                                 target_version, sizeof(target_version),
    2216                                 ini_file);
    2217 
    2218         GetPrivateProfileString("metadata", "name", "",
    2219                                 meta_name, sizeof(meta_name),
    2220                                 ini_file);
    2221 
    2222         GetPrivateProfileString("Setup", "install_script", "",
    2223                                 install_script, sizeof(install_script),
    2224                                 ini_file);
    2225 
    2226         GetPrivateProfileString("Setup", "user_access_control", "",
    2227                                 user_access_control, sizeof(user_access_control), ini_file);
    2228 
    2229         // See if we need to do the Vista UAC magic.
    2230         if (strcmp(user_access_control, "force")==0) {
    2231                 if (PlatformSupportsUAC() && !MyIsUserAnAdmin()) {
    2232                         SpawnUAC();
    2233                         return 0;
    2234                 }
    2235                 // already admin - keep going
    2236         } else if (strcmp(user_access_control, "auto")==0) {
    2237                 // Check if it looks like we need UAC control, based
    2238                 // on how Python itself was installed.
    2239                 if (PlatformSupportsUAC() && !MyIsUserAnAdmin() && NeedAutoUAC()) {
    2240                         SpawnUAC();
    2241                         return 0;
    2242                 }
    2243         } else {
    2244                 // display a warning about unknown values - only the developer
    2245                 // of the extension will see it (until they fix it!)
    2246                 if (user_access_control[0] && strcmp(user_access_control, "none") != 0) {
    2247                         MessageBox(GetFocus(), "Bad user_access_control value", "oops", MB_OK);
    2248                 // nothing to do.
    2249                 }
    2250         }
    2251 
    2252         hwndMain = CreateBackground(title);
    2253 
    2254         RunWizard(hwndMain);
    2255 
    2256         /* Clean up */
    2257         UnmapViewOfFile(arc_data);
    2258         if (ini_file)
    2259                 DeleteFile(ini_file);
    2260 
    2261         if (hBitmap)
    2262                 DeleteObject(hBitmap);
    2263 
    2264         return 0;
     2195    char ini_buffer[4096];
     2196
     2197    /* Read installation information */
     2198    GetPrivateProfileString("Setup", "title", "", ini_buffer,
     2199                            sizeof(ini_buffer), ini_file);
     2200    unescape(title, ini_buffer, sizeof(title));
     2201
     2202    GetPrivateProfileString("Setup", "info", "", ini_buffer,
     2203                            sizeof(ini_buffer), ini_file);
     2204    unescape(info, ini_buffer, sizeof(info));
     2205
     2206    GetPrivateProfileString("Setup", "build_info", "", build_info,
     2207                            sizeof(build_info), ini_file);
     2208
     2209    pyc_compile = GetPrivateProfileInt("Setup", "target_compile", 1,
     2210                                        ini_file);
     2211    pyo_compile = GetPrivateProfileInt("Setup", "target_optimize", 1,
     2212                                        ini_file);
     2213
     2214    GetPrivateProfileString("Setup", "target_version", "",
     2215                            target_version, sizeof(target_version),
     2216                            ini_file);
     2217
     2218    GetPrivateProfileString("metadata", "name", "",
     2219                            meta_name, sizeof(meta_name),
     2220                            ini_file);
     2221
     2222    GetPrivateProfileString("Setup", "install_script", "",
     2223                            install_script, sizeof(install_script),
     2224                            ini_file);
     2225
     2226    GetPrivateProfileString("Setup", "user_access_control", "",
     2227                            user_access_control, sizeof(user_access_control), ini_file);
     2228
     2229    // See if we need to do the Vista UAC magic.
     2230    if (strcmp(user_access_control, "force")==0) {
     2231        if (PlatformSupportsUAC() && !MyIsUserAnAdmin()) {
     2232            SpawnUAC();
     2233            return 0;
     2234        }
     2235        // already admin - keep going
     2236    } else if (strcmp(user_access_control, "auto")==0) {
     2237        // Check if it looks like we need UAC control, based
     2238        // on how Python itself was installed.
     2239        if (PlatformSupportsUAC() && !MyIsUserAnAdmin() && NeedAutoUAC()) {
     2240            SpawnUAC();
     2241            return 0;
     2242        }
     2243    } else {
     2244        // display a warning about unknown values - only the developer
     2245        // of the extension will see it (until they fix it!)
     2246        if (user_access_control[0] && strcmp(user_access_control, "none") != 0) {
     2247            MessageBox(GetFocus(), "Bad user_access_control value", "oops", MB_OK);
     2248        // nothing to do.
     2249        }
     2250    }
     2251
     2252    hwndMain = CreateBackground(title);
     2253
     2254    RunWizard(hwndMain);
     2255
     2256    /* Clean up */
     2257    UnmapViewOfFile(arc_data);
     2258    if (ini_file)
     2259        DeleteFile(ini_file);
     2260
     2261    if (hBitmap)
     2262        DeleteObject(hBitmap);
     2263
     2264    return 0;
    22652265}
    22662266
     
    22692269static int compare(const void *p1, const void *p2)
    22702270{
    2271         return strcmp(*(char **)p2, *(char **)p1);
     2271    return strcmp(*(char **)p2, *(char **)p1);
    22722272}
    22732273
     
    22832283void remove_exe(void)
    22842284{
    2285         char exename[_MAX_PATH];
    2286         char batname[_MAX_PATH];
    2287         FILE *fp;
    2288         STARTUPINFO si;
    2289         PROCESS_INFORMATION pi;
    2290 
    2291         GetModuleFileName(NULL, exename, sizeof(exename));
    2292         sprintf(batname, "%s.bat", exename);
    2293         fp = fopen(batname, "w");
    2294         fprintf(fp, ":Repeat\n");
    2295         fprintf(fp, "del \"%s\"\n", exename);
    2296         fprintf(fp, "if exist \"%s\" goto Repeat\n", exename);
    2297         fprintf(fp, "del \"%s\"\n", batname);
    2298         fclose(fp);
    2299    
    2300         ZeroMemory(&si, sizeof(si));
    2301         si.cb = sizeof(si);
    2302         si.dwFlags = STARTF_USESHOWWINDOW;
    2303         si.wShowWindow = SW_HIDE;
    2304         if (CreateProcess(NULL,
    2305                           batname,
    2306                           NULL,
    2307                           NULL,
    2308                           FALSE,
    2309                           CREATE_SUSPENDED | IDLE_PRIORITY_CLASS,
    2310                           NULL,
    2311                           "\\",
    2312                           &si,
    2313                           &pi)) {
    2314                 SetThreadPriority(pi.hThread, THREAD_PRIORITY_IDLE);
    2315                 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
    2316                 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
    2317                 CloseHandle(pi.hProcess);
    2318                 ResumeThread(pi.hThread);
    2319                 CloseHandle(pi.hThread);
    2320         }
     2285    char exename[_MAX_PATH];
     2286    char batname[_MAX_PATH];
     2287    FILE *fp;
     2288    STARTUPINFO si;
     2289    PROCESS_INFORMATION pi;
     2290
     2291    GetModuleFileName(NULL, exename, sizeof(exename));
     2292    sprintf(batname, "%s.bat", exename);
     2293    fp = fopen(batname, "w");
     2294    fprintf(fp, ":Repeat\n");
     2295    fprintf(fp, "del \"%s\"\n", exename);
     2296    fprintf(fp, "if exist \"%s\" goto Repeat\n", exename);
     2297    fprintf(fp, "del \"%s\"\n", batname);
     2298    fclose(fp);
     2299
     2300    ZeroMemory(&si, sizeof(si));
     2301    si.cb = sizeof(si);
     2302    si.dwFlags = STARTF_USESHOWWINDOW;
     2303    si.wShowWindow = SW_HIDE;
     2304    if (CreateProcess(NULL,
     2305                      batname,
     2306                      NULL,
     2307                      NULL,
     2308                      FALSE,
     2309                      CREATE_SUSPENDED | IDLE_PRIORITY_CLASS,
     2310                      NULL,
     2311                      "\\",
     2312                      &si,
     2313                      &pi)) {
     2314        SetThreadPriority(pi.hThread, THREAD_PRIORITY_IDLE);
     2315        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
     2316        SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
     2317        CloseHandle(pi.hProcess);
     2318        ResumeThread(pi.hThread);
     2319        CloseHandle(pi.hThread);
     2320    }
    23212321}
    23222322
    23232323void DeleteRegistryKey(char *string)
    23242324{
    2325         char *keyname;
    2326         char *subkeyname;
    2327         char *delim;
    2328         HKEY hKey;
    2329         long result;
    2330         char *line;
    2331 
    2332         line = strdup(string); /* so we can change it */
    2333 
    2334         keyname = strchr(line, '[');
    2335         if (!keyname)
    2336                 return;
    2337         ++keyname;
    2338 
    2339         subkeyname = strchr(keyname, ']');
    2340         if (!subkeyname)
    2341                 return;
    2342         *subkeyname++='\0';
    2343         delim = strchr(subkeyname, '\n');
    2344         if (delim)
    2345                 *delim = '\0';
    2346 
    2347         result = RegOpenKeyEx(hkey_root,
    2348                               keyname,
    2349                               0,
    2350                               KEY_WRITE,
    2351                               &hKey);
    2352    
    2353         if (result != ERROR_SUCCESS)
    2354                 MessageBox(GetFocus(), string, "Could not open key", MB_OK);
    2355         else {
    2356                 result = RegDeleteKey(hKey, subkeyname);
    2357                 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND)
    2358                         MessageBox(GetFocus(), string, "Could not delete key", MB_OK);
    2359                 RegCloseKey(hKey);
    2360         }
    2361         free(line);
     2325    char *keyname;
     2326    char *subkeyname;
     2327    char *delim;
     2328    HKEY hKey;
     2329    long result;
     2330    char *line;
     2331
     2332    line = strdup(string); /* so we can change it */
     2333
     2334    keyname = strchr(line, '[');
     2335    if (!keyname)
     2336        return;
     2337    ++keyname;
     2338
     2339    subkeyname = strchr(keyname, ']');
     2340    if (!subkeyname)
     2341        return;
     2342    *subkeyname++='\0';
     2343    delim = strchr(subkeyname, '\n');
     2344    if (delim)
     2345        *delim = '\0';
     2346
     2347    result = RegOpenKeyEx(hkey_root,
     2348                          keyname,
     2349                          0,
     2350                          KEY_WRITE,
     2351                          &hKey);
     2352
     2353    if (result != ERROR_SUCCESS)
     2354        MessageBox(GetFocus(), string, "Could not open key", MB_OK);
     2355    else {
     2356        result = RegDeleteKey(hKey, subkeyname);
     2357        if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND)
     2358            MessageBox(GetFocus(), string, "Could not delete key", MB_OK);
     2359        RegCloseKey(hKey);
     2360    }
     2361    free(line);
    23622362}
    23632363
    23642364void DeleteRegistryValue(char *string)
    23652365{
    2366         char *keyname;
    2367         char *valuename;
    2368         char *value;
    2369         HKEY hKey;
    2370         long result;
    2371         char *line;
    2372 
    2373         line = strdup(string); /* so we can change it */
     2366    char *keyname;
     2367    char *valuename;
     2368    char *value;
     2369    HKEY hKey;
     2370    long result;
     2371    char *line;
     2372
     2373    line = strdup(string); /* so we can change it */
    23742374
    23752375/* Format is 'Reg DB Value: [key]name=value' */
    2376         keyname = strchr(line, '[');
    2377         if (!keyname)
    2378                 return;
    2379         ++keyname;
    2380         valuename = strchr(keyname, ']');
    2381         if (!valuename)
    2382                 return;
    2383         *valuename++ = '\0';
    2384         value = strchr(valuename, '=');
    2385         if (!value)
    2386                 return;
    2387 
    2388         *value++ = '\0';
    2389 
    2390         result = RegOpenKeyEx(hkey_root,
    2391                               keyname,
    2392                               0,
    2393                               KEY_WRITE,
    2394                               &hKey);
    2395         if (result != ERROR_SUCCESS)
    2396                 MessageBox(GetFocus(), string, "Could not open key", MB_OK);
    2397         else {
    2398                 result = RegDeleteValue(hKey, valuename);
    2399                 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND)
    2400                         MessageBox(GetFocus(), string, "Could not delete value", MB_OK);
    2401                 RegCloseKey(hKey);
    2402         }
    2403         free(line);
     2376    keyname = strchr(line, '[');
     2377    if (!keyname)
     2378        return;
     2379    ++keyname;
     2380    valuename = strchr(keyname, ']');
     2381    if (!valuename)
     2382        return;
     2383    *valuename++ = '\0';
     2384    value = strchr(valuename, '=');
     2385    if (!value)
     2386        return;
     2387
     2388    *value++ = '\0';
     2389
     2390    result = RegOpenKeyEx(hkey_root,
     2391                          keyname,
     2392                          0,
     2393                          KEY_WRITE,
     2394                          &hKey);
     2395    if (result != ERROR_SUCCESS)
     2396        MessageBox(GetFocus(), string, "Could not open key", MB_OK);
     2397    else {
     2398        result = RegDeleteValue(hKey, valuename);
     2399        if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND)
     2400            MessageBox(GetFocus(), string, "Could not delete value", MB_OK);
     2401        RegCloseKey(hKey);
     2402    }
     2403    free(line);
    24042404}
    24052405
    24062406BOOL MyDeleteFile(char *line)
    24072407{
    2408         char *pathname = strchr(line, ':');
    2409         if (!pathname)
    2410                 return FALSE;
    2411         ++pathname;
    2412         while (isspace(*pathname))
    2413                 ++pathname;
    2414         return DeleteFile(pathname);
     2408    char *pathname = strchr(line, ':');
     2409    if (!pathname)
     2410        return FALSE;
     2411    ++pathname;
     2412    while (isspace(*pathname))
     2413        ++pathname;
     2414    return DeleteFile(pathname);
    24152415}
    24162416
    24172417BOOL MyRemoveDirectory(char *line)
    24182418{
    2419         char *pathname = strchr(line, ':');
    2420         if (!pathname)
    2421                 return FALSE;
    2422         ++pathname;
    2423         while (isspace(*pathname))
    2424                 ++pathname;
    2425         return RemoveDirectory(pathname);
     2419    char *pathname = strchr(line, ':');
     2420    if (!pathname)
     2421        return FALSE;
     2422    ++pathname;
     2423    while (isspace(*pathname))
     2424        ++pathname;
     2425    return RemoveDirectory(pathname);
    24262426}
    24272427
    24282428BOOL Run_RemoveScript(char *line)
    24292429{
    2430         char *dllname;
    2431         char *scriptname;
    2432         static char lastscript[MAX_PATH];
     2430    char *dllname;
     2431    char *scriptname;
     2432    static char lastscript[MAX_PATH];
    24332433
    24342434/* Format is 'Run Scripts: [pythondll]scriptname' */
    24352435/* XXX Currently, pythondll carries no path!!! */
    2436         dllname = strchr(line, '[');
    2437         if (!dllname)
    2438                 return FALSE;
    2439         ++dllname;
    2440         scriptname = strchr(dllname, ']');
    2441         if (!scriptname)
    2442                 return FALSE;
    2443         *scriptname++ = '\0';
    2444         /* this function may be called more than one time with the same
    2445            script, only run it one time */
    2446         if (strcmp(lastscript, scriptname)) {
    2447                 char *argv[3] = {NULL, "-remove", NULL};
    2448                 char *buffer = NULL;
    2449 
    2450                 argv[0] = scriptname;
    2451 
    2452                 if (0 != run_installscript(scriptname, 2, argv, &buffer))
    2453                         fprintf(stderr, "*** Could not run installation script ***");
    2454 
    2455                 if (buffer && buffer[0])
    2456                         MessageBox(GetFocus(), buffer, "uninstall-script", MB_OK);
    2457                 free(buffer);
    2458 
    2459                 strcpy(lastscript, scriptname);
    2460         }
    2461         return TRUE;
     2436    dllname = strchr(line, '[');
     2437    if (!dllname)
     2438        return FALSE;
     2439    ++dllname;
     2440    scriptname = strchr(dllname, ']');
     2441    if (!scriptname)
     2442        return FALSE;
     2443    *scriptname++ = '\0';
     2444    /* this function may be called more than one time with the same
     2445       script, only run it one time */
     2446    if (strcmp(lastscript, scriptname)) {
     2447        char *argv[3] = {NULL, "-remove", NULL};
     2448        char *buffer = NULL;
     2449
     2450        argv[0] = scriptname;
     2451
     2452        if (0 != run_installscript(scriptname, 2, argv, &buffer))
     2453            fprintf(stderr, "*** Could not run installation script ***");
     2454
     2455        if (buffer && buffer[0])
     2456            MessageBox(GetFocus(), buffer, "uninstall-script", MB_OK);
     2457        free(buffer);
     2458
     2459        strcpy(lastscript, scriptname);
     2460    }
     2461    return TRUE;
    24622462}
    24632463
    24642464int DoUninstall(int argc, char **argv)
    24652465{
    2466         FILE *logfile;
    2467         char buffer[4096];
    2468         int nLines = 0;
    2469         int i;
    2470         char *cp;
    2471         int nFiles = 0;
    2472         int nDirs = 0;
    2473         int nErrors = 0;
    2474         char **lines;
    2475         int lines_buffer_size = 10;
    2476    
    2477         if (argc != 3) {
    2478                 MessageBox(NULL,
    2479                            "Wrong number of args",
    2480                            NULL,
    2481                            MB_OK);
    2482                 return 1; /* Error */
    2483         }
    2484         if (strcmp(argv[1], "-u")) {
    2485                 MessageBox(NULL,
    2486                            "2. arg is not -u",
    2487                            NULL,
    2488                            MB_OK);
    2489                 return 1; /* Error */
    2490         }
    2491 
    2492         logfile = fopen(argv[2], "r");
    2493         if (!logfile) {
    2494                 MessageBox(NULL,
    2495                            "could not open logfile",
    2496                            NULL,
    2497                            MB_OK);
    2498                 return 1; /* Error */
    2499         }
    2500    
    2501         lines = (char **)malloc(sizeof(char *) * lines_buffer_size);
    2502         if (!lines)
    2503                 return SystemError(0, "Out of memory");
    2504 
    2505         /* Read the whole logfile, realloacting the buffer */
    2506         while (fgets(buffer, sizeof(buffer), logfile)) {
    2507                 int len = strlen(buffer);
    2508                 /* remove trailing white space */
    2509                 while (isspace(buffer[len-1]))
    2510                         len -= 1;
    2511                 buffer[len] = '\0';
    2512                 lines[nLines++] = strdup(buffer);
    2513                 if (nLines >= lines_buffer_size) {
    2514                         lines_buffer_size += 10;
    2515                         lines = (char **)realloc(lines,
    2516                                                 sizeof(char *) * lines_buffer_size);
    2517                         if (!lines)
    2518                                 return SystemError(0, "Out of memory");
    2519                 }
    2520         }
    2521         fclose(logfile);
    2522 
    2523         /* Sort all the lines, so that highest 3-digit codes are first */
    2524         qsort(&lines[0], nLines, sizeof(char *),
    2525               compare);
    2526 
    2527         if (IDYES != MessageBox(NULL,
    2528                                 "Are you sure you want to remove\n"
    2529                                 "this package from your computer?",
    2530                                 "Please confirm",
    2531                                 MB_YESNO | MB_ICONQUESTION))
    2532                 return 0;
    2533 
    2534         hkey_root = HKEY_LOCAL_MACHINE;
    2535         cp = "";
    2536         for (i = 0; i < nLines; ++i) {
    2537                 /* Ignore duplicate lines */
    2538                 if (strcmp(cp, lines[i])) {
    2539                         int ign;
    2540                         cp = lines[i];
    2541                         /* Parse the lines */
    2542                         if (2 == sscanf(cp, "%d Root Key: %s", &ign, &buffer)) {
    2543                                 if (strcmp(buffer, "HKEY_CURRENT_USER")==0)
    2544                                         hkey_root = HKEY_CURRENT_USER;
    2545                                 else {
    2546                                         // HKLM - check they have permissions.
    2547                                         if (!HasLocalMachinePrivs()) {
    2548                                                 MessageBox(GetFocus(),
    2549                                                            "You do not seem to have sufficient access rights\n"
    2550                                                            "on this machine to uninstall this software",
    2551                                                            NULL,
    2552                                                            MB_OK | MB_ICONSTOP);
    2553                                                 return 1; /* Error */
    2554                                         }
    2555                                 }
    2556                         } else if (2 == sscanf(cp, "%d Made Dir: %s", &ign, &buffer)) {
    2557                                 if (MyRemoveDirectory(cp))
    2558                                         ++nDirs;
    2559                                 else {
    2560                                         int code = GetLastError();
    2561                                         if (code != 2 && code != 3) { /* file or path not found */
    2562                                                 ++nErrors;
    2563                                         }
    2564                                 }
    2565                         } else if (2 == sscanf(cp, "%d File Copy: %s", &ign, &buffer)) {
    2566                                 if (MyDeleteFile(cp))
    2567                                         ++nFiles;
    2568                                 else {
    2569                                         int code = GetLastError();
    2570                                         if (code != 2 && code != 3) { /* file or path not found */
    2571                                                 ++nErrors;
    2572                                         }
    2573                                 }
    2574                         } else if (2 == sscanf(cp, "%d File Overwrite: %s", &ign, &buffer)) {
    2575                                 if (MyDeleteFile(cp))
    2576                                         ++nFiles;
    2577                                 else {
    2578                                         int code = GetLastError();
    2579                                         if (code != 2 && code != 3) { /* file or path not found */
    2580                                                 ++nErrors;
    2581                                         }
    2582                                 }
    2583                         } else if (2 == sscanf(cp, "%d Reg DB Key: %s", &ign, &buffer)) {
    2584                                 DeleteRegistryKey(cp);
    2585                         } else if (2 == sscanf(cp, "%d Reg DB Value: %s", &ign, &buffer)) {
    2586                                 DeleteRegistryValue(cp);
    2587                         } else if (2 == sscanf(cp, "%d Run Script: %s", &ign, &buffer)) {
    2588                                 Run_RemoveScript(cp);
    2589                         }
    2590                 }
    2591         }
    2592 
    2593         if (DeleteFile(argv[2])) {
    2594                 ++nFiles;
    2595         } else {
    2596                 ++nErrors;
    2597                 SystemError(GetLastError(), argv[2]);
    2598         }
    2599         if (nErrors)
    2600                 wsprintf(buffer,
    2601                         "%d files and %d directories removed\n"
    2602                         "%d files or directories could not be removed",
    2603                         nFiles, nDirs, nErrors);
    2604         else
    2605                 wsprintf(buffer, "%d files and %d directories removed",
    2606                         nFiles, nDirs);
    2607         MessageBox(NULL, buffer, "Uninstall Finished!",
    2608                    MB_OK | MB_ICONINFORMATION);
    2609         remove_exe();
    2610         return 0;
     2466    FILE *logfile;
     2467    char buffer[4096];
     2468    int nLines = 0;
     2469    int i;
     2470    char *cp;
     2471    int nFiles = 0;
     2472    int nDirs = 0;
     2473    int nErrors = 0;
     2474    char **lines;
     2475    int lines_buffer_size = 10;
     2476
     2477    if (argc != 3) {
     2478        MessageBox(NULL,
     2479                   "Wrong number of args",
     2480                   NULL,
     2481                   MB_OK);
     2482        return 1; /* Error */
     2483    }
     2484    if (strcmp(argv[1], "-u")) {
     2485        MessageBox(NULL,
     2486                   "2. arg is not -u",
     2487                   NULL,
     2488                   MB_OK);
     2489        return 1; /* Error */
     2490    }
     2491
     2492    logfile = fopen(argv[2], "r");
     2493    if (!logfile) {
     2494        MessageBox(NULL,
     2495                   "could not open logfile",
     2496                   NULL,
     2497                   MB_OK);
     2498        return 1; /* Error */
     2499    }
     2500
     2501    lines = (char **)malloc(sizeof(char *) * lines_buffer_size);
     2502    if (!lines)
     2503        return SystemError(0, "Out of memory");
     2504
     2505    /* Read the whole logfile, realloacting the buffer */
     2506    while (fgets(buffer, sizeof(buffer), logfile)) {
     2507        int len = strlen(buffer);
     2508        /* remove trailing white space */
     2509        while (isspace(buffer[len-1]))
     2510            len -= 1;
     2511        buffer[len] = '\0';
     2512        lines[nLines++] = strdup(buffer);
     2513        if (nLines >= lines_buffer_size) {
     2514            lines_buffer_size += 10;
     2515            lines = (char **)realloc(lines,
     2516                                    sizeof(char *) * lines_buffer_size);
     2517            if (!lines)
     2518                return SystemError(0, "Out of memory");
     2519        }
     2520    }
     2521    fclose(logfile);
     2522
     2523    /* Sort all the lines, so that highest 3-digit codes are first */
     2524    qsort(&lines[0], nLines, sizeof(char *),
     2525          compare);
     2526
     2527    if (IDYES != MessageBox(NULL,
     2528                            "Are you sure you want to remove\n"
     2529                            "this package from your computer?",
     2530                            "Please confirm",
     2531                            MB_YESNO | MB_ICONQUESTION))
     2532        return 0;
     2533
     2534    hkey_root = HKEY_LOCAL_MACHINE;
     2535    cp = "";
     2536    for (i = 0; i < nLines; ++i) {
     2537        /* Ignore duplicate lines */
     2538        if (strcmp(cp, lines[i])) {
     2539            int ign;
     2540            cp = lines[i];
     2541            /* Parse the lines */
     2542            if (2 == sscanf(cp, "%d Root Key: %s", &ign, &buffer)) {
     2543                if (strcmp(buffer, "HKEY_CURRENT_USER")==0)
     2544                    hkey_root = HKEY_CURRENT_USER;
     2545                else {
     2546                    // HKLM - check they have permissions.
     2547                    if (!HasLocalMachinePrivs()) {
     2548                        MessageBox(GetFocus(),
     2549                                   "You do not seem to have sufficient access rights\n"
     2550                                   "on this machine to uninstall this software",
     2551                                   NULL,
     2552                                   MB_OK | MB_ICONSTOP);
     2553                        return 1; /* Error */
     2554                    }
     2555                }
     2556            } else if (2 == sscanf(cp, "%d Made Dir: %s", &ign, &buffer)) {
     2557                if (MyRemoveDirectory(cp))
     2558                    ++nDirs;
     2559                else {
     2560                    int code = GetLastError();
     2561                    if (code != 2 && code != 3) { /* file or path not found */
     2562                        ++nErrors;
     2563                    }
     2564                }
     2565            } else if (2 == sscanf(cp, "%d File Copy: %s", &ign, &buffer)) {
     2566                if (MyDeleteFile(cp))
     2567                    ++nFiles;
     2568                else {
     2569                    int code = GetLastError();
     2570                    if (code != 2 && code != 3) { /* file or path not found */
     2571                        ++nErrors;
     2572                    }
     2573                }
     2574            } else if (2 == sscanf(cp, "%d File Overwrite: %s", &ign, &buffer)) {
     2575                if (MyDeleteFile(cp))
     2576                    ++nFiles;
     2577                else {
     2578                    int code = GetLastError();
     2579                    if (code != 2 && code != 3) { /* file or path not found */
     2580                        ++nErrors;
     2581                    }
     2582                }
     2583            } else if (2 == sscanf(cp, "%d Reg DB Key: %s", &ign, &buffer)) {
     2584                DeleteRegistryKey(cp);
     2585            } else if (2 == sscanf(cp, "%d Reg DB Value: %s", &ign, &buffer)) {
     2586                DeleteRegistryValue(cp);
     2587            } else if (2 == sscanf(cp, "%d Run Script: %s", &ign, &buffer)) {
     2588                Run_RemoveScript(cp);
     2589            }
     2590        }
     2591    }
     2592
     2593    if (DeleteFile(argv[2])) {
     2594        ++nFiles;
     2595    } else {
     2596        ++nErrors;
     2597        SystemError(GetLastError(), argv[2]);
     2598    }
     2599    if (nErrors)
     2600        wsprintf(buffer,
     2601                "%d files and %d directories removed\n"
     2602                "%d files or directories could not be removed",
     2603                nFiles, nDirs, nErrors);
     2604    else
     2605        wsprintf(buffer, "%d files and %d directories removed",
     2606                nFiles, nDirs);
     2607    MessageBox(NULL, buffer, "Uninstall Finished!",
     2608               MB_OK | MB_ICONINFORMATION);
     2609    remove_exe();
     2610    return 0;
    26112611}
    26122612
    26132613int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
    2614                     LPSTR lpszCmdLine, INT nCmdShow)
    2615 {
    2616         extern int __argc;
    2617         extern char **__argv;
    2618         char *basename;
    2619 
    2620         GetModuleFileName(NULL, modulename, sizeof(modulename));
    2621 
    2622         /* Map the executable file to memory */
    2623         arc_data = MapExistingFile(modulename, &arc_size);
    2624         if (!arc_data) {
    2625                 SystemError(GetLastError(), "Could not open archive");
    2626                 return 1;
    2627         }
    2628 
    2629         /* OK. So this program can act as installer (self-extracting
    2630         * zip-file, or as uninstaller when started with '-u logfile'
    2631         * command line flags.
    2632         *
    2633         * The installer is usually started without command line flags,
    2634         * and the uninstaller is usually started with the '-u logfile'
    2635         * flag. What to do if some innocent user double-clicks the
    2636         * exe-file?
    2637         * The following implements a defensive strategy...
    2638         */
    2639 
    2640         /* Try to extract the configuration data into a temporary file */
    2641         if (ExtractInstallData(arc_data, arc_size, &exe_size,
    2642                                &ini_file, &pre_install_script))
    2643                 return DoInstall();
    2644 
    2645         if (!ini_file && __argc > 1) {
    2646                 return DoUninstall(__argc, __argv);
    2647         }
    2648 
    2649 
    2650         basename = strrchr(modulename, '\\');
    2651         if (basename)
    2652                 ++basename;
    2653 
    2654         /* Last guess about the purpose of this program */
    2655         if (basename && (0 == strncmp(basename, "Remove", 6)))
    2656                 SystemError(0, "This program is normally started by windows");
    2657         else
    2658                 SystemError(0, "Setup program invalid or damaged");
    2659         return 1;
    2660 }
     2614                    LPSTR lpszCmdLine, INT nCmdShow)
     2615{
     2616    extern int __argc;
     2617    extern char **__argv;
     2618    char *basename;
     2619
     2620    GetModuleFileName(NULL, modulename, sizeof(modulename));
     2621
     2622    /* Map the executable file to memory */
     2623    arc_data = MapExistingFile(modulename, &arc_size);
     2624    if (!arc_data) {
     2625        SystemError(GetLastError(), "Could not open archive");
     2626        return 1;
     2627    }
     2628
     2629    /* OK. So this program can act as installer (self-extracting
     2630    * zip-file, or as uninstaller when started with '-u logfile'
     2631    * command line flags.
     2632    *
     2633    * The installer is usually started without command line flags,
     2634    * and the uninstaller is usually started with the '-u logfile'
     2635    * flag. What to do if some innocent user double-clicks the
     2636    * exe-file?
     2637    * The following implements a defensive strategy...
     2638    */
     2639
     2640    /* Try to extract the configuration data into a temporary file */
     2641    if (ExtractInstallData(arc_data, arc_size, &exe_size,
     2642                           &ini_file, &pre_install_script))
     2643        return DoInstall();
     2644
     2645    if (!ini_file && __argc > 1) {
     2646        return DoUninstall(__argc, __argv);
     2647    }
     2648
     2649
     2650    basename = strrchr(modulename, '\\');
     2651    if (basename)
     2652        ++basename;
     2653
     2654    /* Last guess about the purpose of this program */
     2655    if (basename && (0 == strncmp(basename, "Remove", 6)))
     2656        SystemError(0, "This program is normally started by windows");
     2657    else
     2658        SystemError(0, "Setup program invalid or damaged");
     2659    return 1;
     2660}
Note: See TracChangeset for help on using the changeset viewer.