//------------------------------------------------------------------------------ // // The following sample code 'snippet' is provided 'as is' without // warranty of any kind either expressed or assumed. No copyright, // ownership, or any other claims should be made for this code. // //------------------------------------------------------------------------------ // // keyMonkey - provide simple Hopper substitute that can easily be modified. // //------------------------------------------------------------------------------ // // Possible TODO's // // 1. Watchdog loop to verify inputs still being sent // 2. Statistics regarding # inputs sent, time spent in windows, etc. // 3. Visual clue that keyMonkey is still running // 4. Higher priority thread to dismiss windows hard to dismiss // // ... Others. // //------------------------------------------------------------------------------ // // #include #include // Forward declarations for convenience DWORD dwGetNextInput(void); DWORD dwDoNextAction(void); void Log(const TCHAR *tszFormat, ...); void pressKeys(DWORD dwParam); // Other housekeeping items... #define LOGBUFFERSIZE 2048 #define KEY_PRESS_DURATION 100 #define SLEEP_DURATION (KEY_PRESS_DURATION * 20) #define COUNTOF(x) (sizeof(x) / sizeof(x[0])) //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // // Define your inputs here, provide all potential inputs. The Weight key // is used to call critical keys less often. // typedef struct _keyStruct { UCHAR dwWeight; UCHAR dwLast; DWORD dwKey; TCHAR *tszKey; } keyStruct; keyStruct g_keys[] = { {0x0, 0x0, VK_TUP, TEXT("VK_UP") }, {0x0, 0x0, VK_TDOWN, TEXT("VK_DOWN") }, {0x0, 0x0, VK_TLEFT, TEXT("VK_LEFT") }, {0x0, 0x0, VK_TRIGHT, TEXT("VK_RIGHT") }, {0x5, 0x0, VK_TSOFT1, TEXT("VK_SOFT1") }, {0x5, 0x0, VK_TSOFT2, TEXT("VK_SOFT2") }, {0x0, 0x0, VK_TACTION, TEXT("VK_RETURN")}, {0x5, 0x0, VK_TBACK, TEXT("VK_ESCAPE")}, // << NOTE how somes keys {0xF, 0x0, VK_DONE, TEXT("VK_DONE") }, // << are weighted {0xF, 0x0, VK_THOME, TEXT("VK_HOME") }, // << differently? }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // // Simple logging stub - feel free to customize any way you wish including // logging to a file of your choice - for now simple log to stdebug. // void Log(const TCHAR *tszFormat, ...) { TCHAR tszLogBuffer[LOGBUFFERSIZE]; *tszLogBuffer = '0'; va_list vl; va_start(vl, tszFormat); _vsntprintf(tszLogBuffer, LOGBUFFERSIZE, tszFormat, vl); tszLogBuffer[LOGBUFFERSIZE - 1] = 0; va_end(vl); // write to console _tprintf(tszLogBuffer); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // // Provide basis for random keys - simply edit key structure with inputs // specific to your device, they don't have to be keys. // DWORD dwGetNextInput(void) { DWORD dwKey, dwTmp; // Loop until we find a key to press (NOT carrying any weight) do { // Return the next random key dwTmp = (rand() % COUNTOF(g_keys)); // Check all keys for weighting if(! g_keys[dwTmp].dwLast) { Log(TEXT("Pressing Key: %s\r\n"), g_keys[dwTmp].tszKey); dwKey = g_keys[dwTmp].dwKey; } else { // Loop around for next key dwKey = 0x0; } // Decrement any weighted keys if(g_keys[dwTmp].dwWeight) { // And check to see if its time to press this key if(! g_keys[dwTmp].dwLast) { // Reset the weight and continue g_keys[dwTmp].dwLast = g_keys[dwTmp].dwWeight; } else { g_keys[dwTmp].dwLast--; } } } while(! dwKey); return(dwKey); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // // Abstract for "doing something". In our case we will be sending a keystroke // directly to GWES, customize to suit your needs. // DWORD dwDoNextAction(DWORD dwKey) { // Simply press & release key Sleep(KEY_PRESS_DURATION); keybd_event((BYTE) dwKey, 0x0, 0, 0); Sleep(KEY_PRESS_DURATION); keybd_event((BYTE) dwKey, 0x0, KEYEVENTF_KEYUP, 0); // Always return TRUE for now return(TRUE); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // // Thread func to actually get & press the keys // void pressKeys(DWORD dwParam) { DWORD dwKey; // Run forever while(TRUE) { // Find the next action to do dwKey = dwGetNextInput(); // Then do it if(! dwDoNextAction(dwKey)) { Log(TEXT("ERROR: Something wrong with key presses! GLE: %d\r\n"), GetLastError()); break; } } // We should never get here, but if we do - handle it gracefully return; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int iCmdShow ) { HANDLE hThread; DWORD dwThreadId; // Seed our random number generator srand(GetTickCount()); // Thread func to actually get & press the keys if (!(hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) pressKeys, (LPVOID) 0x0, CREATE_SUSPENDED, &dwThreadId))) { Log(TEXT("ERROR: could not create new thread! GLE: %d\r\n"), GetLastError()); goto Error; } // Easily change the priority of your active thread here if (FALSE == CeSetThreadPriority(hThread, THREAD_PRIORITY_NORMAL)) { Log(TEXT("ERROR: could not set thread priority! GLE: %d\r\n"), GetLastError()); CloseHandle(hThread); goto Error; } ResumeThread(hThread); // // TODO: Spin up an additional monitor thread at a higher priority to watch o // the active threads and notify of any problems // // // For now, let the activity thread press keys and wait until device dies // or is stopped - you could easily modify this to wait for some certain // timeout or event or watch for some hard-to-dismiss window or event // blocking inputs // while(TRUE) { Sleep(SLEEP_DURATION); } // We should never exit, but if we do - exit cleanly Error: if(hThread) { CloseHandle(hThread); } }