+++ /dev/null
-#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;
-}