~pythonregexp2.7/python/issue2636

« back to all changes in this revision

Viewing changes to PC/bdist_wininst/install.c

  • Committer: Jeffrey C. "The TimeHorse" Jacobs
  • Date: 2008-05-24 16:05:21 UTC
  • mfrom: (39021.1.401 Regexp-2.6)
  • Revision ID: darklord@timehorse.com-20080524160521-1xenj7p6u3wb89et
Merged in changes from the latest python source snapshot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
133
133
char install_script[MAX_PATH];
134
134
char *pre_install_script; /* run before we install a single file */
135
135
 
 
136
char user_access_control[10]; // one of 'auto', 'force', otherwise none.
136
137
 
137
138
int py_major, py_minor;         /* Python version selected for installation */
138
139
 
344
345
};
345
346
typedef struct PyMethodDef PyMethodDef;
346
347
 
 
348
// XXX - all of these are potentially fragile!  We load and unload
 
349
// the Python DLL multiple times - so storing functions pointers 
 
350
// is dangerous (although things *look* OK at present)
 
351
// Better might be to roll prepare_script_environment() into
 
352
// LoadPythonDll(), and create a new UnloadPythonDLL() which also
 
353
// clears the global pointers.
347
354
void *(*g_Py_BuildValue)(char *, ...);
348
355
int (*g_PyArg_ParseTuple)(PyObject *, char *, ...);
 
356
PyObject * (*g_PyLong_FromVoidPtr)(void *);
349
357
 
350
358
PyObject *g_PyExc_ValueError;
351
359
PyObject *g_PyExc_OSError;
597
605
 
598
606
static PyObject *GetRootHKey(PyObject *self)
599
607
{
600
 
        return g_Py_BuildValue("l", hkey_root);
 
608
        return g_PyLong_FromVoidPtr(hkey_root);
601
609
}
602
610
 
603
611
#define METH_VARARGS 0x0001
631
639
                 "SOFTWARE\\Python\\PythonCore\\%d.%d\\InstallPath",
632
640
                 py_major, py_minor);
633
641
        if (ERROR_SUCCESS != RegQueryValue(HKEY_CURRENT_USER, subkey_name,
634
 
                                           fullpath, &size))
 
642
                                           fullpath, &size) &&
 
643
            ERROR_SUCCESS != RegQueryValue(HKEY_LOCAL_MACHINE, subkey_name,
 
644
                                           fullpath, &size))
635
645
                return NULL;
636
646
        strcat(fullpath, "\\");
637
647
        strcat(fullpath, fname);
648
658
        DECLPROC(hPython, PyObject *, Py_BuildValue, (char *, ...));
649
659
        DECLPROC(hPython, int, PyArg_ParseTuple, (PyObject *, char *, ...));
650
660
        DECLPROC(hPython, PyObject *, PyErr_Format, (PyObject *, char *));
 
661
        DECLPROC(hPython, PyObject *, PyLong_FromVoidPtr, (void *));
651
662
        if (!PyImport_ImportModule || !PyObject_GetAttrString || 
652
663
            !PyObject_SetAttrString || !PyCFunction_New)
653
664
                return 1;
667
678
        g_Py_BuildValue = Py_BuildValue;
668
679
        g_PyArg_ParseTuple = PyArg_ParseTuple;
669
680
        g_PyErr_Format = PyErr_Format;
 
681
        g_PyLong_FromVoidPtr = PyLong_FromVoidPtr;
670
682
 
671
683
        return 0;
672
684
}
777
789
 
778
790
        hPython = LoadPythonDll(pythondll);
779
791
        if (!hPython) {
780
 
                set_failure_reason("Can't load Python for pre-install script");
 
792
                char reason[128];
 
793
                wsprintf(reason, "Can't load Python for pre-install script (%d)", GetLastError());
 
794
                set_failure_reason(reason);
781
795
                return -1;
782
796
        }
783
797
        rc = do_run_simple_script(hPython, script);
2073
2087
                PropertySheet(&psh);
2074
2088
}
2075
2089
 
 
2090
// subtly different from HasLocalMachinePrivs(), in that after executing
 
2091
// an 'elevated' process, we expect this to return TRUE - but there is no
 
2092
// such implication for HasLocalMachinePrivs
 
2093
BOOL MyIsUserAnAdmin()
 
2094
{
 
2095
        typedef BOOL (WINAPI *PFNIsUserAnAdmin)();
 
2096
        static PFNIsUserAnAdmin pfnIsUserAnAdmin = NULL;
 
2097
        HMODULE shell32;
 
2098
        // This function isn't guaranteed to be available (and it can't hurt 
 
2099
        // to leave the library loaded)
 
2100
        if (0 == (shell32=LoadLibrary("shell32.dll")))
 
2101
                return FALSE;
 
2102
        if (0 == (pfnIsUserAnAdmin=(PFNIsUserAnAdmin)GetProcAddress(shell32, "IsUserAnAdmin")))
 
2103
                return FALSE;
 
2104
        return (*pfnIsUserAnAdmin)();
 
2105
}
 
2106
 
 
2107
// Some magic for Vista's UAC.  If there is a target_version, and
 
2108
// if that target version is installed in the registry under
 
2109
// HKLM, and we are not current administrator, then
 
2110
// re-execute ourselves requesting elevation.
 
2111
// Split into 2 functions - "should we elevate" and "spawn elevated"
 
2112
 
 
2113
// Returns TRUE if we should spawn an elevated child
 
2114
BOOL NeedAutoUAC()
 
2115
{
 
2116
        HKEY hk;
 
2117
        char key_name[80];
 
2118
        OSVERSIONINFO winverinfo;
 
2119
        winverinfo.dwOSVersionInfoSize = sizeof(winverinfo);
 
2120
        // If less than XP, then we can't do it (and its not necessary).
 
2121
        if (!GetVersionEx(&winverinfo) || winverinfo.dwMajorVersion < 5)
 
2122
                return FALSE;
 
2123
        // no Python version info == we can't know yet.
 
2124
        if (target_version[0] == '\0')
 
2125
                return FALSE;
 
2126
        // see how python is current installed
 
2127
        wsprintf(key_name,
 
2128
                         "Software\\Python\\PythonCore\\%s\\InstallPath",
 
2129
                         target_version);
 
2130
        if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
 
2131
                                          key_name, 0, KEY_READ, &hk))
 
2132
                return FALSE;
 
2133
        RegCloseKey(hk);
 
2134
        // Python is installed in HKLM - we must elevate.
 
2135
        return TRUE;
 
2136
}
 
2137
 
 
2138
// Spawn ourself as an elevated application.  On failure, a message is
 
2139
// displayed to the user - but this app will always terminate, even
 
2140
// on error.
 
2141
void SpawnUAC()
 
2142
{
 
2143
        // interesting failure scenario that has been seen: initial executable
 
2144
        // runs from a network drive - but once elevated, that network share
 
2145
        // isn't seen, and ShellExecute fails with SE_ERR_ACCESSDENIED.
 
2146
        int ret = (int)ShellExecute(0, "runas", modulename, "", NULL, 
 
2147
                                    SW_SHOWNORMAL);
 
2148
        if (ret <= 32) {
 
2149
                char msg[128];
 
2150
                wsprintf(msg, "Failed to start elevated process (ShellExecute returned %d)", ret);
 
2151
                MessageBox(0, msg, "Setup", MB_OK | MB_ICONERROR);
 
2152
        }
 
2153
}
 
2154
 
2076
2155
int DoInstall(void)
2077
2156
{
2078
2157
        char ini_buffer[4096];
2106
2185
                                 install_script, sizeof(install_script),
2107
2186
                                 ini_file);
2108
2187
 
 
2188
        GetPrivateProfileString("Setup", "user_access_control", "",
 
2189
                                 user_access_control, sizeof(user_access_control), ini_file);
 
2190
 
 
2191
        // See if we need to do the Vista UAC magic.
 
2192
        if (strcmp(user_access_control, "force")==0) {
 
2193
                if (!MyIsUserAnAdmin()) {
 
2194
                        SpawnUAC();
 
2195
                        return 0;
 
2196
                }
 
2197
                // already admin - keep going
 
2198
        } else if (strcmp(user_access_control, "auto")==0) {
 
2199
                // Check if it looks like we need UAC control, based
 
2200
                // on how Python itself was installed.
 
2201
                if (!MyIsUserAnAdmin() && NeedAutoUAC()) {
 
2202
                        SpawnUAC();
 
2203
                        return 0;
 
2204
                }
 
2205
        } else {
 
2206
                // display a warning about unknown values - only the developer
 
2207
                // of the extension will see it (until they fix it!)
 
2208
                if (user_access_control[0] && strcmp(user_access_control, "none") != 0) {
 
2209
                        MessageBox(GetFocus(), "Bad user_access_control value", "oops", MB_OK);
 
2210
                // nothing to do.
 
2211
                }
 
2212
        }
2109
2213
 
2110
2214
        hwndMain = CreateBackground(title);
2111
2215