I'm trying to get GenerateConsoleCtrlEvent to work. This is the minimal example I've come up with:
#include <Windows.h>
static BOOL WINAPI handler(DWORD CtrlType)
{
    return TRUE;
}
int main()
{
    if (!SetConsoleCtrlHandler(&handler, TRUE))
    {
        throw 1;
    }
    STARTUPINFO si = {0};
    DWORD dwStartupFlags = 0;
    PROCESS_INFORMATION pi;
    if (!CreateProcess(
        NULL,
        "cmd.exe",
        NULL,
        NULL,
        FALSE,
        dwStartupFlags,
        NULL, // environ
        NULL, // cwd
        &si,
        &pi))
    {
        throw 1;
    }
    CloseHandle(pi.hThread);
    DWORD exitCode;
    while(true)
    {
        switch (WaitForSingleObject(pi.hProcess, 1000 * 10))
        {
          case WAIT_TIMEOUT:
            GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
            //WaitForSingleObject(pi.hProcess, INFINITE);
            break;
          case WAIT_OBJECT_0:
            GetExitCodeProcess(pi.hProcess, &exitCode);
            return exitCode;
        }
    }
    return -1;
}
So I start it up, type in something (no newline), and wait 10 seconds. The debugger shows the Ctrl-C event. The console shows that the Ctrl-C had no effect.
I tracked down the issue to this: the main cmd.exe thread calls ReadConsoleW. Under the test program with GenerateConsoleCtrlEvent, this does not return. Pressing Ctrl-C does make it return, with *lpNumberOfCharsRead==0.
GenerateConsoleCtrlEvent starts a new thread using kernel32!CtrlRoutine. If, using the debugger, you freeze this thread, cmd.exe still behaves as if Ctrl-C was pressed. In fact, you can trick cmd.exe into believing that there is was a Ctrl-C pressed if you set *lpNumberOfCharsRead==NULL when ReadConsoleW returns after a return keypress.
cmd.exe is not unique in the behavior: Python.exe's read returns immediately upon Ctrl-C, but not upon GenerateConsoleCtrlEvent. Python.exe uses ReadFile. (Python.exe notices the KeyboardInterrupt after you press enter.)
So the question is: why does ReadConsoleW return immediately when you press Ctrl-C, but not when GenerateConsoleCtrlEvent is called? As far as I can tell, on Windows 7, pressing Ctrl-C sends messages that are read by conhost.exe which communicates with csrss.exe, which calls NtCreateThreadEx with kernel32!CtrlRoutine. I do not see that it does anything else when you press Ctrl-C. But what is causing ReadConsoleW to return?
