Search code examples
c++visual-studio-2010exesendinputbsod

C++ - Simulating keystrokes using SendInput method, failure to distinguish rightctrl key


I have very little experience in C++, and I'm completely unfamiliar with the SendInput method. I've setup my laptop (with UK keyboard) via a registry modification, to create a crash dump whenever the right control key is held down and scroll lock is twice pressed. I am trying to achieve this programmatically via a c++ executable, compiled in Visual C++ 2010 Express.

Using this post: how to use sendinput function C++ as my inspiration, I have created the code snippet hereunder. Aside from multiple Cannot find or open the PDB debug outputs, which from reading this post: Error Message : Cannot find or open the PDB file can apparently be ignored, the code compiles and runs. However no BSOD transpires. I have manually "forced" the BSOD, so I know it works.

Bearing in mind I'm a novice, please explain what changes must be made for this to work?

#define WINVER 0x500
#include <windows.h>

int main()
{
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;

ip.ki.wVk = VK_RCONTROL;
ip.ki.dwFlags = 0; 
SendInput(1, &ip, sizeof(INPUT));

ip.ki.wVk = VK_SCROLL;
ip.ki.dwFlags = 0; 
SendInput(1, &ip, sizeof(INPUT));

ip.ki.wVk = VK_SCROLL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));

ip.ki.wVk = VK_SCROLL;
ip.ki.dwFlags = 0;
SendInput(1, &ip, sizeof(INPUT));

ip.ki.wVk = VK_SCROLL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));

ip.ki.wVk = VK_RCONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));

return 0;
}

Solution

  • This Code successfully stuffs RControl+ScrollLock+ScrollLock into the ScanCode app, however, sorry, the computer does not reboot like when it does when these keys are manually typed.

    #define WINVER 0x0500
    #include <windows.h>
    
    int main()
    {
        // Must specify INPUT_KEYBOARD for all INPUT structs
        INPUT ip[6] = { 
                { INPUT_KEYBOARD },
                { INPUT_KEYBOARD },
                { INPUT_KEYBOARD },
                { INPUT_KEYBOARD },
                { INPUT_KEYBOARD },
                { INPUT_KEYBOARD },
        };
    
        Sleep(3000);
    
    
        // Specify keys by scancode.  For the VK_SCROLL, it was necessary
        // to instead specify the wVK, otherwise VK==3 was received by ScanCode, instead
        // of VK_SCROLL == 145!
        //ip[0].ki.wVk = VK_CONTROL;
        ip[0].ki.wScan = MapVirtualKey(VK_RCONTROL, MAPVK_VK_TO_VSC);
        ip[0].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_EXTENDEDKEY;
    
        ip[1].ki.wVk = VK_SCROLL;
        ip[1].ki.wScan = MapVirtualKey(VK_SCROLL, MAPVK_VK_TO_VSC);
        ip[1].ki.dwFlags = /*KEYEVENTF_SCANCODE*/ 0;
    
        ip[2].ki.wVk = VK_SCROLL;
        ip[2].ki.wScan = MapVirtualKey(VK_SCROLL, MAPVK_VK_TO_VSC);
        ip[2].ki.dwFlags = /*KEYEVENTF_SCANCODE |*/ KEYEVENTF_KEYUP;
    
        ip[3].ki.wVk = VK_SCROLL;
        ip[3].ki.wScan = MapVirtualKey(VK_SCROLL, MAPVK_VK_TO_VSC);
        ip[3].ki.dwFlags = /*KEYEVENTF_SCANCODE*/ 0;
    
        ip[4].ki.wVk = VK_SCROLL;
        ip[4].ki.wScan = MapVirtualKey(VK_SCROLL, MAPVK_VK_TO_VSC);
        ip[4].ki.dwFlags = /*KEYEVENTF_SCANCODE |*/ KEYEVENTF_KEYUP;
    
        //ip[5].ki.wVk = VK_CONTROL;
        ip[5].ki.wScan = MapVirtualKey(VK_RCONTROL, MAPVK_VK_TO_VSC);
        ip[5].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY;
    
        int i = _countof(ip);
        int numSuccessful = SendInput(i, ip, sizeof(INPUT));
        if (numSuccessful == i)
            printf("Stuffed successful.\n");
        else
        {
            printf("Succeeded with %d of %d; error %d\n", numSuccessful, i, GetLastError());
        }
    
        return 0;
    }
    

    I believe the reason is that SendInput() injects the keys into the layer above the keyboard driver, and it is the keyboard driver that is monitored for these keystrokes to initiate the BSOD.