// Input model smoke test. // Verifies that input queue handles and request-based reads target one keyboard queue. #include #include // Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } // Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; if (v == 0) { print("0"); return; } while (v && i < (int)sizeof(buf)) { buf[i++] = (char)('0' + (v % 10)); v /= 10; } while (i--) { char c = buf[i]; SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromParts(&c, 1) }; SysWriteConsole(&req); } } // Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } // Fails the test with one status value. static void fail_status(const char* what, uint32_t status) { print("input_model_smoke: "); print(what); print(" status="); print_u64(status); print("\n"); exit_now(1); } // Requires one exact status value. static void expect_status(const char* what, uint32_t got, uint32_t expected) { if (got == expected) return; print("input_model_smoke: "); print(what); print(" got="); print_u64(got); print(" expected="); print_u64(expected); print("\n"); exit_now(1); } // Program entry point. int main(void) { print("input_model_smoke: start\n"); uint32_t inputQueue = 0; expect_status("open input queue null", SysOpenInputQueue(SYS_INPUT_QUEUE_FLAG_NONE, (uint32_t*)0), NTLSTATUS_INVALID_PARAMETER); expect_status("open input queue bad flags", SysOpenInputQueue(1, &inputQueue), NTLSTATUS_INVALID_PARAMETER); uint32_t status = SysOpenInputQueue(SYS_INPUT_QUEUE_FLAG_NONE, &inputQueue); if (status != NTLSTATUS_SUCCESS) fail_status("open input queue", status); INPUT_KEY_RECORD record; SYS_INPUT_EVENT_REQUEST req; req.Size = sizeof(req); req.QueueHandle = inputQueue; req.Flags = SYS_INPUT_EVENT_FLAG_NONE; req.TimeoutMilliseconds = 0; req.RecordOut = &record; SYS_INPUT_EVENT_REQUEST badReq = req; badReq.Size = 0; expect_status("read input bad size", SysReadInputEvent(&badReq), NTLSTATUS_INVALID_PARAMETER); badReq = req; badReq.RecordOut = (INPUT_KEY_RECORD*)0; expect_status("peek input null out", SysPeekInputEvent(&badReq), NTLSTATUS_INVALID_PARAMETER); badReq = req; badReq.QueueHandle = 0xdeadbeefu; expect_status("read input bad handle", SysReadInputEvent(&badReq), NTLSTATUS_INVALID_HANDLE); SYS_GLOBAL_INPUT_STATE state; state.Size = sizeof(state); state.Flags = SYS_GLOBAL_INPUT_STATE_FLAG_NONE; expect_status("query global input null", SysQueryGlobalInputState((SYS_GLOBAL_INPUT_STATE*)0), NTLSTATUS_INVALID_PARAMETER); SYS_GLOBAL_INPUT_STATE badState = state; badState.Size = 0; expect_status("query global input bad size", SysQueryGlobalInputState(&badState), NTLSTATUS_INVALID_PARAMETER); badState = state; badState.Flags = 1; expect_status("query global input bad flags", SysQueryGlobalInputState(&badState), NTLSTATUS_INVALID_PARAMETER); status = SysQueryGlobalInputState(&state); if (status != NTLSTATUS_SUCCESS) fail_status("query global input", status); if (state.Size != sizeof(state)) fail_status("query global input size", state.Size); if (state.Flags != SYS_GLOBAL_INPUT_STATE_FLAG_NONE) fail_status("query global input flags", state.Flags); status = SysPeekInputEvent(&req); if (status != NTLSTATUS_SUCCESS && status != NTLSTATUS_WOULD_BLOCK) fail_status("peek input immediate", status); uint32_t waitStatus = SysWaitSingle(inputQueue, SYS_WAIT_FLAG_NONE, 0); if (status == NTLSTATUS_SUCCESS) { if (waitStatus != NTLSTATUS_SUCCESS) fail_status("wait input after readable peek", waitStatus); } else if (waitStatus != NTLSTATUS_TIMEOUT) { fail_status("wait empty input immediate", waitStatus); } req.TimeoutMilliseconds = 1; status = SysReadInputEvent(&req); if (status != NTLSTATUS_SUCCESS && status != NTLSTATUS_TIMEOUT) fail_status("read input finite timeout", status); SysCloseHandle(inputQueue); print("input_model_smoke: PASS\n"); exit_now(0); return 0; }