1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include <windows.h>
6
7 static char buf[256];
8 static DWORD read_count;
9 static DWORD write_count;
10 static HANDLE stdin_h;
11 static OVERLAPPED stdin_o;
12
die(const char * buf)13 static void die(const char* buf) {
14 fprintf(stderr, "%s\n", buf);
15 fflush(stderr);
16 exit(100);
17 }
18
overlapped_read(void)19 static void overlapped_read(void) {
20 if (ReadFile(stdin_h, buf, sizeof(buf), NULL, &stdin_o)) {
21 // Since we start the read operation immediately before requesting a write,
22 // it should never complete synchronously since no data would be available
23 die("read completed synchronously");
24 }
25 if (GetLastError() != ERROR_IO_PENDING) {
26 die("overlapped read failed");
27 }
28 }
29
write(const char * buf,size_t buf_size)30 static void write(const char* buf, size_t buf_size) {
31 overlapped_read();
32 DWORD write_count;
33 HANDLE stdout_h = GetStdHandle(STD_OUTPUT_HANDLE);
34 if (!WriteFile(stdout_h, buf, buf_size, &write_count, NULL)) {
35 die("overlapped write failed");
36 }
37 fprintf(stderr, "%d", write_count);
38 fflush(stderr);
39 }
40
main(void)41 int main(void) {
42 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
43 if (event == NULL) {
44 die("failed to create event handle");
45 }
46
47 stdin_h = GetStdHandle(STD_INPUT_HANDLE);
48 stdin_o.hEvent = event;
49
50 write("0", 1);
51
52 while (1) {
53 DWORD result = WaitForSingleObject(event, INFINITE);
54 if (result == WAIT_OBJECT_0) {
55 if (!GetOverlappedResult(stdin_h, &stdin_o, &read_count, FALSE)) {
56 die("failed to get overlapped read result");
57 }
58 if (strncmp(buf, "exit", read_count) == 0) {
59 break;
60 }
61 write(buf, read_count);
62 } else {
63 char emsg[0xfff];
64 int ecode = GetLastError();
65 DWORD rv = FormatMessage(
66 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
67 NULL,
68 ecode,
69 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
70 (LPSTR)emsg,
71 sizeof(emsg),
72 NULL);
73 if (rv > 0) {
74 snprintf(emsg, sizeof(emsg),
75 "WaitForSingleObject failed. Error %d (%s)", ecode, emsg);
76 } else {
77 snprintf(emsg, sizeof(emsg),
78 "WaitForSingleObject failed. Error %d", ecode);
79 }
80 die(emsg);
81 }
82 }
83
84 return 0;
85 }
86