• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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