static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) { CharDriverState *chr; WinStdioCharState *stdio; DWORD dwMode; int is_console = 0; chr = g_malloc0(sizeof(CharDriverState)); stdio = g_malloc0(sizeof(WinStdioCharState)); stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE); if (stdio->hStdIn == INVALID_HANDLE_VALUE) { fprintf(stderr, "cannot open stdio: invalid handle\n"); exit(1); } is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0; chr->opaque = stdio; chr->chr_write = win_stdio_write; chr->chr_close = win_stdio_close; if (is_console) { if (qemu_add_wait_object(stdio->hStdIn, win_stdio_wait_func, chr)) { fprintf(stderr, "qemu_add_wait_object: failed\n"); } } else { DWORD dwId; stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread, chr, 0, &dwId); if (stdio->hInputThread == INVALID_HANDLE_VALUE || stdio->hInputReadyEvent == INVALID_HANDLE_VALUE || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) { fprintf(stderr, "cannot create stdio thread or event\n"); exit(1); } if (qemu_add_wait_object(stdio->hInputReadyEvent, win_stdio_thread_wait_func, chr)) { fprintf(stderr, "qemu_add_wait_object: failed\n"); } } dwMode |= ENABLE_LINE_INPUT; if (is_console) { /* set the terminal in raw mode */ /* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */ dwMode |= ENABLE_PROCESSED_INPUT; } SetConsoleMode(stdio->hStdIn, dwMode); chr->chr_set_echo = qemu_chr_set_echo_win_stdio; qemu_chr_fe_set_echo(chr, false); return chr; }