summaryrefslogtreecommitdiffstats
path: root/Python
Commit message (Collapse)AuthorAgeFilesLines
...
| | * Merged revisions 78872 via svnmerge fromVictor Stinner2010-03-212-18/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r78872 | victor.stinner | 2010-03-12 15:45:56 +0100 (ven., 12 mars 2010) | 12 lines Merged revisions 78826 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78826 | victor.stinner | 2010-03-10 23:30:19 +0100 (mer., 10 mars 2010) | 5 lines Issue #3137: Don't ignore errors at startup, especially a keyboard interrupt (SIGINT). If an error occurs while importing the site module, the error is printed and Python exits. Initialize the GIL before importing the site module. ........ ................
| | * Merged revisions 78875 via svnmerge fromVictor Stinner2010-03-212-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r78875 | victor.stinner | 2010-03-12 18:00:41 +0100 (ven., 12 mars 2010) | 5 lines Issue #6697: use %U format instead of _PyUnicode_AsString(), because _PyUnicode_AsString() was not checked for error (NULL). The unicode string is no more truncated to 200 or 400 *bytes*. ........
| | * Merged revisions 78766 via svnmerge fromBenjamin Peterson2010-03-071-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r78766 | benjamin.peterson | 2010-03-07 11:10:51 -0600 (Sun, 07 Mar 2010) | 1 line prevent generator finalization from invalidating sys.exc_info() #7173 ........
| | * Merged revisions 78639 via svnmerge fromVictor Stinner2010-03-031-5/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r78639 | victor.stinner | 2010-03-04 00:28:07 +0100 (jeu., 04 mars 2010) | 10 lines Merged revisions 78638 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78638 | victor.stinner | 2010-03-04 00:20:25 +0100 (jeu., 04 mars 2010) | 3 lines Issue #7544: Preallocate thread memory before creating the thread to avoid a fatal error in low memory condition. ........ ................
| | * Merged revisions 78622 via svnmerge fromFlorent Xicluna2010-03-031-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r78622 | florent.xicluna | 2010-03-03 12:54:54 +0100 (mer, 03 mar 2010) | 9 lines Merged revisions 78620 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78620 | florent.xicluna | 2010-03-03 12:49:53 +0100 (mer, 03 mar 2010) | 2 lines Revert a nonexistent docstring typo, r42805. ........ ................
| | * Merged revisions 78505-78506 via svnmerge fromBenjamin Peterson2010-02-271-8/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r78505 | benjamin.peterson | 2010-02-27 11:40:01 -0600 (Sat, 27 Feb 2010) | 1 line only accept AttributeError as indicating no __prepare__ attribute on a metaclass, allowing lookup errors to propogate ........ r78506 | benjamin.peterson | 2010-02-27 11:41:13 -0600 (Sat, 27 Feb 2010) | 1 line check PyDict_New() for error ........
| | * Merged revisions 77722 via svnmerge fromMark Dickinson2010-01-242-69/+122
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77722 | mark.dickinson | 2010-01-24 10:16:29 +0000 (Sun, 24 Jan 2010) | 23 lines Merged revisions 77691,77698,77713-77714 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77691 | mark.dickinson | 2010-01-22 16:18:09 +0000 (Fri, 22 Jan 2010) | 1 line Correct typo in comment. ........ r77698 | mark.dickinson | 2010-01-22 17:04:07 +0000 (Fri, 22 Jan 2010) | 3 lines Issue #7743: Fix a potential incorrect rounding bug in dtoa.c (2nd bug in issue 7743). ........ r77713 | mark.dickinson | 2010-01-23 20:48:56 +0000 (Sat, 23 Jan 2010) | 3 lines Issue #7743: Add checks for zero inputs to the lshift and mult functions; this fixes the first bug described in issue #7743. ........ r77714 | mark.dickinson | 2010-01-23 21:25:53 +0000 (Sat, 23 Jan 2010) | 1 line dtoa.c fix from upstream that fixes incorrectly rounded results for certain subnormals that are also halfway cases. ........ ................
| | * Merged revisions 77670 via svnmerge fromMark Dickinson2010-01-211-185/+239
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77670 | mark.dickinson | 2010-01-21 19:51:08 +0000 (Thu, 21 Jan 2010) | 24 lines Merged revisions 77614-77616,77663 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77614 | mark.dickinson | 2010-01-20 17:36:31 +0000 (Wed, 20 Jan 2010) | 5 lines Various dtoa.c cleanups. 1. Despagghetify _Py_dg_strtod parsing code and exit points. 2. Simplify bigcomp comparison loop. 3. Don't set ERANGE on _Py_dg_strtod underflow (it was set inconsistently anyway). 4. Remove unused dsign field from BCinfo struct. ........ r77615 | mark.dickinson | 2010-01-20 18:02:41 +0000 (Wed, 20 Jan 2010) | 1 line Don't try to put a value into a NULL pointer. ........ r77616 | mark.dickinson | 2010-01-20 21:23:25 +0000 (Wed, 20 Jan 2010) | 1 line Additional explanatory comments for _Py_dg_strtod. ........ r77663 | mark.dickinson | 2010-01-21 17:02:53 +0000 (Thu, 21 Jan 2010) | 1 line Additional testcases for strtod. ........ ................
| | * Merged revisions 77590 via svnmerge fromMark Dickinson2010-01-171-0/+98
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77590 | mark.dickinson | 2010-01-17 21:02:55 +0000 (Sun, 17 Jan 2010) | 14 lines Merged revisions 77589 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77589 | mark.dickinson | 2010-01-17 20:57:56 +0000 (Sun, 17 Jan 2010) | 7 lines Issue #7632: When Py_USING_MEMORY_DEBUGGER is defined, disable the private memory allocation scheme in dtoa.c, along with a piece of code that caches powers of 5 for future use. This makes it easier to detect dtoa.c memory leaks with Valgrind or similar tools. Patch by Stefan Krah. ........ ................
| | * Merged revisions 77579 via svnmerge fromMark Dickinson2010-01-171-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77579 | mark.dickinson | 2010-01-17 14:39:12 +0000 (Sun, 17 Jan 2010) | 9 lines Merged revisions 77578 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77578 | mark.dickinson | 2010-01-17 13:37:57 +0000 (Sun, 17 Jan 2010) | 2 lines Issue #7632: Fix a memory leak in _Py_dg_strtod. ........ ................
| | * Merged revisions 77535 via svnmerge fromMark Dickinson2010-01-161-37/+89
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77535 | mark.dickinson | 2010-01-16 18:10:25 +0000 (Sat, 16 Jan 2010) | 21 lines Merged revisions 77519,77530,77533 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77519 | mark.dickinson | 2010-01-16 10:44:00 +0000 (Sat, 16 Jan 2010) | 5 lines Issue #7632: Fix a serious wrong output bug for string -> float conversion. Also remove some now unused variables, and add comments clarifying the possible outputs of the parsing section of _Py_dg_strtod. Thanks Eric Smith for reviewing. ........ r77530 | mark.dickinson | 2010-01-16 17:57:49 +0000 (Sat, 16 Jan 2010) | 3 lines Issue #7632: Fix one more case of incorrect rounding for str -> float conversion (see bug 5 in the issue tracker). ........ r77533 | mark.dickinson | 2010-01-16 18:06:17 +0000 (Sat, 16 Jan 2010) | 1 line Fix multiple uses of variable 'L' in _Py_dg_strtod, where one use requires an unsigned long and the other a signed long. See also r77421. ........ ................
| | * Merged revisions 77494 via svnmerge fromMark Dickinson2010-01-141-113/+145
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77494 | mark.dickinson | 2010-01-14 15:37:49 +0000 (Thu, 14 Jan 2010) | 41 lines Merged revisions 77477-77478,77481-77483,77490-77493 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77477 | mark.dickinson | 2010-01-13 18:21:53 +0000 (Wed, 13 Jan 2010) | 1 line Add comments explaining the role of the bigcomp function in dtoa.c. ........ r77478 | mark.dickinson | 2010-01-13 19:02:37 +0000 (Wed, 13 Jan 2010) | 1 line Clarify that sulp expects a nonnegative input, but that +0.0 is fine. ........ r77481 | mark.dickinson | 2010-01-13 20:55:03 +0000 (Wed, 13 Jan 2010) | 1 line Simplify and annotate the bigcomp function, removing unused special cases. ........ r77482 | mark.dickinson | 2010-01-13 22:15:53 +0000 (Wed, 13 Jan 2010) | 1 line Fix buggy comparison: LHS of comparison was being treated as unsigned. ........ r77483 | mark.dickinson | 2010-01-13 22:20:10 +0000 (Wed, 13 Jan 2010) | 1 line More dtoa.c cleanup; remove the need for bc.dplen, bc.dp0 and bc.dp1. ........ r77490 | mark.dickinson | 2010-01-14 13:02:36 +0000 (Thu, 14 Jan 2010) | 1 line Fix off-by-one error introduced in r77483. I have a test for this, but it currently fails due to a different dtoa.c bug; I'll add the test once that bug is fixed. ........ r77491 | mark.dickinson | 2010-01-14 13:14:49 +0000 (Thu, 14 Jan 2010) | 1 line Issue 7632: fix a dtoa.c bug (bug 6) causing incorrect rounding. Tests to follow. ........ r77492 | mark.dickinson | 2010-01-14 14:40:20 +0000 (Thu, 14 Jan 2010) | 1 line Issue 7632: fix incorrect rounding for long input strings with values very close to a power of 2. (See Bug 4 in the tracker discussion.) ........ r77493 | mark.dickinson | 2010-01-14 15:22:33 +0000 (Thu, 14 Jan 2010) | 1 line Issue #7632: add tests for bugs fixed so far. ........ ................
| | * Merged revisions 77452 via svnmerge fromMark Dickinson2010-01-121-36/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77452 | mark.dickinson | 2010-01-12 23:04:19 +0000 (Tue, 12 Jan 2010) | 23 lines Merged revisions 77410,77421,77450-77451 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77410 | mark.dickinson | 2010-01-10 13:06:31 +0000 (Sun, 10 Jan 2010) | 1 line Remove unused BCinfo fields and an unused macro. ........ r77421 | mark.dickinson | 2010-01-11 17:15:13 +0000 (Mon, 11 Jan 2010) | 1 line Change a variable type to avoid signed overflow; replace repeated '19999' constant by a define. ........ r77450 | mark.dickinson | 2010-01-12 22:23:56 +0000 (Tue, 12 Jan 2010) | 4 lines Issue #7632: Fix a problem with _Py_dg_strtod that could lead to crashes in debug builds, for certain long numeric strings corresponding to subnormal values. ........ r77451 | mark.dickinson | 2010-01-12 22:55:51 +0000 (Tue, 12 Jan 2010) | 2 lines Issue #7632: Fix a bug in dtoa.c that could lead to incorrectly-rounded results. ........ ................
| | * Merged revisions 77304 via svnmerge fromMark Dickinson2010-01-041-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77304 | mark.dickinson | 2010-01-04 21:33:31 +0000 (Mon, 04 Jan 2010) | 9 lines Merged revisions 77302 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77302 | mark.dickinson | 2010-01-04 21:32:02 +0000 (Mon, 04 Jan 2010) | 1 line Fix typo in comment. ........ ................
| | * Merged revisions 77206-77207 via svnmerge fromEzio Melotti2010-01-011-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77206 | benjamin.peterson | 2010-01-01 06:47:54 +0200 (Fri, 01 Jan 2010) | 9 lines Merged revisions 77203 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77203 | benjamin.peterson | 2009-12-31 22:00:55 -0600 (Thu, 31 Dec 2009) | 1 line update copyright year ........ ................ r77207 | benjamin.peterson | 2010-01-01 06:49:25 +0200 (Fri, 01 Jan 2010) | 9 lines Merged revisions 77204 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77204 | ezio.melotti | 2009-12-31 22:16:42 -0600 (Thu, 31 Dec 2009) | 1 line more copyright year updates ........ ................
| | * Merged revisions 77161 via svnmerge fromBenjamin Peterson2009-12-301-5/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r77161 | benjamin.peterson | 2009-12-30 13:44:54 -0600 (Wed, 30 Dec 2009) | 12 lines Merged revisions 77157 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77157 | benjamin.peterson | 2009-12-30 13:34:10 -0600 (Wed, 30 Dec 2009) | 5 lines check if the attribute is set before deleting it with T_OBJECT_EX (fixes #7604) Also, add a note to the docs about the better behavior of T_OBJECT_EX as compared to T_OBJECT. ........ ................
| | * Merged revisions 76902 via svnmerge fromMark Dickinson2009-12-191-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r76902 | mark.dickinson | 2009-12-19 21:19:35 +0000 (Sat, 19 Dec 2009) | 1 line Fix typo (reported by terlop on IRC) ........
| | * Merged revisions 76776 via svnmerge fromBenjamin Peterson2009-12-132-90/+460
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r76776 | benjamin.peterson | 2009-12-12 19:23:39 -0600 (Sat, 12 Dec 2009) | 25 lines Merged revisions 76534,76538,76628,76701,76774 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76534 | martin.v.loewis | 2009-11-26 02:42:05 -0600 (Thu, 26 Nov 2009) | 2 lines Fix typo. ........ r76538 | georg.brandl | 2009-11-26 14:48:25 -0600 (Thu, 26 Nov 2009) | 1 line #7400: typo. ........ r76628 | andrew.kuchling | 2009-12-02 08:27:11 -0600 (Wed, 02 Dec 2009) | 1 line Markup fixes ........ r76701 | andrew.kuchling | 2009-12-07 20:37:05 -0600 (Mon, 07 Dec 2009) | 1 line Typo fix; grammar fix ........ r76774 | benjamin.peterson | 2009-12-12 18:54:15 -0600 (Sat, 12 Dec 2009) | 1 line account for PyObject_IsInstance's new ability to fail ........ ................
| | * Merged revisions 76646 via svnmerge fromMark Dickinson2009-12-031-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r76646 | mark.dickinson | 2009-12-03 10:59:46 +0000 (Thu, 03 Dec 2009) | 6 lines Issue #7414: Add missing 'case 'C'' to skipitem() in getargs.c. This was causing PyArg_ParseTupleAndKeywords(args, kwargs, "|CC", ...) to fail with a RuntimeError. Thanks Case Van Horsen for tracking down the source of this error. ........
| | * Merged revisions 76577 via svnmerge fromMark Dickinson2009-11-281-26/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r76577 | mark.dickinson | 2009-11-28 16:38:16 +0000 (Sat, 28 Nov 2009) | 12 lines Merged revisions 76575 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76575 | mark.dickinson | 2009-11-28 16:32:27 +0000 (Sat, 28 Nov 2009) | 5 lines Issue #1678380: When distinguishing between -0.0 and 0.0 in compiler_add_o, use copysign instead of examining the first and last bytes of the double. The latter method fails for little-endian ARM, OABI, where doubles are little-endian but with the words swapped. ........ ................
| | * Merged revisions 76573 via svnmerge fromAntoine Pitrou2009-11-281-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r76573 | antoine.pitrou | 2009-11-28 17:12:28 +0100 (sam., 28 nov. 2009) | 3 lines Issue #4486: When an exception has an explicit cause, do not print its implicit context too. ........
| | * Merged revisions 76425 via svnmerge fromBenjamin Peterson2009-11-201-3/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r76425 | benjamin.peterson | 2009-11-19 19:19:41 -0600 (Thu, 19 Nov 2009) | 13 lines Merged revisions 76423-76424 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76423 | benjamin.peterson | 2009-11-19 19:15:53 -0600 (Thu, 19 Nov 2009) | 1 line provide line number for lambdas ........ r76424 | benjamin.peterson | 2009-11-19 19:16:58 -0600 (Thu, 19 Nov 2009) | 1 line genexps have linenos ........ ................
| | * Merged revisions 75984 via svnmerge fromMark Dickinson2009-10-311-1/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r75984 | mark.dickinson | 2009-10-31 10:18:44 +0000 (Sat, 31 Oct 2009) | 12 lines Merged revisions 75982 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75982 | mark.dickinson | 2009-10-31 10:11:28 +0000 (Sat, 31 Oct 2009) | 5 lines Issue #6603: Fix --with-tsc build failures on x86-64 that resulted from a gcc inline assembler peculiarity. (gcc's "A" constraint apparently means 'rax or rdx' in 64-bit mode, not edx:eax or rdx:rax as one might expect.) ........ ................
| | * Merged revisions 75928 via svnmerge fromBenjamin Peterson2009-10-291-9/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r75928 | benjamin.peterson | 2009-10-28 16:59:39 -0500 (Wed, 28 Oct 2009) | 5 lines in wide builds, avoid storing high unicode characters from source code with surrogates This is accomplished by decoding with utf-32 instead of utf-16 on all builds. The patch is by Adam Olsen. ........
| | * Merged revisions 75797 via svnmerge fromGeorg Brandl2009-10-271-5/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://svn.python.org/python/branches/py3k ................ r75797 | georg.brandl | 2009-10-27 16:28:25 +0100 (Di, 27 Okt 2009) | 129 lines Merged revisions 75365,75394,75402-75403,75418,75459,75484,75592-75596,75600,75602-75607,75610-75613,75616-75617,75623,75627,75640,75647,75696,75795 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75365 | georg.brandl | 2009-10-11 22:16:16 +0200 (So, 11 Okt 2009) | 1 line Fix broken links found by "make linkcheck". scipy.org seems to be done right now, so I could not verify links going there. ........ r75394 | georg.brandl | 2009-10-13 20:10:59 +0200 (Di, 13 Okt 2009) | 1 line Fix markup. ........ r75402 | georg.brandl | 2009-10-14 17:51:48 +0200 (Mi, 14 Okt 2009) | 1 line #7125: fix typo. ........ r75403 | georg.brandl | 2009-10-14 17:57:46 +0200 (Mi, 14 Okt 2009) | 1 line #7126: os.environ changes *do* take effect in subprocesses started with os.system(). ........ r75418 | georg.brandl | 2009-10-14 20:48:32 +0200 (Mi, 14 Okt 2009) | 1 line #7116: str.join() takes an iterable. ........ r75459 | georg.brandl | 2009-10-17 10:57:43 +0200 (Sa, 17 Okt 2009) | 1 line Fix refleaks in _ctypes PyCSimpleType_New, which fixes the refleak seen in test___all__. ........ r75484 | georg.brandl | 2009-10-18 09:58:12 +0200 (So, 18 Okt 2009) | 1 line Fix missing word. ........ r75592 | georg.brandl | 2009-10-22 09:05:48 +0200 (Do, 22 Okt 2009) | 1 line Fix punctuation. ........ r75593 | georg.brandl | 2009-10-22 09:06:49 +0200 (Do, 22 Okt 2009) | 1 line Revert unintended change. ........ r75594 | georg.brandl | 2009-10-22 09:56:02 +0200 (Do, 22 Okt 2009) | 1 line Fix markup. ........ r75595 | georg.brandl | 2009-10-22 09:56:56 +0200 (Do, 22 Okt 2009) | 1 line Fix duplicate target. ........ r75596 | georg.brandl | 2009-10-22 10:05:04 +0200 (Do, 22 Okt 2009) | 1 line Add a new directive marking up implementation details and start using it. ........ r75600 | georg.brandl | 2009-10-22 13:01:46 +0200 (Do, 22 Okt 2009) | 1 line Make it more robust. ........ r75602 | georg.brandl | 2009-10-22 13:28:06 +0200 (Do, 22 Okt 2009) | 1 line Document new directive. ........ r75603 | georg.brandl | 2009-10-22 13:28:23 +0200 (Do, 22 Okt 2009) | 1 line Allow short form with text as argument. ........ r75604 | georg.brandl | 2009-10-22 13:36:50 +0200 (Do, 22 Okt 2009) | 1 line Fix stylesheet for multi-paragraph impl-details. ........ r75605 | georg.brandl | 2009-10-22 13:48:10 +0200 (Do, 22 Okt 2009) | 1 line Use "impl-detail" directive where applicable. ........ r75606 | georg.brandl | 2009-10-22 17:00:06 +0200 (Do, 22 Okt 2009) | 1 line #6324: membership test tries iteration via __iter__. ........ r75607 | georg.brandl | 2009-10-22 17:04:09 +0200 (Do, 22 Okt 2009) | 1 line #7088: document new functions in signal as Unix-only. ........ r75610 | georg.brandl | 2009-10-22 17:27:24 +0200 (Do, 22 Okt 2009) | 1 line Reorder __slots__ fine print and add a clarification. ........ r75611 | georg.brandl | 2009-10-22 17:42:32 +0200 (Do, 22 Okt 2009) | 1 line #7035: improve docs of the various <method>_errors() functions, and give them docstrings. ........ r75612 | georg.brandl | 2009-10-22 17:52:15 +0200 (Do, 22 Okt 2009) | 1 line #7156: document curses as Unix-only. ........ r75613 | georg.brandl | 2009-10-22 17:54:35 +0200 (Do, 22 Okt 2009) | 1 line #6977: getopt does not support optional option arguments. ........ r75616 | georg.brandl | 2009-10-22 18:17:05 +0200 (Do, 22 Okt 2009) | 1 line Add proper references. ........ r75617 | georg.brandl | 2009-10-22 18:20:55 +0200 (Do, 22 Okt 2009) | 1 line Make printout margin important. ........ r75623 | georg.brandl | 2009-10-23 10:14:44 +0200 (Fr, 23 Okt 2009) | 1 line #7188: fix optionxform() docs. ........ r75627 | fred.drake | 2009-10-23 15:04:51 +0200 (Fr, 23 Okt 2009) | 2 lines add further note about what's passed to optionxform ........ r75640 | neil.schemenauer | 2009-10-23 21:58:17 +0200 (Fr, 23 Okt 2009) | 2 lines Improve some docstrings in the 'warnings' module. ........ r75647 | georg.brandl | 2009-10-24 12:04:19 +0200 (Sa, 24 Okt 2009) | 1 line Fix markup. ........ r75696 | georg.brandl | 2009-10-25 21:25:43 +0100 (So, 25 Okt 2009) | 1 line Fix a demo. ........ r75795 | georg.brandl | 2009-10-27 16:10:22 +0100 (Di, 27 Okt 2009) | 1 line Fix a strange mis-edit. ........ ................
| | * Merged revisions 75441 via svnmerge fromMark Dickinson2009-10-272-3/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r75441 | mark.dickinson | 2009-10-15 20:55:18 +0100 (Thu, 15 Oct 2009) | 9 lines Merged revisions 75440 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75440 | mark.dickinson | 2009-10-15 18:45:39 +0100 (Thu, 15 Oct 2009) | 1 line Allow core Python build to succeed under WITHOUT_COMPLEX. The module build stage still fails. ........ ................
| | * Merged revisions 75571,75576-75577 via svnmerge fromAntoine Pitrou2009-10-201-0/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r75571 | antoine.pitrou | 2009-10-20 23:52:47 +0200 (mar., 20 oct. 2009) | 11 lines Merged revisions 75570 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75570 | antoine.pitrou | 2009-10-20 23:29:37 +0200 (mar., 20 oct. 2009) | 6 lines Issue #1722344: threading._shutdown() is now called in Py_Finalize(), which fixes the problem of some exceptions being thrown at shutdown when the interpreter is killed. Patch by Adam Olsen. ........ ................ r75576 | antoine.pitrou | 2009-10-21 00:02:29 +0200 (mer., 21 oct. 2009) | 10 lines Merged revisions 75574 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75574 | antoine.pitrou | 2009-10-20 23:59:25 +0200 (mar., 20 oct. 2009) | 4 lines Test wouldn't work in debug mode. We probably need a function in test_support to handle this. ........ ................ r75577 | antoine.pitrou | 2009-10-21 00:05:38 +0200 (mer., 21 oct. 2009) | 3 lines Another futile error in the previous commit :-( ................
| | * Merged revisions 75246 via svnmerge fromBenjamin Peterson2009-10-041-19/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r75246 | benjamin.peterson | 2009-10-04 15:32:25 -0500 (Sun, 04 Oct 2009) | 29 lines Merged revisions 74841 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74841 | thomas.wouters | 2009-09-16 14:55:54 -0500 (Wed, 16 Sep 2009) | 23 lines Fix issue #1590864, multiple threads and fork() can cause deadlocks, by acquiring the import lock around fork() calls. This prevents other threads from having that lock while the fork happens, and is the recommended way of dealing with such issues. There are two other locks we care about, the GIL and the Thread Local Storage lock. The GIL is obviously held when calling Python functions like os.fork(), and the TLS lock is explicitly reallocated instead, while also deleting now-orphaned TLS data. This only fixes calls to os.fork(), not extension modules or embedding programs calling C's fork() directly. Solving that requires a new set of API functions, and possibly a rewrite of the Python/thread_*.c mess. Add a warning explaining the problem to the documentation in the mean time. This also changes behaviour a little on AIX. Before, AIX (but only AIX) was getting the import lock reallocated, seemingly to avoid this very same problem. This is not the right approach, because the import lock is a re-entrant one, and reallocating would do the wrong thing when forking while holding the import lock. Will backport to 2.6, minus the tiny AIX behaviour change. ........ ................
| | * Merged revisions 75224 via svnmerge fromBenjamin Peterson2009-10-031-0/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r75224 | benjamin.peterson | 2009-10-03 15:27:13 -0500 (Sat, 03 Oct 2009) | 9 lines Merged revisions 75223 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75223 | benjamin.peterson | 2009-10-03 15:23:24 -0500 (Sat, 03 Oct 2009) | 1 line #7050 fix a SystemError when using tuple unpacking and augmented assignment ........ ................
| | * Merged revisions 75145 via svnmerge fromMark Dickinson2009-09-291-3/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@www.python.org/python/branches/py3k ................ r75145 | mark.dickinson | 2009-09-29 20:21:35 +0100 (Tue, 29 Sep 2009) | 10 lines Merged revisions 75141 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75141 | mark.dickinson | 2009-09-29 20:01:06 +0100 (Tue, 29 Sep 2009) | 3 lines Issue #7019: Unmarshalling of bad long data could produce unnormalized PyLongs. Raise ValueError instead. ........ ................
| | * Merged revisions 74062 via svnmerge fromGeorg Brandl2009-08-131-10/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://svn.python.org/python/branches/py3k ................ r74062 | alexandre.vassalotti | 2009-07-17 13:43:26 +0200 (Fr, 17 Jul 2009) | 37 lines Merged revisions 73665,73693,73704-73705,73707,73712-73713,73824 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73665 | alexandre.vassalotti | 2009-06-28 21:01:51 -0400 (Sun, 28 Jun 2009) | 2 lines Update docstrings for sys.getdlopenflags() and sys.setdlopenflags(). ........ r73693 | jesse.noller | 2009-06-29 14:20:34 -0400 (Mon, 29 Jun 2009) | 1 line Bug 5906: add a documentation note for unix daemons vs. multiprocessing daemons ........ r73704 | georg.brandl | 2009-06-30 12:15:43 -0400 (Tue, 30 Jun 2009) | 1 line #6376: fix copy-n-paste oversight. ........ r73705 | georg.brandl | 2009-06-30 12:17:28 -0400 (Tue, 30 Jun 2009) | 1 line #6374: add a bit of explanation about shell=True on Windows. ........ r73707 | georg.brandl | 2009-06-30 12:35:11 -0400 (Tue, 30 Jun 2009) | 1 line #6371: fix link targets. ........ r73712 | ezio.melotti | 2009-06-30 18:51:06 -0400 (Tue, 30 Jun 2009) | 1 line Fixed defaultTestCase -> defaultTestResult ........ r73713 | ezio.melotti | 2009-06-30 18:56:16 -0400 (Tue, 30 Jun 2009) | 1 line Fixed a backslash that was not supposed to be there ........ r73824 | ezio.melotti | 2009-07-03 21:18:08 -0400 (Fri, 03 Jul 2009) | 1 line #6398 typo: versio. -> version. ........ ................
| | * Merged revisions 74126,74130-74131,74149,74155,74157,74180-74183,74398 via ↵Georg Brandl2009-08-131-6/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svnmerge from svn+ssh://svn.python.org/python/branches/py3k ................ r74126 | alexandre.vassalotti | 2009-07-21 02:39:03 +0200 (Di, 21 Jul 2009) | 14 lines Merged revisions 73871 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73871 | alexandre.vassalotti | 2009-07-06 22:17:30 -0400 (Mon, 06 Jul 2009) | 7 lines Grow the allocated buffer in PyUnicode_EncodeUTF7 to avoid buffer overrun. Without this change, test_unicode.UnicodeTest.test_codecs_utf7 crashes in debug mode. What happens is the unicode string u'\U000abcde' with a length of 1 encodes to the string '+2m/c3g-' of length 8. Since only 5 bytes is reserved in the buffer, a buffer overrun occurs. ........ ................ r74130 | alexandre.vassalotti | 2009-07-21 02:57:50 +0200 (Di, 21 Jul 2009) | 2 lines Add ignore rule for the Doc/tools/jinga2/ directory. ................ r74131 | alexandre.vassalotti | 2009-07-21 04:51:58 +0200 (Di, 21 Jul 2009) | 13 lines Merged revisions 73683,73786 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73683 | georg.brandl | 2009-06-29 10:44:49 -0400 (Mon, 29 Jun 2009) | 1 line Fix error handling in PyCode_Optimize, by Alexander Schremmer at EuroPython sprint. ........ r73786 | benjamin.peterson | 2009-07-02 18:56:16 -0400 (Thu, 02 Jul 2009) | 1 line condense with assertRaises ........ ................ r74149 | ezio.melotti | 2009-07-21 22:37:52 +0200 (Di, 21 Jul 2009) | 9 lines Merged revisions 74148 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74148 | ezio.melotti | 2009-07-21 23:18:27 +0300 (Tue, 21 Jul 2009) | 1 line #6536 fixed typo ........ ................ r74155 | alexandre.vassalotti | 2009-07-22 04:24:49 +0200 (Mi, 22 Jul 2009) | 2 lines Issue #6242: Fix deallocator of io.StringIO and io.BytesIO. ................ r74157 | alexandre.vassalotti | 2009-07-22 05:07:33 +0200 (Mi, 22 Jul 2009) | 2 lines Issue #6241: Better type checking for the arguments of io.StringIO. ................ r74180 | ezio.melotti | 2009-07-22 23:17:14 +0200 (Mi, 22 Jul 2009) | 9 lines Merged revisions 74179 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74179 | ezio.melotti | 2009-07-23 00:08:49 +0300 (Thu, 23 Jul 2009) | 1 line #6423 has_key -> in ........ ................ r74181 | alexandre.vassalotti | 2009-07-22 23:27:53 +0200 (Mi, 22 Jul 2009) | 6 lines Clean up test_curses. By using __stdout__ directly, test_curses caused regrtest.py to duplicate the output of some test results. ................ r74182 | alexandre.vassalotti | 2009-07-22 23:29:01 +0200 (Mi, 22 Jul 2009) | 2 lines Use assertGreater instead of assertTrue(x > y). ................ r74183 | alexandre.vassalotti | 2009-07-23 01:27:17 +0200 (Do, 23 Jul 2009) | 4 lines Specialize assertTrue checks when possible. We should get slightly more helpful failure messages with this change. ................ r74398 | georg.brandl | 2009-08-13 11:16:39 +0200 (Do, 13 Aug 2009) | 1 line #6694: fix old function names. ................
| | * Merged revisions 74264 via svnmerge fromGeorg Brandl2009-08-131-7/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://svn.python.org/python/branches/py3k ................ r74264 | alexandre.vassalotti | 2009-07-29 22:12:15 +0200 (Mi, 29 Jul 2009) | 32 lines Merged revisions 74075,74187,74197,74201,74216,74225 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74075 | georg.brandl | 2009-07-18 05:06:31 -0400 (Sat, 18 Jul 2009) | 1 line #6505: fix typos. ........ r74187 | benjamin.peterson | 2009-07-23 10:19:08 -0400 (Thu, 23 Jul 2009) | 1 line use bools for autoraise ........ r74197 | benjamin.peterson | 2009-07-24 22:03:48 -0400 (Fri, 24 Jul 2009) | 1 line clarify ........ r74201 | amaury.forgeotdarc | 2009-07-25 12:22:06 -0400 (Sat, 25 Jul 2009) | 2 lines Better name a variable: 'buf' seems to imply a mutable buffer. ........ r74216 | michael.foord | 2009-07-26 17:12:14 -0400 (Sun, 26 Jul 2009) | 1 line Issue 6581. Michael Foord ........ r74225 | kurt.kaiser | 2009-07-27 12:09:28 -0400 (Mon, 27 Jul 2009) | 5 lines 1. Clean workspace more thoughly before build. 2. Add url of branch we are building to 'results' webpage. (url is now available in $repo_path, could be added to failure email.) 3. Adjust permissions to improve upload reliability. ........ ................
| | * Merged revisions 74278 via svnmerge fromGeorg Brandl2009-08-131-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://svn.python.org/python/branches/py3k ........ r74278 | sean.reifschneider | 2009-08-02 01:55:06 +0200 (So, 02 Aug 2009) | 3 lines - Issue #6624: yArg_ParseTuple with "s" format when parsing argument with NUL: Bogus TypeError detail string. ........
| | * Merged revisions 74058 via svnmerge fromR. David Murray2009-07-191-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r74058 | alexandre.vassalotti | 2009-07-17 06:55:50 -0400 (Fri, 17 Jul 2009) | 36 lines Merged revisions 73870,73879,73899-73900,73905-73906 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73870 | r.david.murray | 2009-07-06 21:06:13 -0400 (Mon, 06 Jul 2009) | 5 lines Issue 6070: when creating a compiled file, after copying the mode bits, on posix zap the execute bit in case it was set on the .py file, since the compiled files are not directly executable on posix. Patch by Marco N. ........ r73879 | r.david.murray | 2009-07-07 05:54:16 -0400 (Tue, 07 Jul 2009) | 3 lines Update issue 6070 patch to match the patch that was actually tested on Windows. ........ r73899 | r.david.murray | 2009-07-08 21:43:41 -0400 (Wed, 08 Jul 2009) | 3 lines Conditionalize test cleanup code to eliminate traceback, which will hopefully reveal the real problem. ........ r73900 | r.david.murray | 2009-07-08 22:06:17 -0400 (Wed, 08 Jul 2009) | 2 lines Make test work with -O. ........ r73905 | r.david.murray | 2009-07-09 09:55:44 -0400 (Thu, 09 Jul 2009) | 3 lines Specify umask in execute bit test to get consistent results and make sure we test resetting all three execute bits. ........ r73906 | r.david.murray | 2009-07-09 11:35:33 -0400 (Thu, 09 Jul 2009) | 5 lines Curdir needs to be in the path for the test to work on all buildbots. (I copied this from another import test, but currently this will fail if TESTFN ends up in /tmp...see issue 2609). ........ ................
| | * Merged revisions 74046 via svnmerge fromHirokazu Yamamoto2009-07-171-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r74046 | hirokazu.yamamoto | 2009-07-17 15:55:42 +0900 | 13 lines Merged revisions 74040,74042 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74040 | hirokazu.yamamoto | 2009-07-17 15:20:46 +0900 | 1 line Issue #6415: Fixed warnings.warn sagfault on bad formatted string. ........ r74042 | hirokazu.yamamoto | 2009-07-17 15:26:54 +0900 | 1 line NEWS about r74040. ........ ................
| | * unfortunately we can't kill compiler_new_tmpname hereBenjamin Peterson2009-06-281-0/+10
| | |
| | * Merged revisions 73623-73624 via svnmerge fromBenjamin Peterson2009-06-281-12/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ................ r73623 | benjamin.peterson | 2009-06-28 12:22:03 -0500 (Sun, 28 Jun 2009) | 58 lines Merged revisions 73004,73439,73496,73509,73529,73564,73576-73577,73595-73596,73605 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73004 | jeffrey.yasskin | 2009-05-28 22:44:31 -0500 (Thu, 28 May 2009) | 5 lines Fix nearly all compilation warnings under Apple gcc-4.0. Tested with OPT="-g -Wall -Wstrict-prototypes -Werror" in both --with-pydebug mode and --without. There's still a batch of non-prototype warnings in Xlib.h that I don't know how to fix. ........ r73439 | benjamin.peterson | 2009-06-15 19:29:31 -0500 (Mon, 15 Jun 2009) | 1 line don't mask encoding errors when decoding a string #6289 ........ r73496 | vinay.sajip | 2009-06-21 12:37:27 -0500 (Sun, 21 Jun 2009) | 1 line Issue #6314: logging.basicConfig() performs extra checks on the "level" argument. ........ r73509 | amaury.forgeotdarc | 2009-06-22 14:33:48 -0500 (Mon, 22 Jun 2009) | 2 lines #4490 Fix sample code run by "python -m xml.sax.xmlreader" ........ r73529 | r.david.murray | 2009-06-23 13:02:46 -0500 (Tue, 23 Jun 2009) | 4 lines Fix issue 5230 by having pydoc's safeimport check to see if the import error was thrown from itself in order to decide if the module can't be found. Thanks to Lucas Prado Melo for collaborating on the fix and tests. ........ r73564 | amaury.forgeotdarc | 2009-06-25 17:29:29 -0500 (Thu, 25 Jun 2009) | 6 lines #2016 Fix a crash in function call when the **kwargs dictionary is mutated during the function call setup. This even gives a slight speedup, probably because tuple allocation is faster than PyMem_NEW. ........ r73576 | benjamin.peterson | 2009-06-26 18:37:06 -0500 (Fri, 26 Jun 2009) | 1 line document is_declared_global() ........ r73577 | benjamin.peterson | 2009-06-27 09:16:23 -0500 (Sat, 27 Jun 2009) | 1 line link to extensive generator docs in the reference manual ........ r73595 | ezio.melotti | 2009-06-27 18:45:39 -0500 (Sat, 27 Jun 2009) | 1 line stmt and setup can contain multiple statements, see #5896 ........ r73596 | ezio.melotti | 2009-06-27 19:07:45 -0500 (Sat, 27 Jun 2009) | 1 line Fixed a wrong apostrophe ........ r73605 | georg.brandl | 2009-06-28 07:10:18 -0500 (Sun, 28 Jun 2009) | 1 line Remove stray pychecker directive. ........ ................ r73624 | benjamin.peterson | 2009-06-28 12:32:20 -0500 (Sun, 28 Jun 2009) | 1 line document BufferedIOBase.raw and TextIOBase.buffer ................
| * | Merged revisions 88530 via svnmerge fromVictor Stinner2011-02-232-5/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r88530 | victor.stinner | 2011-02-23 13:07:37 +0100 (mer., 23 févr. 2011) | 4 lines Issue #11272: Fix input() and sys.stdin for Windows newline On Windows, input() strips '\r' (and not only '\n'), and sys.stdin uses universal newline (replace '\r\n' by '\n'). ........
* | | Issue #3080: Add PyImport_AddModuleObject() and PyImport_ExecCodeModuleObject()Victor Stinner2011-03-041-21/+66
| | |
* | | Remove useless argument of _PyUnicode_AsDefaultEncodedString()Victor Stinner2011-03-023-3/+3
| | |
* | | Issue #11272: Fix input() and sys.stdin for Windows newlineVictor Stinner2011-02-232-5/+19
| | | | | | | | | | | | | | | On Windows, input() strips '\r' (and not only '\n'), and sys.stdin uses universal newline (replace '\r\n' by '\n').
* | | dynload_dl.c: replace tabs by spacesVictor Stinner2011-02-231-7/+7
| | |
* | | Issue #3080: Mark _PyImport_FindBuiltin() argument as constantVictor Stinner2011-02-231-2/+2
| | | | | | | | | | | | | | | | | | And as a consequence, mark also name argument of _PyImport_FindExtensionUnicode() constant too. But I plan to change this argument type to PyObject* later.
* | | Issue #3080: Remove unused argument of _PyImport_GetDynLoadFunc()Victor Stinner2011-02-228-11/+10
| | | | | | | | | | | | The first argument, fqname, was not used.
* | | Issue #3080: Mark PyWin_FindRegisteredModule() as privateVictor Stinner2011-02-221-3/+3
| | | | | | | | | | | | | | | This function was not declared in Python public API (in any .h file) and not documented. Mark it as private to prepare a change of its API.
* | | Issue #8914: fix various warnings from the Clang static analyzer v254.Brett Cannon2011-02-227-15/+9
| | |
* | | Remove filename variable from ceval.cVictor Stinner2011-02-211-16/+0
|/ / | | | | | | | | | | | | Issue #11168: Remove filename debug variable from PyEval_EvalFrameEx(). It encoded the Unicode filename to UTF-8, but the encoding fails on undecodable filename (on surrogate characters) which raises an unexpected UnicodeEncodeError on recursion limit.
* | #730467: Another small AIX fix.Georg Brandl2011-02-151-1/+1
| |
* | Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work ↵Antoine Pitrou2011-01-151-4/+7
| | | | | | | | | | | | with 3.2. (we need some tests for this)
lMessage)", &successText); break; case BOOTSTRAPPER_ACTION_MODIFY: hr = LocGetString(_wixLoc, L"#(loc.SuccessModifyMessage)", &successText); break; case BOOTSTRAPPER_ACTION_REPAIR: hr = LocGetString(_wixLoc, L"#(loc.SuccessRepairMessage)", &successText); break; case BOOTSTRAPPER_ACTION_UNINSTALL: hr = LocGetString(_wixLoc, L"#(loc.SuccessRemoveMessage)", &successText); break; } if (successText) { LPWSTR formattedString = nullptr; BalFormatString(successText->wzText, &formattedString); if (formattedString) { ThemeSetTextControl(_theme, ID_SUCCESS_TEXT, formattedString); StrFree(formattedString); } } ThemeControlEnable(_theme, ID_LAUNCH_BUTTON, launchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < _plannedAction); ThemeControlEnable(_theme, ID_SUCCESS_RESTART_TEXT, showRestartButton); ThemeControlEnable(_theme, ID_SUCCESS_RESTART_BUTTON, showRestartButton); } void FailurePage_Show() { // on the "Failure" page, show error message and check if the restart button should be enabled. // if there is a log file variable then we'll assume the log file exists. BOOL showLogLink = (_bundle.sczLogVariable && *_bundle.sczLogVariable); BOOL showErrorMessage = FALSE; BOOL showRestartButton = FALSE; if (FAILED(_hrFinal)) { LPWSTR unformattedText = nullptr; LPWSTR text = nullptr; // If we know the failure message, use that. if (_failedMessage && *_failedMessage) { StrAllocString(&unformattedText, _failedMessage, 0); } else { // try to get the error message from the error code. StrAllocFromError(&unformattedText, _hrFinal, nullptr); if (!unformattedText || !*unformattedText) { StrAllocFromError(&unformattedText, E_FAIL, nullptr); } } if (E_WIXSTDBA_CONDITION_FAILED == _hrFinal) { if (unformattedText) { StrAllocString(&text, unformattedText, 0); } } else { StrAllocFormatted(&text, L"0x%08x - %ls", _hrFinal, unformattedText); } if (text) { ThemeSetTextControl(_theme, ID_FAILURE_MESSAGE_TEXT, text); showErrorMessage = TRUE; } ReleaseStr(text); ReleaseStr(unformattedText); } if (_restartRequired && BOOTSTRAPPER_RESTART_PROMPT == _command.restart) { showRestartButton = TRUE; } ThemeControlEnable(_theme, ID_FAILURE_LOGFILE_LINK, showLogLink); ThemeControlEnable(_theme, ID_FAILURE_MESSAGE_TEXT, showErrorMessage); ThemeControlEnable(_theme, ID_FAILURE_RESTART_TEXT, showRestartButton); ThemeControlEnable(_theme, ID_FAILURE_RESTART_BUTTON, showRestartButton); } public: // IBootstrapperApplication virtual STDMETHODIMP OnStartup() { HRESULT hr = S_OK; DWORD dwUIThreadId = 0; // create UI thread _hUiThread = ::CreateThread(nullptr, 0, UiThreadProc, this, 0, &dwUIThreadId); if (!_hUiThread) { ExitWithLastError(hr, "Failed to create UI thread."); } LExit: return hr; } virtual STDMETHODIMP_(int) OnShutdown() { int nResult = IDNOACTION; // wait for UI thread to terminate if (_hUiThread) { ::WaitForSingleObject(_hUiThread, INFINITE); ReleaseHandle(_hUiThread); } // If a restart was required. if (_restartRequired && _allowRestart) { nResult = IDRESTART; } return nResult; } virtual STDMETHODIMP_(int) OnDetectRelatedBundle( __in LPCWSTR wzBundleId, __in BOOTSTRAPPER_RELATION_TYPE relationType, __in LPCWSTR /*wzBundleTag*/, __in BOOL fPerMachine, __in DWORD64 /*dw64Version*/, __in BOOTSTRAPPER_RELATED_OPERATION operation ) { BalInfoAddRelatedBundleAsPackage(&_bundle.packages, wzBundleId, relationType, fPerMachine); // Remember when our bundle would cause a downgrade. if (BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) { _downgradingOtherVersion = TRUE; } else if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation) { _upgradingOldVersion = TRUE; // Assume we don't want the launcher or file associations, and if // they have already been installed then loading the state will // reactivate these settings. _engine->SetVariableNumeric(L"Include_launcher", 0); _engine->SetVariableNumeric(L"AssociateFiles", 0); auto hr = LoadLauncherStateFromKey(_engine, HKEY_CURRENT_USER); if (hr == S_FALSE) { hr = LoadLauncherStateFromKey(_engine, HKEY_LOCAL_MACHINE); } } else if (BOOTSTRAPPER_RELATED_OPERATION_NONE == operation) { if (_command.action == BOOTSTRAPPER_ACTION_INSTALL) { LOC_STRING *pLocString = nullptr; if (SUCCEEDED(LocGetString(_wixLoc, L"#(loc.FailureExistingInstall)", &pLocString)) && pLocString) { BalFormatString(pLocString->wzText, &_failedMessage); } else { BalFormatString(L"Cannot install [WixBundleName] because it is already installed.", &_failedMessage); } BalLog( BOOTSTRAPPER_LOG_LEVEL_ERROR, "Related bundle %ls is preventing install", wzBundleId ); SetState(PYBA_STATE_FAILED, E_WIXSTDBA_CONDITION_FAILED); } } return CheckCanceled() ? IDCANCEL : IDOK; } virtual STDMETHODIMP_(void) OnDetectPackageComplete( __in LPCWSTR wzPackageId, __in HRESULT /*hrStatus*/, __in BOOTSTRAPPER_PACKAGE_STATE state ) { } virtual STDMETHODIMP_(void) OnDetectComplete(__in HRESULT hrStatus) { if (SUCCEEDED(hrStatus) && _baFunction) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running detect complete BA function"); _baFunction->OnDetectComplete(); } if (SUCCEEDED(hrStatus)) { hrStatus = EvaluateConditions(); } SetState(PYBA_STATE_DETECTED, hrStatus); // If we're not interacting with the user or we're doing a layout or we're just after a force restart // then automatically start planning. if (BOOTSTRAPPER_DISPLAY_FULL > _command.display || BOOTSTRAPPER_ACTION_LAYOUT == _command.action || BOOTSTRAPPER_ACTION_UNINSTALL == _command.action || BOOTSTRAPPER_RESUME_TYPE_REBOOT == _command.resumeType) { if (SUCCEEDED(hrStatus)) { ::PostMessageW(_hWnd, WM_PYBA_PLAN_PACKAGES, 0, _command.action); } } } virtual STDMETHODIMP_(int) OnPlanRelatedBundle( __in_z LPCWSTR /*wzBundleId*/, __inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState ) { return CheckCanceled() ? IDCANCEL : IDOK; } virtual STDMETHODIMP_(int) OnPlanPackageBegin( __in_z LPCWSTR wzPackageId, __inout BOOTSTRAPPER_REQUEST_STATE *pRequestState ) { HRESULT hr = S_OK; BAL_INFO_PACKAGE* pPackage = nullptr; if (_nextPackageAfterRestart) { // After restart we need to finish the dependency registration for our package so allow the package // to go present. if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, _nextPackageAfterRestart, -1)) { // Do not allow a repair because that could put us in a perpetual restart loop. if (BOOTSTRAPPER_REQUEST_STATE_REPAIR == *pRequestState) { *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; } ReleaseNullStr(_nextPackageAfterRestart); // no more skipping now. } else { // not the matching package, so skip it. BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Skipping package: %ls, after restart because it was applied before the restart.", wzPackageId); *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; } } else if ((_plannedAction == BOOTSTRAPPER_ACTION_INSTALL || _plannedAction == BOOTSTRAPPER_ACTION_MODIFY) && SUCCEEDED(BalInfoFindPackageById(&_bundle.packages, wzPackageId, &pPackage))) { BOOL f = FALSE; if (SUCCEEDED(_engine->EvaluateCondition(pPackage->sczInstallCondition, &f)) && f) { *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; } } return CheckCanceled() ? IDCANCEL : IDOK; } virtual STDMETHODIMP_(int) OnPlanMsiFeature( __in_z LPCWSTR wzPackageId, __in_z LPCWSTR wzFeatureId, __inout BOOTSTRAPPER_FEATURE_STATE* pRequestedState ) { LONGLONG install; if (wcscmp(wzFeatureId, L"AssociateFiles") == 0 || wcscmp(wzFeatureId, L"Shortcuts") == 0) { if (SUCCEEDED(_engine->GetVariableNumeric(wzFeatureId, &install)) && install) { *pRequestedState = BOOTSTRAPPER_FEATURE_STATE_LOCAL; } else { *pRequestedState = BOOTSTRAPPER_FEATURE_STATE_ABSENT; } } else { *pRequestedState = BOOTSTRAPPER_FEATURE_STATE_LOCAL; } return CheckCanceled() ? IDCANCEL : IDNOACTION; } virtual STDMETHODIMP_(void) OnPlanComplete(__in HRESULT hrStatus) { if (SUCCEEDED(hrStatus) && _baFunction) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running plan complete BA function"); _baFunction->OnPlanComplete(); } SetState(PYBA_STATE_PLANNED, hrStatus); if (SUCCEEDED(hrStatus)) { ::PostMessageW(_hWnd, WM_PYBA_APPLY_PACKAGES, 0, 0); } _startedExecution = FALSE; _calculatedCacheProgress = 0; _calculatedExecuteProgress = 0; } virtual STDMETHODIMP_(int) OnCachePackageBegin( __in_z LPCWSTR wzPackageId, __in DWORD cCachePayloads, __in DWORD64 dw64PackageCacheSize ) { if (wzPackageId && *wzPackageId) { BAL_INFO_PACKAGE* pPackage = nullptr; HRESULT hr = BalInfoFindPackageById(&_bundle.packages, wzPackageId, &pPackage); LPCWSTR wz = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId; ThemeSetTextControl(_theme, ID_CACHE_PROGRESS_PACKAGE_TEXT, wz); // If something started executing, leave it in the overall progress text. if (!_startedExecution) { ThemeSetTextControl(_theme, ID_OVERALL_PROGRESS_PACKAGE_TEXT, wz); } } return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize); } virtual STDMETHODIMP_(int) OnCacheAcquireProgress( __in_z LPCWSTR wzPackageOrContainerId, __in_z_opt LPCWSTR wzPayloadId, __in DWORD64 dw64Progress, __in DWORD64 dw64Total, __in DWORD dwOverallPercentage ) { WCHAR wzProgress[5] = { }; #ifdef DEBUG BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "PYBA: OnCacheAcquireProgress() - container/package: %ls, payload: %ls, progress: %I64u, total: %I64u, overall progress: %u%%", wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage); #endif ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallPercentage); ThemeSetTextControl(_theme, ID_CACHE_PROGRESS_TEXT, wzProgress); ThemeSetProgressControl(_theme, ID_CACHE_PROGRESS_BAR, dwOverallPercentage); _calculatedCacheProgress = dwOverallPercentage * PYBA_ACQUIRE_PERCENTAGE / 100; ThemeSetProgressControl(_theme, ID_OVERALL_CALCULATED_PROGRESS_BAR, _calculatedCacheProgress + _calculatedExecuteProgress); SetTaskbarButtonProgress(_calculatedCacheProgress + _calculatedExecuteProgress); return __super::OnCacheAcquireProgress(wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage); } virtual STDMETHODIMP_(int) OnCacheAcquireComplete( __in_z LPCWSTR wzPackageOrContainerId, __in_z_opt LPCWSTR wzPayloadId, __in HRESULT hrStatus, __in int nRecommendation ) { SetProgressState(hrStatus); return __super::OnCacheAcquireComplete(wzPackageOrContainerId, wzPayloadId, hrStatus, nRecommendation); } virtual STDMETHODIMP_(int) OnCacheVerifyComplete( __in_z LPCWSTR wzPackageId, __in_z LPCWSTR wzPayloadId, __in HRESULT hrStatus, __in int nRecommendation ) { SetProgressState(hrStatus); return __super::OnCacheVerifyComplete(wzPackageId, wzPayloadId, hrStatus, nRecommendation); } virtual STDMETHODIMP_(void) OnCacheComplete(__in HRESULT /*hrStatus*/) { ThemeSetTextControl(_theme, ID_CACHE_PROGRESS_PACKAGE_TEXT, L""); SetState(PYBA_STATE_CACHED, S_OK); // we always return success here and let OnApplyComplete() deal with the error. } virtual STDMETHODIMP_(int) OnError( __in BOOTSTRAPPER_ERROR_TYPE errorType, __in LPCWSTR wzPackageId, __in DWORD dwCode, __in_z LPCWSTR wzError, __in DWORD dwUIHint, __in DWORD /*cData*/, __in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/, __in int nRecommendation ) { int nResult = nRecommendation; LPWSTR sczError = nullptr; if (BOOTSTRAPPER_DISPLAY_EMBEDDED == _command.display) { HRESULT hr = _engine->SendEmbeddedError(dwCode, wzError, dwUIHint, &nResult); if (FAILED(hr)) { nResult = IDERROR; } } else if (BOOTSTRAPPER_DISPLAY_FULL == _command.display) { // If this is an authentication failure, let the engine try to handle it for us. if (BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER == errorType || BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY == errorType) { nResult = IDTRYAGAIN; } else // show a generic error message box. { BalRetryErrorOccurred(wzPackageId, dwCode); if (!_showingInternalUIThisPackage) { // If no error message was provided, use the error code to try and get an error message. if (!wzError || !*wzError || BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER != errorType) { HRESULT hr = StrAllocFromError(&sczError, dwCode, nullptr); if (FAILED(hr) || !sczError || !*sczError) { StrAllocFormatted(&sczError, L"0x%x", dwCode); } } nResult = ::MessageBoxW(_hWnd, sczError ? sczError : wzError, _theme->sczCaption, dwUIHint); } } SetProgressState(HRESULT_FROM_WIN32(dwCode)); } else { // just take note of the error code and let things continue. BalRetryErrorOccurred(wzPackageId, dwCode); } ReleaseStr(sczError); return nResult; } virtual STDMETHODIMP_(int) OnExecuteMsiMessage( __in_z LPCWSTR wzPackageId, __in INSTALLMESSAGE mt, __in UINT uiFlags, __in_z LPCWSTR wzMessage, __in DWORD cData, __in_ecount_z_opt(cData) LPCWSTR* rgwzData, __in int nRecommendation ) { #ifdef DEBUG BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "PYBA: OnExecuteMsiMessage() - package: %ls, message: %ls", wzPackageId, wzMessage); #endif if (BOOTSTRAPPER_DISPLAY_FULL == _command.display && (INSTALLMESSAGE_WARNING == mt || INSTALLMESSAGE_USER == mt)) { int nResult = ::MessageBoxW(_hWnd, wzMessage, _theme->sczCaption, uiFlags); return nResult; } if (INSTALLMESSAGE_ACTIONSTART == mt) { ThemeSetTextControl(_theme, ID_EXECUTE_PROGRESS_ACTIONDATA_TEXT, wzMessage); } return __super::OnExecuteMsiMessage(wzPackageId, mt, uiFlags, wzMessage, cData, rgwzData, nRecommendation); } virtual STDMETHODIMP_(int) OnProgress(__in DWORD dwProgressPercentage, __in DWORD dwOverallProgressPercentage) { WCHAR wzProgress[5] = { }; #ifdef DEBUG BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "PYBA: OnProgress() - progress: %u%%, overall progress: %u%%", dwProgressPercentage, dwOverallProgressPercentage); #endif ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage); ThemeSetTextControl(_theme, ID_OVERALL_PROGRESS_TEXT, wzProgress); ThemeSetProgressControl(_theme, ID_OVERALL_PROGRESS_BAR, dwOverallProgressPercentage); SetTaskbarButtonProgress(dwOverallProgressPercentage); return __super::OnProgress(dwProgressPercentage, dwOverallProgressPercentage); } virtual STDMETHODIMP_(int) OnExecutePackageBegin(__in_z LPCWSTR wzPackageId, __in BOOL fExecute) { LPWSTR sczFormattedString = nullptr; _startedExecution = TRUE; if (wzPackageId && *wzPackageId) { BAL_INFO_PACKAGE* pPackage = nullptr; BalInfoFindPackageById(&_bundle.packages, wzPackageId, &pPackage); LPCWSTR wz = wzPackageId; if (pPackage) { LOC_STRING* pLocString = nullptr; switch (pPackage->type) { case BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON: LocGetString(_wixLoc, L"#(loc.ExecuteAddonRelatedBundleMessage)", &pLocString); break; case BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH: LocGetString(_wixLoc, L"#(loc.ExecutePatchRelatedBundleMessage)", &pLocString); break; case BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE: LocGetString(_wixLoc, L"#(loc.ExecuteUpgradeRelatedBundleMessage)", &pLocString); break; } if (pLocString) { // If the wix developer is showing a hidden variable in the UI, then obviously they don't care about keeping it safe // so don't go down the rabbit hole of making sure that this is securely freed. BalFormatString(pLocString->wzText, &sczFormattedString); } wz = sczFormattedString ? sczFormattedString : pPackage->sczDisplayName ? pPackage->sczDisplayName : wzPackageId; } _showingInternalUIThisPackage = pPackage && pPackage->fDisplayInternalUI; ThemeSetTextControl(_theme, ID_EXECUTE_PROGRESS_PACKAGE_TEXT, wz); ThemeSetTextControl(_theme, ID_OVERALL_PROGRESS_PACKAGE_TEXT, wz); } else { _showingInternalUIThisPackage = FALSE; } ReleaseStr(sczFormattedString); return __super::OnExecutePackageBegin(wzPackageId, fExecute); } virtual int __stdcall OnExecuteProgress( __in_z LPCWSTR wzPackageId, __in DWORD dwProgressPercentage, __in DWORD dwOverallProgressPercentage ) { WCHAR wzProgress[8] = { }; #ifdef DEBUG BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "PYBA: OnExecuteProgress() - package: %ls, progress: %u%%, overall progress: %u%%", wzPackageId, dwProgressPercentage, dwOverallProgressPercentage); #endif ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage); ThemeSetTextControl(_theme, ID_EXECUTE_PROGRESS_TEXT, wzProgress); ThemeSetProgressControl(_theme, ID_EXECUTE_PROGRESS_BAR, dwOverallProgressPercentage); _calculatedExecuteProgress = dwOverallProgressPercentage * (100 - PYBA_ACQUIRE_PERCENTAGE) / 100; ThemeSetProgressControl(_theme, ID_OVERALL_CALCULATED_PROGRESS_BAR, _calculatedCacheProgress + _calculatedExecuteProgress); SetTaskbarButtonProgress(_calculatedCacheProgress + _calculatedExecuteProgress); return __super::OnExecuteProgress(wzPackageId, dwProgressPercentage, dwOverallProgressPercentage); } virtual STDMETHODIMP_(int) OnExecutePackageComplete( __in_z LPCWSTR wzPackageId, __in HRESULT hrExitCode, __in BOOTSTRAPPER_APPLY_RESTART restart, __in int nRecommendation ) { SetProgressState(hrExitCode); if (_wcsnicmp(wzPackageId, L"path_", 5) == 0 && SUCCEEDED(hrExitCode)) { SendMessageTimeoutW( HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"Environment"), SMTO_ABORTIFHUNG, 1000, nullptr ); } int nResult = __super::OnExecutePackageComplete(wzPackageId, hrExitCode, restart, nRecommendation); return nResult; } virtual STDMETHODIMP_(void) OnExecuteComplete(__in HRESULT hrStatus) { ThemeSetTextControl(_theme, ID_EXECUTE_PROGRESS_PACKAGE_TEXT, L""); ThemeSetTextControl(_theme, ID_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L""); ThemeSetTextControl(_theme, ID_OVERALL_PROGRESS_PACKAGE_TEXT, L""); ThemeControlEnable(_theme, ID_PROGRESS_CANCEL_BUTTON, FALSE); // no more cancel. SetState(PYBA_STATE_EXECUTED, S_OK); // we always return success here and let OnApplyComplete() deal with the error. SetProgressState(hrStatus); } virtual STDMETHODIMP_(int) OnResolveSource( __in_z LPCWSTR wzPackageOrContainerId, __in_z_opt LPCWSTR wzPayloadId, __in_z LPCWSTR wzLocalSource, __in_z_opt LPCWSTR wzDownloadSource ) { int nResult = IDERROR; // assume we won't resolve source and that is unexpected. if (BOOTSTRAPPER_DISPLAY_FULL == _command.display) { if (wzDownloadSource) { nResult = IDDOWNLOAD; } else { // prompt to change the source location. OPENFILENAMEW ofn = { }; WCHAR wzFile[MAX_PATH] = { }; ::StringCchCopyW(wzFile, countof(wzFile), wzLocalSource); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = _hWnd; ofn.lpstrFile = wzFile; ofn.nMaxFile = countof(wzFile); ofn.lpstrFilter = L"All Files\0*.*\0"; ofn.nFilterIndex = 1; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.lpstrTitle = _theme->sczCaption; if (::GetOpenFileNameW(&ofn)) { HRESULT hr = _engine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile); nResult = SUCCEEDED(hr) ? IDRETRY : IDERROR; } else { nResult = IDCANCEL; } } } else if (wzDownloadSource) { // If doing a non-interactive install and download source is available, let's try downloading the package silently nResult = IDDOWNLOAD; } // else there's nothing more we can do in non-interactive mode return CheckCanceled() ? IDCANCEL : nResult; } virtual STDMETHODIMP_(int) OnApplyComplete(__in HRESULT hrStatus, __in BOOTSTRAPPER_APPLY_RESTART restart) { _restartResult = restart; // remember the restart result so we return the correct error code no matter what the user chooses to do in the UI. // If a restart was encountered and we are not suppressing restarts, then restart is required. _restartRequired = (BOOTSTRAPPER_APPLY_RESTART_NONE != restart && BOOTSTRAPPER_RESTART_NEVER < _command.restart); // If a restart is required and we're not displaying a UI or we are not supposed to prompt for restart then allow the restart. _allowRestart = _restartRequired && (BOOTSTRAPPER_DISPLAY_FULL > _command.display || BOOTSTRAPPER_RESTART_PROMPT < _command.restart); // If we are showing UI, wait a beat before moving to the final screen. if (BOOTSTRAPPER_DISPLAY_NONE < _command.display) { ::Sleep(250); } SetState(PYBA_STATE_APPLIED, hrStatus); SetTaskbarButtonProgress(100); // show full progress bar, green, yellow, or red return IDNOACTION; } virtual STDMETHODIMP_(void) OnLaunchApprovedExeComplete(__in HRESULT hrStatus, __in DWORD /*processId*/) { if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hrStatus) { //try with ShelExec next time OnClickLaunchButton(); } else { ::PostMessageW(_hWnd, WM_CLOSE, 0, 0); } } private: // // UiThreadProc - entrypoint for UI thread. // static DWORD WINAPI UiThreadProc(__in LPVOID pvContext) { HRESULT hr = S_OK; PythonBootstrapperApplication* pThis = (PythonBootstrapperApplication*)pvContext; BOOL comInitialized = FALSE; BOOL ret = FALSE; MSG msg = { }; // Initialize COM and theme. hr = ::CoInitialize(nullptr); BalExitOnFailure(hr, "Failed to initialize COM."); comInitialized = TRUE; hr = ThemeInitialize(pThis->_hModule); BalExitOnFailure(hr, "Failed to initialize theme manager."); hr = pThis->InitializeData(); BalExitOnFailure(hr, "Failed to initialize data in bootstrapper application."); // Create main window. pThis->InitializeTaskbarButton(); hr = pThis->CreateMainWindow(); BalExitOnFailure(hr, "Failed to create main window."); if (FAILED(pThis->_hrFinal)) { pThis->SetState(PYBA_STATE_FAILED, hr); ::PostMessageW(pThis->_hWnd, WM_PYBA_SHOW_FAILURE, 0, 0); } else { // Okay, we're ready for packages now. pThis->SetState(PYBA_STATE_INITIALIZED, hr); ::PostMessageW(pThis->_hWnd, BOOTSTRAPPER_ACTION_HELP == pThis->_command.action ? WM_PYBA_SHOW_HELP : WM_PYBA_DETECT_PACKAGES, 0, 0); } // message pump while (0 != (ret = ::GetMessageW(&msg, nullptr, 0, 0))) { if (-1 == ret) { hr = E_UNEXPECTED; BalExitOnFailure(hr, "Unexpected return value from message pump."); } else if (!ThemeHandleKeyboardMessage(pThis->_theme, msg.hwnd, &msg)) { ::TranslateMessage(&msg); ::DispatchMessageW(&msg); } } // Succeeded thus far, check to see if anything went wrong while actually // executing changes. if (FAILED(pThis->_hrFinal)) { hr = pThis->_hrFinal; } else if (pThis->CheckCanceled()) { hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); } LExit: // destroy main window pThis->DestroyMainWindow(); // initiate engine shutdown DWORD dwQuit = HRESULT_CODE(hr); if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->_restartResult) { dwQuit = ERROR_SUCCESS_REBOOT_INITIATED; } else if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == pThis->_restartResult) { dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED; } pThis->_engine->Quit(dwQuit); ReleaseTheme(pThis->_theme); ThemeUninitialize(); // uninitialize COM if (comInitialized) { ::CoUninitialize(); } return hr; } // // InitializeData - initializes all the package information. // HRESULT InitializeData() { HRESULT hr = S_OK; LPWSTR sczModulePath = nullptr; IXMLDOMDocument *pixdManifest = nullptr; hr = BalManifestLoad(_hModule, &pixdManifest); BalExitOnFailure(hr, "Failed to load bootstrapper application manifest."); hr = ParseOverridableVariablesFromXml(pixdManifest); BalExitOnFailure(hr, "Failed to read overridable variables."); hr = ProcessCommandLine(&_language); ExitOnFailure(hr, "Unknown commandline parameters."); hr = PathRelativeToModule(&sczModulePath, nullptr, _hModule); BalExitOnFailure(hr, "Failed to get module path."); hr = LoadLocalization(sczModulePath, _language); ExitOnFailure(hr, "Failed to load localization."); hr = LoadTheme(sczModulePath, _language); ExitOnFailure(hr, "Failed to load theme."); hr = BalInfoParseFromXml(&_bundle, pixdManifest); BalExitOnFailure(hr, "Failed to load bundle information."); hr = BalConditionsParseFromXml(&_conditions, pixdManifest, _wixLoc); BalExitOnFailure(hr, "Failed to load conditions from XML."); hr = LoadBootstrapperBAFunctions(); BalExitOnFailure(hr, "Failed to load bootstrapper functions."); hr = UpdateUIStrings(_command.action); BalExitOnFailure(hr, "Failed to load UI strings."); GetBundleFileVersion(); // don't fail if we couldn't get the version info; best-effort only LExit: ReleaseObject(pixdManifest); ReleaseStr(sczModulePath); return hr; } // // ProcessCommandLine - process the provided command line arguments. // HRESULT ProcessCommandLine(__inout LPWSTR* psczLanguage) { HRESULT hr = S_OK; int argc = 0; LPWSTR* argv = nullptr; LPWSTR sczVariableName = nullptr; LPWSTR sczVariableValue = nullptr; if (_command.wzCommandLine && *_command.wzCommandLine) { argv = ::CommandLineToArgvW(_command.wzCommandLine, &argc); ExitOnNullWithLastError(argv, hr, "Failed to get command line."); for (int i = 0; i < argc; ++i) { if (argv[i][0] == L'-' || argv[i][0] == L'/') { if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"lang", -1)) { if (i + 1 >= argc) { hr = E_INVALIDARG; BalExitOnFailure(hr, "Must specify a language."); } ++i; hr = StrAllocString(psczLanguage, &argv[i][0], 0); BalExitOnFailure(hr, "Failed to copy language."); } } else if (_overridableVariables) { int value; const wchar_t* pwc = wcschr(argv[i], L'='); if (pwc) { hr = StrAllocString(&sczVariableName, argv[i], pwc - argv[i]); BalExitOnFailure(hr, "Failed to copy variable name."); hr = DictKeyExists(_overridableVariables, sczVariableName); if (E_NOTFOUND == hr) { BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Ignoring attempt to set non-overridable variable: '%ls'.", sczVariableName); hr = S_OK; continue; } ExitOnFailure(hr, "Failed to check the dictionary of overridable variables."); hr = StrAllocString(&sczVariableValue, ++pwc, 0); BalExitOnFailure(hr, "Failed to copy variable value."); if (::StrToIntEx(sczVariableValue, STIF_DEFAULT, &value)) { hr = _engine->SetVariableNumeric(sczVariableName, value); } else { hr = _engine->SetVariableString(sczVariableName, sczVariableValue); } BalExitOnFailure(hr, "Failed to set variable."); } else { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Ignoring unknown argument: %ls", argv[i]); } } } } LExit: if (argv) { ::LocalFree(argv); } ReleaseStr(sczVariableName); ReleaseStr(sczVariableValue); return hr; } HRESULT LoadLocalization(__in_z LPCWSTR wzModulePath, __in_z_opt LPCWSTR wzLanguage) { HRESULT hr = S_OK; LPWSTR sczLocPath = nullptr; LPCWSTR wzLocFileName = L"Default.wxl"; hr = LocProbeForFile(wzModulePath, wzLocFileName, wzLanguage, &sczLocPath); BalExitOnFailure2(hr, "Failed to probe for loc file: %ls in path: %ls", wzLocFileName, wzModulePath); hr = LocLoadFromFile(sczLocPath, &_wixLoc); BalExitOnFailure1(hr, "Failed to load loc file from path: %ls", sczLocPath); if (WIX_LOCALIZATION_LANGUAGE_NOT_SET != _wixLoc->dwLangId) { ::SetThreadLocale(_wixLoc->dwLangId); } hr = StrAllocString(&_confirmCloseMessage, L"#(loc.ConfirmCancelMessage)", 0); ExitOnFailure(hr, "Failed to initialize confirm message loc identifier."); hr = LocLocalizeString(_wixLoc, &_confirmCloseMessage); BalExitOnFailure1(hr, "Failed to localize confirm close message: %ls", _confirmCloseMessage); LExit: ReleaseStr(sczLocPath); return hr; } HRESULT LoadTheme(__in_z LPCWSTR wzModulePath, __in_z_opt LPCWSTR wzLanguage) { HRESULT hr = S_OK; LPWSTR sczThemePath = nullptr; LPCWSTR wzThemeFileName = L"Default.thm"; LPWSTR sczCaption = nullptr; hr = LocProbeForFile(wzModulePath, wzThemeFileName, wzLanguage, &sczThemePath); BalExitOnFailure2(hr, "Failed to probe for theme file: %ls in path: %ls", wzThemeFileName, wzModulePath); hr = ThemeLoadFromFile(sczThemePath, &_theme); BalExitOnFailure1(hr, "Failed to load theme from path: %ls", sczThemePath); hr = ThemeLocalize(_theme, _wixLoc); BalExitOnFailure1(hr, "Failed to localize theme: %ls", sczThemePath); // Update the caption if there are any formatted strings in it. // If the wix developer is showing a hidden variable in the UI, then // obviously they don't care about keeping it safe so don't go down the // rabbit hole of making sure that this is securely freed. hr = BalFormatString(_theme->sczCaption, &sczCaption); if (SUCCEEDED(hr)) { ThemeUpdateCaption(_theme, sczCaption); } LExit: ReleaseStr(sczCaption); ReleaseStr(sczThemePath); return hr; } HRESULT ParseOverridableVariablesFromXml(__in IXMLDOMDocument* pixdManifest) { HRESULT hr = S_OK; IXMLDOMNode* pNode = nullptr; IXMLDOMNodeList* pNodes = nullptr; DWORD cNodes = 0; LPWSTR scz = nullptr; BOOL hidden = FALSE; // get the list of variables users can override on the command line hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOverridableVariable", &pNodes); if (S_FALSE == hr) { ExitFunction1(hr = S_OK); } ExitOnFailure(hr, "Failed to select overridable variable nodes."); hr = pNodes->get_length((long*)&cNodes); ExitOnFailure(hr, "Failed to get overridable variable node count."); if (cNodes) { hr = DictCreateStringList(&_overridableVariables, 32, DICT_FLAG_NONE); ExitOnFailure(hr, "Failed to create the string dictionary."); for (DWORD i = 0; i < cNodes; ++i) { hr = XmlNextElement(pNodes, &pNode, nullptr); ExitOnFailure(hr, "Failed to get next node."); // @Name hr = XmlGetAttributeEx(pNode, L"Name", &scz); ExitOnFailure(hr, "Failed to get @Name."); hr = XmlGetYesNoAttribute(pNode, L"Hidden", &hidden); if (!hidden) { hr = DictAddKey(_overridableVariables, scz); ExitOnFailure1(hr, "Failed to add \"%ls\" to the string dictionary.", scz); } // prepare next iteration ReleaseNullObject(pNode); } } LExit: ReleaseObject(pNode); ReleaseObject(pNodes); ReleaseStr(scz); return hr; } // // Get the file version of the bootstrapper and record in bootstrapper log file // HRESULT GetBundleFileVersion() { HRESULT hr = S_OK; ULARGE_INTEGER uliVersion = { }; LPWSTR sczCurrentPath = nullptr; hr = PathForCurrentProcess(&sczCurrentPath, nullptr); BalExitOnFailure(hr, "Failed to get bundle path."); hr = FileVersion(sczCurrentPath, &uliVersion.HighPart, &uliVersion.LowPart); BalExitOnFailure(hr, "Failed to get bundle file version."); hr = _engine->SetVariableVersion(PYBA_VARIABLE_BUNDLE_FILE_VERSION, uliVersion.QuadPart); BalExitOnFailure(hr, "Failed to set WixBundleFileVersion variable."); LExit: ReleaseStr(sczCurrentPath); return hr; } // // CreateMainWindow - creates the main install window. // HRESULT CreateMainWindow() { HRESULT hr = S_OK; HICON hIcon = reinterpret_cast<HICON>(_theme->hIcon); WNDCLASSW wc = { }; DWORD dwWindowStyle = 0; int x = CW_USEDEFAULT; int y = CW_USEDEFAULT; POINT ptCursor = { }; HMONITOR hMonitor = nullptr; MONITORINFO mi = { }; COLORREF fg, bg; HBRUSH bgBrush; // If the theme did not provide an icon, try using the icon from the bundle engine. if (!hIcon) { HMODULE hBootstrapperEngine = ::GetModuleHandleW(nullptr); if (hBootstrapperEngine) { hIcon = ::LoadIconW(hBootstrapperEngine, MAKEINTRESOURCEW(1)); } } fg = RGB(0, 0, 0); bg = RGB(255, 255, 255); bgBrush = (HBRUSH)(COLOR_WINDOW+1); if (_theme->dwFontId < _theme->cFonts) { THEME_FONT *font = &_theme->rgFonts[_theme->dwFontId]; fg = font->crForeground; bg = font->crBackground; bgBrush = font->hBackground; RemapColor(&fg, &bg, &bgBrush); } // Register the window class and create the window. wc.lpfnWndProc = PythonBootstrapperApplication::WndProc; wc.hInstance = _hModule; wc.hIcon = hIcon; wc.hCursor = ::LoadCursorW(nullptr, (LPCWSTR)IDC_ARROW); wc.hbrBackground = bgBrush; wc.lpszMenuName = nullptr; wc.lpszClassName = PYBA_WINDOW_CLASS; if (!::RegisterClassW(&wc)) { ExitWithLastError(hr, "Failed to register window."); } _registered = TRUE; // Calculate the window style based on the theme style and command display value. dwWindowStyle = _theme->dwStyle; if (BOOTSTRAPPER_DISPLAY_NONE >= _command.display) { dwWindowStyle &= ~WS_VISIBLE; } // Don't show the window if there is a splash screen (it will be made visible when the splash screen is hidden) if (::IsWindow(_command.hwndSplashScreen)) { dwWindowStyle &= ~WS_VISIBLE; } // Center the window on the monitor with the mouse. if (::GetCursorPos(&ptCursor)) { hMonitor = ::MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST); if (hMonitor) { mi.cbSize = sizeof(mi); if (::GetMonitorInfoW(hMonitor, &mi)) { x = mi.rcWork.left + (mi.rcWork.right - mi.rcWork.left - _theme->nWidth) / 2; y = mi.rcWork.top + (mi.rcWork.bottom - mi.rcWork.top - _theme->nHeight) / 2; } } } _hWnd = ::CreateWindowExW( 0, wc.lpszClassName, _theme->sczCaption, dwWindowStyle, x, y, _theme->nWidth, _theme->nHeight, HWND_DESKTOP, nullptr, _hModule, this ); ExitOnNullWithLastError(_hWnd, hr, "Failed to create window."); hr = S_OK; LExit: return hr; } // // InitializeTaskbarButton - initializes taskbar button for progress. // void InitializeTaskbarButton() { HRESULT hr = S_OK; hr = ::CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_ALL, __uuidof(ITaskbarList3), reinterpret_cast<LPVOID*>(&_taskbarList)); if (REGDB_E_CLASSNOTREG == hr) { // not supported before Windows 7 ExitFunction1(hr = S_OK); } BalExitOnFailure(hr, "Failed to create ITaskbarList3. Continuing."); _taskbarButtonCreatedMessage = ::RegisterWindowMessageW(L"TaskbarButtonCreated"); BalExitOnNullWithLastError(_taskbarButtonCreatedMessage, hr, "Failed to get TaskbarButtonCreated message. Continuing."); LExit: return; } // // DestroyMainWindow - clean up all the window registration. // void DestroyMainWindow() { if (::IsWindow(_hWnd)) { ::DestroyWindow(_hWnd); _hWnd = nullptr; _taskbarButtonOK = FALSE; } if (_registered) { ::UnregisterClassW(PYBA_WINDOW_CLASS, _hModule); _registered = FALSE; } } // // WndProc - standard windows message handler. // static LRESULT CALLBACK WndProc( __in HWND hWnd, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { #pragma warning(suppress:4312) auto pBA = reinterpret_cast<PythonBootstrapperApplication*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA)); switch (uMsg) { case WM_NCCREATE: { LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); pBA = reinterpret_cast<PythonBootstrapperApplication*>(lpcs->lpCreateParams); #pragma warning(suppress:4244) ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pBA)); break; } case WM_NCDESTROY: { LRESULT lres = ThemeDefWindowProc(pBA ? pBA->_theme : nullptr, hWnd, uMsg, wParam, lParam); ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0); return lres; } case WM_CREATE: if (!pBA->OnCreate(hWnd)) { return -1; } break; case WM_QUERYENDSESSION: return IDCANCEL != pBA->OnSystemShutdown(static_cast<DWORD>(lParam), IDCANCEL); case WM_CLOSE: // If the user chose not to close, do *not* let the default window proc handle the message. if (!pBA->OnClose()) { return 0; } break; case WM_DESTROY: ::PostQuitMessage(0); break; case WM_PAINT: __fallthrough; case WM_ERASEBKGND: if (pBA && pBA->_suppressPaint) { return TRUE; } break; case WM_PYBA_SHOW_HELP: pBA->OnShowHelp(); return 0; case WM_PYBA_DETECT_PACKAGES: pBA->OnDetect(); return 0; case WM_PYBA_PLAN_PACKAGES: pBA->OnPlan(static_cast<BOOTSTRAPPER_ACTION>(lParam)); return 0; case WM_PYBA_APPLY_PACKAGES: pBA->OnApply(); return 0; case WM_PYBA_CHANGE_STATE: pBA->OnChangeState(static_cast<PYBA_STATE>(lParam)); return 0; case WM_PYBA_SHOW_FAILURE: pBA->OnShowFailure(); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { // Customize commands // Success/failure commands case ID_LAUNCH_BUTTON: pBA->OnClickLaunchButton(); return 0; case ID_SUCCESS_RESTART_BUTTON: __fallthrough; case ID_FAILURE_RESTART_BUTTON: pBA->OnClickRestartButton(); return 0; case IDCANCEL: __fallthrough; case ID_INSTALL_CANCEL_BUTTON: __fallthrough; case ID_CUSTOM1_CANCEL_BUTTON: __fallthrough; case ID_CUSTOM2_CANCEL_BUTTON: __fallthrough; case ID_MODIFY_CANCEL_BUTTON: __fallthrough; case ID_PROGRESS_CANCEL_BUTTON: __fallthrough; case ID_SUCCESS_CANCEL_BUTTON: __fallthrough; case ID_FAILURE_CANCEL_BUTTON: __fallthrough; case ID_CLOSE_BUTTON: pBA->OnCommand(ID_CLOSE_BUTTON); return 0; default: pBA->OnCommand((CONTROL_ID)LOWORD(wParam)); } break; case WM_NOTIFY: if (lParam) { LPNMHDR pnmhdr = reinterpret_cast<LPNMHDR>(lParam); switch (pnmhdr->code) { case NM_CLICK: __fallthrough; case NM_RETURN: switch (static_cast<DWORD>(pnmhdr->idFrom)) { case ID_FAILURE_LOGFILE_LINK: pBA->OnClickLogFileLink(); return 1; } } } break; case WM_CTLCOLORSTATIC: case WM_CTLCOLORBTN: if (pBA) { HBRUSH brush = nullptr; if (pBA->SetControlColor((HWND)lParam, (HDC)wParam, &brush)) { return (LRESULT)brush; } } break; } if (pBA && pBA->_taskbarList && uMsg == pBA->_taskbarButtonCreatedMessage) { pBA->_taskbarButtonOK = TRUE; return 0; } return ThemeDefWindowProc(pBA ? pBA->_theme : nullptr, hWnd, uMsg, wParam, lParam); } // // OnCreate - finishes loading the theme. // BOOL OnCreate(__in HWND hWnd) { HRESULT hr = S_OK; hr = ThemeLoadControls(_theme, hWnd, CONTROL_ID_NAMES, countof(CONTROL_ID_NAMES)); BalExitOnFailure(hr, "Failed to load theme controls."); C_ASSERT(COUNT_PAGE == countof(PAGE_NAMES)); C_ASSERT(countof(_pageIds) == countof(PAGE_NAMES)); ThemeGetPageIds(_theme, PAGE_NAMES, _pageIds, countof(_pageIds)); // Initialize the text on all "application" (non-page) controls. for (DWORD i = 0; i < _theme->cControls; ++i) { THEME_CONTROL* pControl = _theme->rgControls + i; LPWSTR text = nullptr; LPWSTR name = nullptr; LOC_STRING *locText = nullptr; // If a command link has a note, then add it. if ((pControl->dwStyle & BS_TYPEMASK) == BS_COMMANDLINK || (pControl->dwStyle & BS_TYPEMASK) == BS_DEFCOMMANDLINK) { hr = StrAllocFormatted(&name, L"#(loc.%lsNote)", pControl->sczName); if (SUCCEEDED(hr)) { hr = LocGetString(_wixLoc, name, &locText); ReleaseStr(name); if (SUCCEEDED(hr) && locText && locText->wzText && locText->wzText[0]) { hr = BalFormatString(locText->wzText, &text); if (SUCCEEDED(hr) && text && text[0]) { ThemeSendControlMessage(_theme, pControl->wId, BCM_SETNOTE, 0, (LPARAM)text); ReleaseStr(text); text = nullptr; } } } hr = S_OK; } if (!pControl->wPageId && pControl->sczText && *pControl->sczText) { HRESULT hrFormat; // If the wix developer is showing a hidden variable in the UI, // then obviously they don't care about keeping it safe so don't // go down the rabbit hole of making sure that this is securely // freed. hrFormat = BalFormatString(pControl->sczText, &text); if (SUCCEEDED(hrFormat)) { ThemeSetTextControl(_theme, pControl->wId, text); ReleaseStr(text); } } } LExit: return SUCCEEDED(hr); } void RemapColor(COLORREF *fg, COLORREF *bg, HBRUSH *bgBrush) { if (*fg == RGB(0, 0, 0)) { *fg = GetSysColor(COLOR_WINDOWTEXT); } else if (*fg == RGB(128, 128, 128)) { *fg = GetSysColor(COLOR_GRAYTEXT); } if (*bgBrush && *bg == RGB(255, 255, 255)) { *bg = GetSysColor(COLOR_WINDOW); *bgBrush = GetSysColorBrush(COLOR_WINDOW); } } BOOL SetControlColor(HWND hWnd, HDC hDC, HBRUSH *brush) { for (int i = 0; i < _theme->cControls; ++i) { if (_theme->rgControls[i].hWnd != hWnd) { continue; } DWORD fontId = _theme->rgControls[i].dwFontId; if (fontId > _theme->cFonts) { fontId = 0; } THEME_FONT *fnt = &_theme->rgFonts[fontId]; COLORREF fg = fnt->crForeground, bg = fnt->crBackground; *brush = fnt->hBackground; RemapColor(&fg, &bg, brush); ::SetTextColor(hDC, fg); ::SetBkColor(hDC, bg); return TRUE; } return FALSE; } // // OnShowFailure - display the failure page. // void OnShowFailure() { SetState(PYBA_STATE_FAILED, S_OK); // If the UI should be visible, display it now and hide the splash screen if (BOOTSTRAPPER_DISPLAY_NONE < _command.display) { ::ShowWindow(_theme->hwndParent, SW_SHOW); } _engine->CloseSplashScreen(); return; } // // OnShowHelp - display the help page. // void OnShowHelp() { SetState(PYBA_STATE_HELP, S_OK); // If the UI should be visible, display it now and hide the splash screen if (BOOTSTRAPPER_DISPLAY_NONE < _command.display) { ::ShowWindow(_theme->hwndParent, SW_SHOW); } _engine->CloseSplashScreen(); return; } // // OnDetect - start the processing of packages. // void OnDetect() { HRESULT hr = S_OK; if (_baFunction) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running detect BA function"); hr = _baFunction->OnDetect(); BalExitOnFailure(hr, "Failed calling detect BA function."); } SetState(PYBA_STATE_DETECTING, hr); // If the UI should be visible, display it now and hide the splash screen if (BOOTSTRAPPER_DISPLAY_NONE < _command.display) { ::ShowWindow(_theme->hwndParent, SW_SHOW); } _engine->CloseSplashScreen(); // Tell the core we're ready for the packages to be processed now. hr = _engine->Detect(); BalExitOnFailure(hr, "Failed to start detecting chain."); LExit: if (FAILED(hr)) { SetState(PYBA_STATE_DETECTING, hr); } return; } HRESULT UpdateUIStrings(__in BOOTSTRAPPER_ACTION action) { HRESULT hr = S_OK; LPCWSTR likeInstalling = nullptr; LPCWSTR likeInstallation = nullptr; switch (action) { case BOOTSTRAPPER_ACTION_INSTALL: likeInstalling = L"Installing"; likeInstallation = L"Installation"; break; case BOOTSTRAPPER_ACTION_MODIFY: // For modify, we actually want to pass INSTALL action = BOOTSTRAPPER_ACTION_INSTALL; likeInstalling = L"Modifying"; likeInstallation = L"Modification"; break; case BOOTSTRAPPER_ACTION_REPAIR: likeInstalling = L"Repairing"; likeInstallation = L"Repair"; break; case BOOTSTRAPPER_ACTION_UNINSTALL: likeInstalling = L"Uninstalling"; likeInstallation = L"Uninstallation"; break; } if (likeInstalling) { LPWSTR locName = nullptr; LOC_STRING *locText = nullptr; hr = StrAllocFormatted(&locName, L"#(loc.%ls)", likeInstalling); if (SUCCEEDED(hr)) { hr = LocGetString(_wixLoc, locName, &locText); ReleaseStr(locName); } _engine->SetVariableString( L"ActionLikeInstalling", SUCCEEDED(hr) && locText ? locText->wzText : likeInstalling ); } if (likeInstallation) { LPWSTR locName = nullptr; LOC_STRING *locText = nullptr; hr = StrAllocFormatted(&locName, L"#(loc.%ls)", likeInstallation); if (SUCCEEDED(hr)) { hr = LocGetString(_wixLoc, locName, &locText); ReleaseStr(locName); } _engine->SetVariableString( L"ActionLikeInstallation", SUCCEEDED(hr) && locText ? locText->wzText : likeInstallation ); } return hr; } // // OnPlan - plan the detected changes. // void OnPlan(__in BOOTSTRAPPER_ACTION action) { HRESULT hr = S_OK; _plannedAction = action; hr = UpdateUIStrings(action); BalExitOnFailure(hr, "Failed to update strings"); // If we are going to apply a downgrade, bail. if (_downgradingOtherVersion && BOOTSTRAPPER_ACTION_UNINSTALL < action) { if (_suppressDowngradeFailure) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version of this product is installed but downgrade failure has been suppressed; continuing..."); } else { hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_VERSION); BalExitOnFailure(hr, "Cannot install a product when a newer version is installed."); } } SetState(PYBA_STATE_PLANNING, hr); if (_baFunction) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Running plan BA function"); _baFunction->OnPlan(); } hr = _engine->Plan(action); BalExitOnFailure(hr, "Failed to start planning packages."); LExit: if (FAILED(hr)) { SetState(PYBA_STATE_PLANNING, hr); } return; } // // OnApply - apply the packages. // void OnApply() { HRESULT hr = S_OK; SetState(PYBA_STATE_APPLYING, hr); SetProgressState(hr); SetTaskbarButtonProgress(0); hr = _engine->Apply(_hWnd); BalExitOnFailure(hr, "Failed to start applying packages."); ThemeControlEnable(_theme, ID_PROGRESS_CANCEL_BUTTON, TRUE); // ensure the cancel button is enabled before starting. LExit: if (FAILED(hr)) { SetState(PYBA_STATE_APPLYING, hr); } return; } // // OnChangeState - change state. // void OnChangeState(__in PYBA_STATE state) { LPWSTR unformattedText = nullptr; _state = state; // If our install is at the end (success or failure) and we're not showing full UI // then exit (prompt for restart if required). if ((PYBA_STATE_APPLIED <= _state && BOOTSTRAPPER_DISPLAY_FULL > _command.display)) { // If a restart was required but we were not automatically allowed to // accept the reboot then do the prompt. if (_restartRequired && !_allowRestart) { StrAllocFromError(&unformattedText, HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), nullptr); _allowRestart = IDOK == ::MessageBoxW( _hWnd, unformattedText ? unformattedText : L"The requested operation is successful. Changes will not be effective until the system is rebooted.", _theme->sczCaption, MB_ICONEXCLAMATION | MB_OKCANCEL ); } // Quietly exit. ::PostMessageW(_hWnd, WM_CLOSE, 0, 0); } else { // try to change the pages. DWORD newPageId = 0; DeterminePageId(_state, &newPageId); if (_visiblePageId != newPageId) { ShowPage(newPageId); } } ReleaseStr(unformattedText); } // // Called before showing a page to handle all controls. // void ProcessPageControls(THEME_PAGE *pPage) { if (!pPage) { return; } for (DWORD i = 0; i < pPage->cControlIndices; ++i) { THEME_CONTROL* pControl = _theme->rgControls + pPage->rgdwControlIndices[i]; BOOL enableControl = TRUE; // If this is a named control, try to set its default state. if (pControl->sczName && *pControl->sczName) { // If this is a checkable control, try to set its default state // to the state of a matching named Burn variable. if (IsCheckable(pControl)) { LONGLONG llValue = 0; HRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue); // If the control value isn't set then disable it. if (!SUCCEEDED(hr)) { enableControl = FALSE; } else { ThemeSendControlMessage( _theme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0 ); } } // Hide or disable controls based on the control name with 'State' appended LPWSTR controlName = nullptr; HRESULT hr = StrAllocFormatted(&controlName, L"%lsState", pControl->sczName); if (SUCCEEDED(hr)) { LPWSTR controlState = nullptr; hr = BalGetStringVariable(controlName, &controlState); if (SUCCEEDED(hr) && controlState && *controlState) { if (controlState[0] == '[') { LPWSTR formatted = nullptr; if (SUCCEEDED(BalFormatString(controlState, &formatted))) { StrFree(controlState); controlState = formatted; } } if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, controlState, -1, L"disable", -1)) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Disable control %ls", pControl->sczName); enableControl = FALSE; } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, controlState, -1, L"hide", -1)) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Hide control %ls", pControl->sczName); // TODO: This doesn't work ThemeShowControl(_theme, pControl->wId, SW_HIDE); } else { // An explicit state can override the lack of a // backing variable. enableControl = TRUE; } } StrFree(controlState); } StrFree(controlName); } ThemeControlEnable(_theme, pControl->wId, enableControl); // Format the text in each of the new page's controls if (pControl->sczText && *pControl->sczText) { // If the wix developer is showing a hidden variable // in the UI, then obviously they don't care about // keeping it safe so don't go down the rabbit hole // of making sure that this is securely freed. LPWSTR text = nullptr; HRESULT hr = BalFormatString(pControl->sczText, &text); if (SUCCEEDED(hr)) { ThemeSetTextControl(_theme, pControl->wId, text); } } } } // // OnClose - called when the window is trying to be closed. // BOOL OnClose() { BOOL close = FALSE; // If we've already succeeded or failed or showing the help page, just close (prompts are annoying if the bootstrapper is done). if (PYBA_STATE_APPLIED <= _state || PYBA_STATE_HELP == _state) { close = TRUE; } else { // prompt the user or force the cancel if there is no UI. close = PromptCancel( _hWnd, BOOTSTRAPPER_DISPLAY_FULL != _command.display, _confirmCloseMessage ? _confirmCloseMessage : L"Are you sure you want to cancel?", _theme->sczCaption ); } // If we're doing progress then we never close, we just cancel to let rollback occur. if (PYBA_STATE_APPLYING <= _state && PYBA_STATE_APPLIED > _state) { // If we canceled disable cancel button since clicking it again is silly. if (close) { ThemeControlEnable(_theme, ID_PROGRESS_CANCEL_BUTTON, FALSE); } close = FALSE; } return close; } // // OnClickCloseButton - close the application. // void OnClickCloseButton() { ::SendMessageW(_hWnd, WM_CLOSE, 0, 0); } // // OnClickLaunchButton - launch the app from the success page. // void OnClickLaunchButton() { HRESULT hr = S_OK; LPWSTR sczUnformattedLaunchTarget = nullptr; LPWSTR sczLaunchTarget = nullptr; LPWSTR sczLaunchTargetElevatedId = nullptr; LPWSTR sczUnformattedArguments = nullptr; LPWSTR sczArguments = nullptr; int nCmdShow = SW_SHOWNORMAL; hr = BalGetStringVariable(PYBA_VARIABLE_LAUNCH_TARGET_PATH, &sczUnformattedLaunchTarget); BalExitOnFailure1(hr, "Failed to get launch target variable '%ls'.", PYBA_VARIABLE_LAUNCH_TARGET_PATH); hr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget); BalExitOnFailure1(hr, "Failed to format launch target variable: %ls", sczUnformattedLaunchTarget); if (BalStringVariableExists(PYBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID)) { hr = BalGetStringVariable(PYBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID, &sczLaunchTargetElevatedId); BalExitOnFailure1(hr, "Failed to get launch target elevated id '%ls'.", PYBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID); } if (BalStringVariableExists(PYBA_VARIABLE_LAUNCH_ARGUMENTS)) { hr = BalGetStringVariable(PYBA_VARIABLE_LAUNCH_ARGUMENTS, &sczUnformattedArguments); BalExitOnFailure1(hr, "Failed to get launch arguments '%ls'.", PYBA_VARIABLE_LAUNCH_ARGUMENTS); } if (BalStringVariableExists(PYBA_VARIABLE_LAUNCH_HIDDEN)) { nCmdShow = SW_HIDE; } if (sczLaunchTargetElevatedId && !_triedToLaunchElevated) { _triedToLaunchElevated = TRUE; hr = _engine->LaunchApprovedExe(_hWnd, sczLaunchTargetElevatedId, sczUnformattedArguments, 0); if (FAILED(hr)) { BalLogError(hr, "Failed to launch elevated target: %ls", sczLaunchTargetElevatedId); //try with ShelExec next time OnClickLaunchButton(); } } else { if (sczUnformattedArguments) { hr = BalFormatString(sczUnformattedArguments, &sczArguments); BalExitOnFailure1(hr, "Failed to format launch arguments variable: %ls", sczUnformattedArguments); } hr = ShelExec(sczLaunchTarget, sczArguments, L"open", nullptr, nCmdShow, _hWnd, nullptr); BalExitOnFailure1(hr, "Failed to launch target: %ls", sczLaunchTarget); ::PostMessageW(_hWnd, WM_CLOSE, 0, 0); } LExit: StrSecureZeroFreeString(sczArguments); ReleaseStr(sczUnformattedArguments); ReleaseStr(sczLaunchTargetElevatedId); StrSecureZeroFreeString(sczLaunchTarget); ReleaseStr(sczUnformattedLaunchTarget); return; } // // OnClickRestartButton - allows the restart and closes the app. // void OnClickRestartButton() { AssertSz(_restartRequired, "Restart must be requested to be able to click on the restart button."); _allowRestart = TRUE; ::SendMessageW(_hWnd, WM_CLOSE, 0, 0); return; } // // OnClickLogFileLink - show the log file. // void OnClickLogFileLink() { HRESULT hr = S_OK; LPWSTR sczLogFile = nullptr; hr = BalGetStringVariable(_bundle.sczLogVariable, &sczLogFile); BalExitOnFailure1(hr, "Failed to get log file variable '%ls'.", _bundle.sczLogVariable); hr = ShelExec(L"notepad.exe", sczLogFile, L"open", nullptr, SW_SHOWDEFAULT, _hWnd, nullptr); BalExitOnFailure1(hr, "Failed to open log file target: %ls", sczLogFile); LExit: ReleaseStr(sczLogFile); return; } // // SetState // void SetState(__in PYBA_STATE state, __in HRESULT hrStatus) { if (FAILED(hrStatus)) { _hrFinal = hrStatus; } if (FAILED(_hrFinal)) { state = PYBA_STATE_FAILED; } if (_state != state) { ::PostMessageW(_hWnd, WM_PYBA_CHANGE_STATE, 0, state); } } // // GoToPage // void GoToPage(__in PAGE page) { _installPage = page; ::PostMessageW(_hWnd, WM_PYBA_CHANGE_STATE, 0, _state); } void DeterminePageId(__in PYBA_STATE state, __out DWORD* pdwPageId) { LONGLONG simple; if (BOOTSTRAPPER_DISPLAY_PASSIVE == _command.display) { switch (state) { case PYBA_STATE_INITIALIZED: *pdwPageId = BOOTSTRAPPER_ACTION_HELP == _command.action ? _pageIds[PAGE_HELP] : _pageIds[PAGE_LOADING]; break; case PYBA_STATE_HELP: *pdwPageId = _pageIds[PAGE_HELP]; break; case PYBA_STATE_DETECTING: *pdwPageId = _pageIds[PAGE_LOADING] ? _pageIds[PAGE_LOADING] : _pageIds[PAGE_PROGRESS_PASSIVE] ? _pageIds[PAGE_PROGRESS_PASSIVE] : _pageIds[PAGE_PROGRESS]; break; case PYBA_STATE_DETECTED: __fallthrough; case PYBA_STATE_PLANNING: __fallthrough; case PYBA_STATE_PLANNED: __fallthrough; case PYBA_STATE_APPLYING: __fallthrough; case PYBA_STATE_CACHING: __fallthrough; case PYBA_STATE_CACHED: __fallthrough; case PYBA_STATE_EXECUTING: __fallthrough; case PYBA_STATE_EXECUTED: *pdwPageId = _pageIds[PAGE_PROGRESS_PASSIVE] ? _pageIds[PAGE_PROGRESS_PASSIVE] : _pageIds[PAGE_PROGRESS]; break; default: *pdwPageId = 0; break; } } else if (BOOTSTRAPPER_DISPLAY_FULL == _command.display) { switch (state) { case PYBA_STATE_INITIALIZING: *pdwPageId = 0; break; case PYBA_STATE_INITIALIZED: *pdwPageId = BOOTSTRAPPER_ACTION_HELP == _command.action ? _pageIds[PAGE_HELP] : _pageIds[PAGE_LOADING]; break; case PYBA_STATE_HELP: *pdwPageId = _pageIds[PAGE_HELP]; break; case PYBA_STATE_DETECTING: *pdwPageId = _pageIds[PAGE_LOADING]; break; case PYBA_STATE_DETECTED: if (_installPage == PAGE_LOADING) { switch (_command.action) { case BOOTSTRAPPER_ACTION_INSTALL: if (_upgradingOldVersion) { _installPage = PAGE_UPGRADE; } else if (SUCCEEDED(BalGetNumericVariable(L"SimpleInstall", &simple)) && simple) { _installPage = PAGE_SIMPLE_INSTALL; } else { _installPage = PAGE_INSTALL; } break; case BOOTSTRAPPER_ACTION_MODIFY: __fallthrough; case BOOTSTRAPPER_ACTION_REPAIR: __fallthrough; case BOOTSTRAPPER_ACTION_UNINSTALL: _installPage = PAGE_MODIFY; break; } } *pdwPageId = _pageIds[_installPage]; break; case PYBA_STATE_PLANNING: __fallthrough; case PYBA_STATE_PLANNED: __fallthrough; case PYBA_STATE_APPLYING: __fallthrough; case PYBA_STATE_CACHING: __fallthrough; case PYBA_STATE_CACHED: __fallthrough; case PYBA_STATE_EXECUTING: __fallthrough; case PYBA_STATE_EXECUTED: *pdwPageId = _pageIds[PAGE_PROGRESS]; break; case PYBA_STATE_APPLIED: *pdwPageId = _pageIds[PAGE_SUCCESS]; break; case PYBA_STATE_FAILED: *pdwPageId = _pageIds[PAGE_FAILURE]; break; } } } BOOL WillElevate() { static BAL_CONDITION WILL_ELEVATE_CONDITION = { L"not WixBundleElevated and (InstallAllUsers or (InstallLauncherAllUsers and Include_launcher))", L"" }; BOOL result; return SUCCEEDED(BalConditionEvaluate(&WILL_ELEVATE_CONDITION, _engine, &result, nullptr)) && result; } BOOL IsCrtInstalled() { if (_crtInstalledToken > 0) { return TRUE; } else if (_crtInstalledToken == 0) { return FALSE; } // Check whether at least CRT v10.0.10137.0 is available. // It should only be installed as a Windows Update package, which means // we don't need to worry about 32-bit/64-bit. LPCWSTR crtFile = L"ucrtbase.dll"; DWORD cbVer = GetFileVersionInfoSizeW(crtFile, nullptr); if (!cbVer) { _crtInstalledToken = 0; return FALSE; } void *pData = malloc(cbVer); if (!pData) { _crtInstalledToken = 0; return FALSE; } if (!GetFileVersionInfoW(crtFile, 0, cbVer, pData)) { free(pData); _crtInstalledToken = 0; return FALSE; } VS_FIXEDFILEINFO *ffi; UINT cb; BOOL result = FALSE; if (VerQueryValueW(pData, L"\\", (LPVOID*)&ffi, &cb) && ffi->dwFileVersionMS == 0x000A0000 && ffi->dwFileVersionLS >= 0x27990000) { result = TRUE; } free(pData); _crtInstalledToken = result ? 1 : 0; return result; } BOOL QueryElevateForCrtInstall() { // Called to prompt the user that even though they think they won't need // to elevate, they actually will because of the CRT install. if (IsCrtInstalled()) { // CRT is already installed - no need to prompt return TRUE; } LONGLONG elevated; HRESULT hr = BalGetNumericVariable(L"WixBundleElevated", &elevated); if (SUCCEEDED(hr) && elevated) { // Already elevated - no need to prompt return TRUE; } LOC_STRING *locStr; hr = LocGetString(_wixLoc, L"#(loc.ElevateForCRTInstall)", &locStr); if (FAILED(hr)) { BalLogError(hr, "Failed to get ElevateForCRTInstall string"); return FALSE; } return ::MessageBoxW(_hWnd, locStr->wzText, _theme->sczCaption, MB_YESNO) != IDNO; } HRESULT EvaluateConditions() { HRESULT hr = S_OK; BOOL result = FALSE; for (DWORD i = 0; i < _conditions.cConditions; ++i) { BAL_CONDITION* pCondition = _conditions.rgConditions + i; hr = BalConditionEvaluate(pCondition, _engine, &result, &_failedMessage); BalExitOnFailure(hr, "Failed to evaluate condition."); if (!result) { // Hope they didn't have hidden variables in their message, because it's going in the log in plaintext. BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "%ls", _failedMessage); hr = E_WIXSTDBA_CONDITION_FAILED; // todo: remove in WiX v4, in case people are relying on v3.x logging behavior BalExitOnFailure1(hr, "Bundle condition evaluated to false: %ls", pCondition->sczCondition); } } ReleaseNullStrSecure(_failedMessage); LExit: return hr; } void SetTaskbarButtonProgress(__in DWORD dwOverallPercentage) { HRESULT hr = S_OK; if (_taskbarButtonOK) { hr = _taskbarList->SetProgressValue(_hWnd, dwOverallPercentage, 100UL); BalExitOnFailure1(hr, "Failed to set taskbar button progress to: %d%%.", dwOverallPercentage); } LExit: return; } void SetTaskbarButtonState(__in TBPFLAG tbpFlags) { HRESULT hr = S_OK; if (_taskbarButtonOK) { hr = _taskbarList->SetProgressState(_hWnd, tbpFlags); BalExitOnFailure1(hr, "Failed to set taskbar button state.", tbpFlags); } LExit: return; } void SetProgressState(__in HRESULT hrStatus) { TBPFLAG flag = TBPF_NORMAL; if (IsCanceled() || HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hrStatus) { flag = TBPF_PAUSED; } else if (IsRollingBack() || FAILED(hrStatus)) { flag = TBPF_ERROR; } SetTaskbarButtonState(flag); } HRESULT LoadBootstrapperBAFunctions() { HRESULT hr = S_OK; LPWSTR sczBafPath = nullptr; hr = PathRelativeToModule(&sczBafPath, L"bafunctions.dll", _hModule); BalExitOnFailure(hr, "Failed to get path to BA function DLL."); #ifdef DEBUG BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "PYBA: LoadBootstrapperBAFunctions() - BA function DLL %ls", sczBafPath); #endif _hBAFModule = ::LoadLibraryW(sczBafPath); if (_hBAFModule) { auto pfnBAFunctionCreate = reinterpret_cast<PFN_BOOTSTRAPPER_BA_FUNCTION_CREATE>(::GetProcAddress(_hBAFModule, "CreateBootstrapperBAFunction")); BalExitOnNullWithLastError1(pfnBAFunctionCreate, hr, "Failed to get CreateBootstrapperBAFunction entry-point from: %ls", sczBafPath); hr = pfnBAFunctionCreate(_engine, _hBAFModule, &_baFunction); BalExitOnFailure(hr, "Failed to create BA function."); } #ifdef DEBUG else { BalLogError(HRESULT_FROM_WIN32(::GetLastError()), "PYBA: LoadBootstrapperBAFunctions() - Failed to load DLL %ls", sczBafPath); } #endif LExit: if (_hBAFModule && !_baFunction) { ::FreeLibrary(_hBAFModule); _hBAFModule = nullptr; } ReleaseStr(sczBafPath); return hr; } BOOL IsCheckable(THEME_CONTROL* pControl) { if (!pControl->sczName || !pControl->sczName[0]) { return FALSE; } if (pControl->type == THEME_CONTROL_TYPE_CHECKBOX) { return TRUE; } if (pControl->type == THEME_CONTROL_TYPE_BUTTON) { if ((pControl->dwStyle & BS_TYPEMASK) == BS_AUTORADIOBUTTON) { return TRUE; } } return FALSE; } void SavePageSettings() { DWORD pageId = 0; THEME_PAGE* pPage = nullptr; DeterminePageId(_state, &pageId); pPage = ThemeGetPage(_theme, pageId); if (!pPage) { return; } for (DWORD i = 0; i < pPage->cControlIndices; ++i) { // Loop through all the checkable controls and set a Burn variable // with that name to true or false. THEME_CONTROL* pControl = _theme->rgControls + pPage->rgdwControlIndices[i]; if (IsCheckable(pControl) && ThemeControlEnabled(_theme, pControl->wId)) { BOOL checked = ThemeIsControlChecked(_theme, pControl->wId); _engine->SetVariableNumeric(pControl->sczName, checked ? 1 : 0); } // Loop through all the editbox controls with names and set a // Burn variable with that name to the contents. if (THEME_CONTROL_TYPE_EDITBOX == pControl->type && pControl->sczName && *pControl->sczName) { LPWSTR sczValue = nullptr; ThemeGetTextControl(_theme, pControl->wId, &sczValue); _engine->SetVariableString(pControl->sczName, sczValue); } } } static bool IsTargetPlatformx64(__in IBootstrapperEngine* pEngine) { WCHAR platform[8]; DWORD platformLen = 8; if (FAILED(pEngine->GetVariableString(L"TargetPlatform", platform, &platformLen))) { return S_FALSE; } return ::CompareStringW(LOCALE_NEUTRAL, 0, platform, -1, L"x64", -1) == CSTR_EQUAL; } static HRESULT LoadOptionalFeatureStatesFromKey( __in IBootstrapperEngine* pEngine, __in HKEY hkHive, __in LPCWSTR subkey ) { HKEY hKey; LRESULT res; if (IsTargetPlatformx64(pEngine)) { res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); } else { res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); } if (res == ERROR_FILE_NOT_FOUND) { return S_FALSE; } if (res != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(res); } for (auto p = OPTIONAL_FEATURES; p->regName; ++p) { res = RegQueryValueExW(hKey, p->regName, nullptr, nullptr, nullptr, nullptr); if (res == ERROR_FILE_NOT_FOUND) { pEngine->SetVariableNumeric(p->variableName, 0); } else if (res == ERROR_SUCCESS) { pEngine->SetVariableNumeric(p->variableName, 1); } else { RegCloseKey(hKey); return HRESULT_FROM_WIN32(res); } } RegCloseKey(hKey); return S_OK; } static HRESULT LoadTargetDirFromKey( __in IBootstrapperEngine* pEngine, __in HKEY hkHive, __in LPCWSTR subkey ) { HKEY hKey; LRESULT res; DWORD dataType; BYTE buffer[1024]; DWORD bufferLen = sizeof(buffer); if (IsTargetPlatformx64(pEngine)) { res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); } else { res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); } if (res == ERROR_FILE_NOT_FOUND) { return S_FALSE; } if (res != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(res); } res = RegQueryValueExW(hKey, nullptr, nullptr, &dataType, buffer, &bufferLen); if (res == ERROR_SUCCESS && dataType == REG_SZ && bufferLen < sizeof(buffer)) { pEngine->SetVariableString(L"TargetDir", reinterpret_cast<wchar_t*>(buffer)); } RegCloseKey(hKey); return HRESULT_FROM_WIN32(res); } static HRESULT LoadLauncherStateFromKey( __in IBootstrapperEngine* pEngine, __in HKEY hkHive ) { const LPCWSTR subkey = L"Software\\Python\\PyLauncher"; HKEY hKey; LRESULT res; if (IsTargetPlatformx64(pEngine)) { res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); } else { res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); } if (res == ERROR_FILE_NOT_FOUND) { return S_FALSE; } if (res != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(res); } res = RegQueryValueExW(hKey, nullptr, nullptr, nullptr, nullptr, nullptr); if (res == ERROR_FILE_NOT_FOUND) { pEngine->SetVariableNumeric(L"Include_launcher", 0); } else if (res == ERROR_SUCCESS) { pEngine->SetVariableNumeric(L"Include_launcher", 1); } res = RegQueryValueExW(hKey, L"AssociateFiles", nullptr, nullptr, nullptr, nullptr); if (res == ERROR_FILE_NOT_FOUND) { pEngine->SetVariableNumeric(L"AssociateFiles", 0); } else if (res == ERROR_SUCCESS) { pEngine->SetVariableNumeric(L"AssociateFiles", 1); } RegCloseKey(hKey); return S_OK; } static void LoadOptionalFeatureStates(__in IBootstrapperEngine* pEngine) { WCHAR subkeyFmt[256]; WCHAR subkey[256]; DWORD subkeyLen; HRESULT hr; HKEY hkHive; // The launcher installation is separate from the Python install, so we // check its state later. This also checks the file association option. // Get the registry key from the bundle, to save having to duplicate it // in multiple places. subkeyLen = sizeof(subkeyFmt) / sizeof(subkeyFmt[0]); hr = pEngine->GetVariableString(L"OptionalFeaturesRegistryKey", subkeyFmt, &subkeyLen); BalExitOnFailure(hr, "Failed to locate registry key"); subkeyLen = sizeof(subkey) / sizeof(subkey[0]); hr = pEngine->FormatString(subkeyFmt, subkey, &subkeyLen); BalExitOnFailure1(hr, "Failed to format %ls", subkeyFmt); // Check the current user's registry for existing features hkHive = HKEY_CURRENT_USER; hr = LoadOptionalFeatureStatesFromKey(pEngine, hkHive, subkey); BalExitOnFailure1(hr, "Failed to read from HKCU\\%ls", subkey); if (hr == S_FALSE) { // Now check the local machine registry hkHive = HKEY_LOCAL_MACHINE; hr = LoadOptionalFeatureStatesFromKey(pEngine, hkHive, subkey); BalExitOnFailure1(hr, "Failed to read from HKLM\\%ls", subkey); if (hr == S_OK) { // Found a system-wide install, so enable these settings. pEngine->SetVariableNumeric(L"InstallAllUsers", 1); pEngine->SetVariableNumeric(L"CompileAll", 1); } } if (hr == S_OK) { // Cannot change InstallAllUsersState when upgrading. While there's // no good reason to not allow installing a per-user and an all-user // version simultaneously, Burn can't handle the state management // and will need to uninstall the old one. pEngine->SetVariableString(L"InstallAllUsersState", L"disable"); // Get the previous install directory. This can be changed by the // user. subkeyLen = sizeof(subkeyFmt) / sizeof(subkeyFmt[0]); hr = pEngine->GetVariableString(L"TargetDirRegistryKey", subkeyFmt, &subkeyLen); BalExitOnFailure(hr, "Failed to locate registry key"); subkeyLen = sizeof(subkey) / sizeof(subkey[0]); hr = pEngine->FormatString(subkeyFmt, subkey, &subkeyLen); BalExitOnFailure1(hr, "Failed to format %ls", subkeyFmt); LoadTargetDirFromKey(pEngine, hkHive, subkey); } LExit: return; } public: // // Constructor - initialize member variables. // PythonBootstrapperApplication( __in HMODULE hModule, __in BOOL fPrereq, __in HRESULT hrHostInitialization, __in IBootstrapperEngine* pEngine, __in const BOOTSTRAPPER_COMMAND* pCommand ) : CBalBaseBootstrapperApplication(pEngine, pCommand, 3, 3000) { _hModule = hModule; memcpy_s(&_command, sizeof(_command), pCommand, sizeof(BOOTSTRAPPER_COMMAND)); LONGLONG llInstalled = 0; HRESULT hr = BalGetNumericVariable(L"WixBundleInstalled", &llInstalled); if (SUCCEEDED(hr) && BOOTSTRAPPER_RESUME_TYPE_REBOOT != _command.resumeType && 0 < llInstalled && BOOTSTRAPPER_ACTION_INSTALL == _command.action) { _command.action = BOOTSTRAPPER_ACTION_MODIFY; } else if (0 == llInstalled && (BOOTSTRAPPER_ACTION_MODIFY == _command.action || BOOTSTRAPPER_ACTION_REPAIR == _command.action)) { _command.action = BOOTSTRAPPER_ACTION_INSTALL; } _plannedAction = BOOTSTRAPPER_ACTION_UNKNOWN; // When resuming from restart doing some install-like operation, try to find the package that forced the // restart. We'll use this information during planning. _nextPackageAfterRestart = nullptr; if (BOOTSTRAPPER_RESUME_TYPE_REBOOT == _command.resumeType && BOOTSTRAPPER_ACTION_UNINSTALL < _command.action) { // Ensure the forced restart package variable is null when it is an empty string. HRESULT hr = BalGetStringVariable(L"WixBundleForcedRestartPackage", &_nextPackageAfterRestart); if (FAILED(hr) || !_nextPackageAfterRestart || !*_nextPackageAfterRestart) { ReleaseNullStr(_nextPackageAfterRestart); } } _crtInstalledToken = -1; pEngine->SetVariableNumeric(L"CRTInstalled", IsCrtInstalled() ? 1 : 0); _wixLoc = nullptr; memset(&_bundle, 0, sizeof(_bundle)); memset(&_conditions, 0, sizeof(_conditions)); _confirmCloseMessage = nullptr; _failedMessage = nullptr; _language = nullptr; _theme = nullptr; memset(_pageIds, 0, sizeof(_pageIds)); _hUiThread = nullptr; _registered = FALSE; _hWnd = nullptr; _state = PYBA_STATE_INITIALIZING; _visiblePageId = 0; _installPage = PAGE_LOADING; _hrFinal = hrHostInitialization; _downgradingOtherVersion = FALSE; _upgradingOldVersion = FALSE; _restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; _restartRequired = FALSE; _allowRestart = FALSE; _suppressDowngradeFailure = FALSE; _suppressRepair = FALSE; _modifying = FALSE; _overridableVariables = nullptr; _taskbarList = nullptr; _taskbarButtonCreatedMessage = UINT_MAX; _taskbarButtonOK = FALSE; _showingInternalUIThisPackage = FALSE; _triedToLaunchElevated = FALSE; _suppressPaint = FALSE; pEngine->AddRef(); _engine = pEngine; _hBAFModule = nullptr; _baFunction = nullptr; LoadOptionalFeatureStates(pEngine); } // // Destructor - release member variables. // ~PythonBootstrapperApplication() { AssertSz(!::IsWindow(_hWnd), "Window should have been destroyed before destructor."); AssertSz(!_theme, "Theme should have been released before destructor."); ReleaseObject(_taskbarList); ReleaseDict(_overridableVariables); ReleaseStr(_failedMessage); ReleaseStr(_confirmCloseMessage); BalConditionsUninitialize(&_conditions); BalInfoUninitialize(&_bundle); LocFree(_wixLoc); ReleaseStr(_language); ReleaseStr(_nextPackageAfterRestart); ReleaseNullObject(_engine); if (_hBAFModule) { ::FreeLibrary(_hBAFModule); _hBAFModule = nullptr; } } private: HMODULE _hModule; BOOTSTRAPPER_COMMAND _command; IBootstrapperEngine* _engine; BOOTSTRAPPER_ACTION _plannedAction; LPWSTR _nextPackageAfterRestart; WIX_LOCALIZATION* _wixLoc; BAL_INFO_BUNDLE _bundle; BAL_CONDITIONS _conditions; LPWSTR _failedMessage; LPWSTR _confirmCloseMessage; LPWSTR _language; THEME* _theme; DWORD _pageIds[countof(PAGE_NAMES)]; HANDLE _hUiThread; BOOL _registered; HWND _hWnd; PYBA_STATE _state; HRESULT _hrFinal; DWORD _visiblePageId; PAGE _installPage; BOOL _startedExecution; DWORD _calculatedCacheProgress; DWORD _calculatedExecuteProgress; BOOL _downgradingOtherVersion; BOOL _upgradingOldVersion; BOOTSTRAPPER_APPLY_RESTART _restartResult; BOOL _restartRequired; BOOL _allowRestart; BOOL _suppressDowngradeFailure; BOOL _suppressRepair; BOOL _modifying; int _crtInstalledToken; STRINGDICT_HANDLE _overridableVariables; ITaskbarList3* _taskbarList; UINT _taskbarButtonCreatedMessage; BOOL _taskbarButtonOK; BOOL _showingInternalUIThisPackage; BOOL _triedToLaunchElevated; BOOL _suppressPaint; HMODULE _hBAFModule; IBootstrapperBAFunction* _baFunction; }; // // CreateBootstrapperApplication - creates a new IBootstrapperApplication object. // HRESULT CreateBootstrapperApplication( __in HMODULE hModule, __in BOOL fPrereq, __in HRESULT hrHostInitialization, __in IBootstrapperEngine* pEngine, __in const BOOTSTRAPPER_COMMAND* pCommand, __out IBootstrapperApplication** ppApplication ) { HRESULT hr = S_OK; if (fPrereq) { hr = E_INVALIDARG; ExitWithLastError(hr, "Failed to create UI thread."); } PythonBootstrapperApplication* pApplication = nullptr; pApplication = new PythonBootstrapperApplication(hModule, fPrereq, hrHostInitialization, pEngine, pCommand); ExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object."); *ppApplication = pApplication; pApplication = nullptr; LExit: ReleaseObject(pApplication); return hr; }