File size: 4,640 Bytes
19605ab |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
#include <windows.h>
#include "TestUtil.cc"
const char *g_prefix = "";
static void dumpHandles() {
trace("%sSTDIN=0x%I64x STDOUT=0x%I64x STDERR=0x%I64x",
g_prefix,
(long long)GetStdHandle(STD_INPUT_HANDLE),
(long long)GetStdHandle(STD_OUTPUT_HANDLE),
(long long)GetStdHandle(STD_ERROR_HANDLE));
}
static HANDLE createBuffer() {
// If sa isn't provided, the handle defaults to not-inheritable.
SECURITY_ATTRIBUTES sa = {0};
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
trace("%sCreating a new buffer...", g_prefix);
HANDLE conout = CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
&sa,
CONSOLE_TEXTMODE_BUFFER, NULL);
trace("%sCreating a new buffer... 0x%I64x", g_prefix, (long long)conout);
return conout;
}
static const char *successOrFail(BOOL ret) {
return ret ? "ok" : "FAILED";
}
static void setConsoleActiveScreenBuffer(HANDLE conout) {
trace("%sSetConsoleActiveScreenBuffer(0x%I64x) called...",
g_prefix, (long long)conout);
trace("%sSetConsoleActiveScreenBuffer(0x%I64x) called... %s",
g_prefix, (long long)conout,
successOrFail(SetConsoleActiveScreenBuffer(conout)));
}
static void writeTest(HANDLE conout, const char *msg) {
char writeData[256];
sprintf(writeData, "%s%s\n", g_prefix, msg);
trace("%sWriting to 0x%I64x: '%s'...",
g_prefix, (long long)conout, msg);
DWORD actual = 0;
BOOL ret = WriteConsoleA(conout, writeData, strlen(writeData), &actual, NULL);
trace("%sWriting to 0x%I64x: '%s'... %s",
g_prefix, (long long)conout, msg,
successOrFail(ret && actual == strlen(writeData)));
}
static HANDLE startChildInSameConsole(const wchar_t *args, BOOL
bInheritHandles=FALSE) {
wchar_t program[1024];
wchar_t cmdline[1024];
GetModuleFileNameW(NULL, program, 1024);
swprintf(cmdline, L"\"%ls\" %ls", program, args);
STARTUPINFOW sui;
PROCESS_INFORMATION pi;
memset(&sui, 0, sizeof(sui));
memset(&pi, 0, sizeof(pi));
sui.cb = sizeof(sui);
CreateProcessW(program, cmdline,
NULL, NULL,
/*bInheritHandles=*/bInheritHandles,
/*dwCreationFlags=*/0,
NULL, NULL,
&sui, &pi);
return pi.hProcess;
}
static HANDLE dup(HANDLE h, HANDLE targetProcess) {
HANDLE h2 = INVALID_HANDLE_VALUE;
BOOL ret = DuplicateHandle(
GetCurrentProcess(), h,
targetProcess, &h2,
0, TRUE, DUPLICATE_SAME_ACCESS);
trace("dup(0x%I64x) to process 0x%I64x... %s, 0x%I64x",
(long long)h,
(long long)targetProcess,
successOrFail(ret),
(long long)h2);
return h2;
}
int main(int argc, char *argv[]) {
if (argc == 1) {
startChildProcess(L"parent");
return 0;
}
if (!strcmp(argv[1], "parent")) {
g_prefix = "parent: ";
dumpHandles();
HANDLE hChild = startChildInSameConsole(L"child");
// Windows 10.
HANDLE orig1 = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE new1 = createBuffer();
Sleep(2000);
setConsoleActiveScreenBuffer(new1);
// Handle duplication results to child process in same console:
// - Windows XP: fails
// - Windows 7 Ultimate SP1 32-bit: fails
// - Windows Server 2008 R2 Datacenter SP1 64-bit: fails
// - Windows 8 Enterprise 32-bit: succeeds
// - Windows 10: succeeds
HANDLE orig2 = dup(orig1, GetCurrentProcess());
HANDLE new2 = dup(new1, GetCurrentProcess());
dup(orig1, hChild);
dup(new1, hChild);
// The writes to orig1/orig2 are invisible. The writes to new1/new2
// are visible.
writeTest(orig1, "write to orig1");
writeTest(orig2, "write to orig2");
writeTest(new1, "write to new1");
writeTest(new2, "write to new2");
Sleep(120000);
return 0;
}
if (!strcmp(argv[1], "child")) {
g_prefix = "child: ";
dumpHandles();
Sleep(4000);
for (unsigned int i = 0x1; i <= 0xB0; ++i) {
char msg[256];
sprintf(msg, "Write to handle 0x%x", i);
HANDLE h = reinterpret_cast<HANDLE>(i);
writeTest(h, msg);
}
Sleep(120000);
return 0;
}
return 0;
}
|