0

I'm creating a process using the WinAPI's CreateProcessA() function and I'm trying to terminate the child process when the user presses the Ctrl+C keys, but all I can find on the msdn docs is the SetConsoleControlHandler, which in my understanding, sets the control handler to the current process, not a child process.

I'm looking for a way to set the control handler for a child process by using a handle to that process or something like this:

HANDLE hProcess;    // A handle to the child process after the CreateProcess function.

SetConsoleControlHandler(hProcess, myControlhandler, TRUE);

How can I do something like that?

Lior Levin
  • 179
  • 1
  • 13
  • 1
    You can not do anything to make child process handle ctrc+c unless it already does so. If it does then you can use https://stackoverflow.com/questions/813086/can-i-send-a-ctrl-c-sigint-to-an-application-on-windows – user7860670 Apr 03 '20 at 12:29
  • The only possibility I can think of would be to [inject code](https://en.wikipedia.org/wiki/DLL_injection) into the child process which calls `SetConsoleControlHandler` from within the child process. – Andreas Wenzel Apr 03 '20 at 12:42
  • 1
    Windows uses Job Objects to allow you to control a set of processes as a whole. – IInspectable Apr 03 '20 at 13:00
  • Isn't any console application terminated by default when ctrl-c is pressed? – ssbssa Apr 03 '20 at 13:55
  • @ssbssa The child process is not a console application, it is a photo-editing program (for now I'm using ms-paint, in the future it will be something else). – Lior Levin Apr 03 '20 at 20:34
  • In that case `SetConsoleControlHandler` wouldn't help you at all, because as the name says, it's for console applications. – ssbssa Apr 03 '20 at 21:59
  • Do you want to use `ctrl + c` in the parent process to end the child process?If not, you could use Alt+F4 to close the process with window instead to use Ctrl +C – Drake Wu Apr 06 '20 at 08:22

1 Answers1

1

If you want to use "Ctrl + C" in the parent process(console) to end the child process, you could call TerminateProcess in the handler routine callback function:

#include <Windows.h>
#include <iostream>
PROCESS_INFORMATION pi = { 0 };

BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
    switch (fdwCtrlType)
    {
        // Handle the CTRL-C signal. 
    case CTRL_C_EVENT:
        printf("Ctrl-C event\n\n");
        TerminateProcess(pi.hProcess, 0);
        return TRUE;
    default:
        return FALSE;
    }
}
int main()
{
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = true;

    BOOL ret = CreateProcess("C:\\Windows\\System32\\mspaint.exe", NULL, NULL, NULL, false, 0, NULL, NULL, &si, &pi);

    SetConsoleCtrlHandler(CtrlHandler, true);
    WaitForSingleObject(pi.hProcess, -1);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return 0;
}

If you want to use "Ctrl+C" in the child process, you could monitor low-level keyboard input events:

#include <Windows.h>
#include <iostream>
PROCESS_INFORMATION pi = { 0 };
HHOOK hook;
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (code == HC_ACTION)
    {
        PKBDLLHOOKSTRUCT pkb = (PKBDLLHOOKSTRUCT)lParam;
        if (wParam == WM_KEYDOWN && pkb->vkCode == 'C')
        {
            if (GetAsyncKeyState(VK_CONTROL) < 0)
            {
                DWORD pid = 0;
                HWND hwnd = GetForegroundWindow();
                GetWindowThreadProcessId(hwnd, &pid);
                if (pid == pi.dwProcessId)
                {
                    TerminateProcess(pi.hProcess, 0);
                    PostQuitMessage(0);
                }
            }
        }
    }
    return CallNextHookEx(hook, code, wParam, lParam);
}
int main()
{
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = true;

    BOOL ret = CreateProcess("C:\\Windows\\System32\\mspaint.exe", NULL, NULL, NULL, false, 0, NULL, NULL, &si, &pi);

    hook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    WaitForSingleObject(pi.hProcess,-1);
    UnhookWindowsHookEx(hook);
    printf("unhook\n");
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return 0;
}
Drake Wu
  • 6,927
  • 1
  • 7
  • 30