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