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:
parent
9260d0b54e
commit
955b5c61c3
@ -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)) ==
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user