1 |
|
2 |
|
3 | #include <windows.h>
|
4 | #include <assert.h>
|
5 | #include <stdio.h>
|
6 | #include <string.h>
|
7 | #include <wchar.h>
|
8 | #include <vector>
|
9 | #include <string>
|
10 |
|
11 | #include "../src/shared/DebugClient.h"
|
12 | #include "../src/shared/TimeMeasurement.h"
|
13 |
|
14 | #include "../src/shared/DebugClient.cc"
|
15 | #include "../src/shared/WinptyAssert.cc"
|
16 | #include "../src/shared/WinptyException.cc"
|
17 |
|
18 |
|
19 | static void startChildProcess(const wchar_t *args) {
|
20 | wchar_t program[1024];
|
21 | wchar_t cmdline[1024];
|
22 | GetModuleFileNameW(NULL, program, 1024);
|
23 | swprintf(cmdline, L"\"%ls\" %ls", program, args);
|
24 |
|
25 | STARTUPINFOW sui;
|
26 | PROCESS_INFORMATION pi;
|
27 | memset(&sui, 0, sizeof(sui));
|
28 | memset(&pi, 0, sizeof(pi));
|
29 | sui.cb = sizeof(sui);
|
30 |
|
31 | CreateProcessW(program, cmdline,
|
32 | NULL, NULL,
|
33 | FALSE,
|
34 | CREATE_NEW_CONSOLE,
|
35 | NULL, NULL,
|
36 | &sui, &pi);
|
37 | }
|
38 |
|
39 | static void setBufferSize(HANDLE conout, int x, int y) {
|
40 | COORD size = { static_cast<SHORT>(x), static_cast<SHORT>(y) };
|
41 | BOOL success = SetConsoleScreenBufferSize(conout, size);
|
42 | trace("setBufferSize: (%d,%d), result=%d", x, y, success);
|
43 | }
|
44 |
|
45 | static void setWindowPos(HANDLE conout, int x, int y, int w, int h) {
|
46 | SMALL_RECT r = {
|
47 | static_cast<SHORT>(x), static_cast<SHORT>(y),
|
48 | static_cast<SHORT>(x + w - 1),
|
49 | static_cast<SHORT>(y + h - 1)
|
50 | };
|
51 | BOOL success = SetConsoleWindowInfo(conout, TRUE, &r);
|
52 | trace("setWindowPos: (%d,%d,%d,%d), result=%d", x, y, w, h, success);
|
53 | }
|
54 |
|
55 | static void setCursorPos(HANDLE conout, int x, int y) {
|
56 | COORD coord = { static_cast<SHORT>(x), static_cast<SHORT>(y) };
|
57 | SetConsoleCursorPosition(conout, coord);
|
58 | }
|
59 |
|
60 | static void setBufferSize(int x, int y) {
|
61 | setBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), x, y);
|
62 | }
|
63 |
|
64 | static void setWindowPos(int x, int y, int w, int h) {
|
65 | setWindowPos(GetStdHandle(STD_OUTPUT_HANDLE), x, y, w, h);
|
66 | }
|
67 |
|
68 | static void setCursorPos(int x, int y) {
|
69 | setCursorPos(GetStdHandle(STD_OUTPUT_HANDLE), x, y);
|
70 | }
|
71 |
|
72 | static void countDown(int sec) {
|
73 | for (int i = sec; i > 0; --i) {
|
74 | printf("%d.. ", i);
|
75 | fflush(stdout);
|
76 | Sleep(1000);
|
77 | }
|
78 | printf("\n");
|
79 | }
|
80 |
|
81 | static void writeBox(int x, int y, int w, int h, char ch, int attributes=7) {
|
82 | CHAR_INFO info = { 0 };
|
83 | info.Char.AsciiChar = ch;
|
84 | info.Attributes = attributes;
|
85 | std::vector<CHAR_INFO> buf(w * h, info);
|
86 | HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE);
|
87 | COORD bufSize = { static_cast<SHORT>(w), static_cast<SHORT>(h) };
|
88 | COORD bufCoord = { 0, 0 };
|
89 | SMALL_RECT writeRegion = {
|
90 | static_cast<SHORT>(x),
|
91 | static_cast<SHORT>(y),
|
92 | static_cast<SHORT>(x + w - 1),
|
93 | static_cast<SHORT>(y + h - 1)
|
94 | };
|
95 | WriteConsoleOutputA(conout, buf.data(), bufSize, bufCoord, &writeRegion);
|
96 | }
|
97 |
|
98 | static void setChar(int x, int y, char ch, int attributes=7) {
|
99 | writeBox(x, y, 1, 1, ch, attributes);
|
100 | }
|
101 |
|
102 | static void fillChar(int x, int y, int repeat, char ch) {
|
103 | COORD coord = { static_cast<SHORT>(x), static_cast<SHORT>(y) };
|
104 | DWORD actual = 0;
|
105 | FillConsoleOutputCharacterA(
|
106 | GetStdHandle(STD_OUTPUT_HANDLE),
|
107 | ch, repeat, coord, &actual);
|
108 | }
|
109 |
|
110 | static void repeatChar(int count, char ch) {
|
111 | for (int i = 0; i < count; ++i) {
|
112 | putchar(ch);
|
113 | }
|
114 | fflush(stdout);
|
115 | }
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 | static void cvfprintf(HANDLE conout, const wchar_t *fmt, va_list ap) {
|
123 | wchar_t buffer[256];
|
124 | vswprintf(buffer, 256 - 1, fmt, ap);
|
125 | buffer[255] = L'\0';
|
126 | DWORD actual = 0;
|
127 | if (!WriteConsoleW(conout, buffer, wcslen(buffer), &actual, NULL)) {
|
128 | wprintf(L"WriteConsoleW call failed!\n");
|
129 | }
|
130 | }
|
131 |
|
132 | static void cfprintf(HANDLE conout, const wchar_t *fmt, ...) {
|
133 | va_list ap;
|
134 | va_start(ap, fmt);
|
135 | cvfprintf(conout, fmt, ap);
|
136 | va_end(ap);
|
137 | }
|
138 |
|
139 | static void cprintf(const wchar_t *fmt, ...) {
|
140 | va_list ap;
|
141 | va_start(ap, fmt);
|
142 | cvfprintf(GetStdHandle(STD_OUTPUT_HANDLE), fmt, ap);
|
143 | va_end(ap);
|
144 | }
|
145 |
|
146 | static std::string narrowString(const std::wstring &input)
|
147 | {
|
148 | int mblen = WideCharToMultiByte(
|
149 | CP_UTF8, 0,
|
150 | input.data(), input.size(),
|
151 | NULL, 0, NULL, NULL);
|
152 | if (mblen <= 0) {
|
153 | return std::string();
|
154 | }
|
155 | std::vector<char> tmp(mblen);
|
156 | int mblen2 = WideCharToMultiByte(
|
157 | CP_UTF8, 0,
|
158 | input.data(), input.size(),
|
159 | tmp.data(), tmp.size(),
|
160 | NULL, NULL);
|
161 | assert(mblen2 == mblen);
|
162 | return std::string(tmp.data(), tmp.size());
|
163 | }
|
164 |
|
165 | HANDLE openConout() {
|
166 | const HANDLE conout = CreateFileW(L"CONOUT$",
|
167 | GENERIC_READ | GENERIC_WRITE,
|
168 | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
169 | NULL, OPEN_EXISTING, 0, NULL);
|
170 | ASSERT(conout != INVALID_HANDLE_VALUE);
|
171 | return conout;
|
172 | }
|