Fix CreateProcess_UseStdHandles on Win8 and fix the spec.

* The NULL-to-new-handle conversion only happens when creating a new
   console, not when attaching to the parent's console.

 * Also, Windows reports that the handle value 0x7 is value, presumably
   because it ignores the lowest 2 bits.  It's better to just remove those
   values from this test.
This commit is contained in:
Ryan Prichard 2015-10-25 17:37:06 -05:00
parent 9260d0b54e
commit 955b5c61c3
2 changed files with 25 additions and 19 deletions

View File

@ -15,7 +15,7 @@
// in STARTUPINFO, without exception. Starting with Windows 8, the STARTUPINFO
// handles are ignored with bInheritHandles=FALSE, and even with
// bInheritHandles=TRUE, a NULL hStd{Input,Output,Error} field is translated to
// a new, open handle.
// a new open handle if a new console is being created.
template <typename T>
void checkVariousInputs(T check) {
@ -59,23 +59,18 @@ void checkVariousInputs(T check) {
});
}
{
// Invalid (or potentially invalid) handles.
// Invalid handles.
Worker p;
check(p, {
Handle::invent(nullptr, p),
Handle::invent(0x10000ull, p),
Handle::invent(0xdeadbeefull, p),
Handle::invent(0xdeadbeecull, p),
});
check(p, {
Handle::invent(INVALID_HANDLE_VALUE, p),
Handle::invent(nullptr, p),
Handle::invent(nullptr, p),
});
check(p, {
Handle::invent(3ull, p),
Handle::invent(7ull, p),
Handle::invent(11ull, p),
});
check(p, {
Handle::invent(nullptr, p),
Handle::invent(nullptr, p),
@ -109,6 +104,9 @@ static void Test_CreateProcess_UseStdHandles() {
checkVariousInputs([](Worker &p, std::vector<Handle> newHandles) {
ASSERT(newHandles.size() == 3);
auto check = [&](Worker &c, bool inheritHandles, bool newConsole) {
trace("Test_CreateProcess_UseStdHandles: "
"inheritHandles=%d newConsole=%d",
inheritHandles, newConsole);
auto childHandles = stdHandles(c);
if (isTraditionalConio()) {
CHECK(handleValues(stdHandles(c)) == handleValues(newHandles));
@ -141,7 +139,7 @@ static void Test_CreateProcess_UseStdHandles() {
// values we test for. (i.e. There could be some
// handle H to object O that isn't inherited, but by
// sheer conincidence, the child gets a handle H that
// also refers to O. e.g. Windows internal objects.
// also refers to O. (e.g. Windows internal objects.)
// This test case works because we know that Windows
// won't create a reference to our test objects.)
CHECK(snap.eq(newHandles[i], childHandles[i]) ==
@ -158,7 +156,7 @@ static void Test_CreateProcess_UseStdHandles() {
// The parent's standard handle is used, without
// validation or duplication. It is not inherited
// simply because it is listed in STARTUPINFO.
if (newHandles[i].value() == nullptr) {
if (newConsole && newHandles[i].value() == nullptr) {
// If the handle is NULL, though, then Windows
// instead opens a new console handle. It's
// checked below.
@ -166,16 +164,22 @@ static void Test_CreateProcess_UseStdHandles() {
}
CHECK(childHandles[i].value() ==
newHandles[i].value());
if (newHandles[i].tryFlags()) {
if (newHandles[i].value() == INVALID_HANDLE_VALUE) {
// The test below does not work on the current
// process pseudo-handle (aka
// INVALID_HANDLE_VALUE).
} else if (newHandles[i].tryFlags()) {
CHECK(snap.eq(newHandles[i], childHandles[i]) ==
newHandles[i].inheritable());
}
}
checkModernConsoleHandleInit(c,
newHandles[0].value() == nullptr,
newHandles[1].value() == nullptr,
newHandles[2].value() == nullptr,
nonReuseCheck);
if (newConsole) {
checkModernConsoleHandleInit(c,
newHandles[0].value() == nullptr,
newHandles[1].value() == nullptr,
newHandles[2].value() == nullptr,
nonReuseCheck);
}
} else {
if (!newConsole) {
CHECK(handleInts(stdHandles(c)) ==

View File

@ -222,11 +222,13 @@ Starting in Windows 8, `CreateProcess` sets standard handles as follows:
- Regardless of *ConsoleCreationMode*, if *InheritHandles* and
*UseStdHandles*, then handles are set according to `STARTUPINFO`,
except that each `NULL` handle is replaced with a new console
handle. As with previous releases, Windows makes no effort to validate
the handle, nor will it treat a non-inheritable handle as inheritable
As with previous releases, Windows makes no effort to validate the
handle, nor will it treat a non-inheritable handle as inheritable
simply because it is listed in `STARTUPINFO`.
If the *ConsoleCreationMode* is *NewConsole* or *NewConsoleNoWindow*, then
Windows replaces any `NULL` standard handle with a new console handle.
Otherwise, find the next applicable rule.
- If *ConsoleCreationMode* is *NewConsole* or *NewConsoleNoWindow*, then