#include #include #include #include #include #define EVENT_AUTO_RESET 0u static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } static uint32_t open_file(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenFile(&req); } static void print_hex8(uint8_t v) { static const char h[] = "0123456789ABCDEF"; char b[3]; b[0] = h[(v >> 4) & 0xF]; b[1] = h[v & 0xF]; b[2] = 0; print(b); } static void print_u64(uint64_t n) { char buf[32]; int i = 0; if (!n) { print("0"); return; } while (n && i < (int)sizeof(buf)) { buf[i++] = (char)('0' + (n % 10)); n /= 10; } while (i) { char c[2] = { buf[--i], 0 }; print(c); } } typedef struct APC_TEST_STATE { volatile uint32_t Delivered; volatile uint32_t Status; volatile uint64_t Information; } APC_TEST_STATE; static void file_apc(void* context, SYS_IO_STATUS_BLOCK* iosb, uint64_t information) { APC_TEST_STATE* st = (APC_TEST_STATE*)context; st->Status = iosb ? iosb->Status : 0xFFFFFFFFu; st->Information = information; st->Delivered++; do { SYS_DEBUG_PRINT_REQUEST req = { SYS_SV_LITERAL("async_apc: user APC callback ran\n") }; SysDebugPrint(&req); } while (0); } int main(void) { print("async_apc: start\n"); uint32_t s = SysSetUserApcDispatcher((void*)SysUserApcDispatcher); if (s != SYS_STATUS_SUCCESS) { print("async_apc: dispatcher registration failed status="); print_u64(s); print("\n"); SysExitProcess(1); } uint32_t file = 0; s = open_file("system/init.exe", &file); if (s != SYS_STATUS_SUCCESS) { print("async_apc: open failed status="); print_u64(s); print("\n"); SysExitProcess(1); } uint32_t event = 0; s = SysEventCreate(EVENT_AUTO_RESET, 0, &event); if (s != SYS_STATUS_SUCCESS) { print("async_apc: event create failed status="); print_u64(s); print("\n"); SysExitProcess(1); } uint8_t* buffer = (uint8_t*)SysAlloc(512); if (!buffer) { print("async_apc: allocation failed\n"); SysExitProcess(1); } memset(buffer, 0, 512); SYS_IO_STATUS_BLOCK iosb; iosb.Status = 0; iosb.Information = 0; APC_TEST_STATE state; memset(&state, 0, sizeof(state)); SYS_ASYNC_FILE_REQUEST req; memset(&req, 0, sizeof(req)); req.FileHandle = file; req.EventHandle = event; req.Offset = 0; req.Buffer = buffer; req.Size = 512; req.Iosb = &iosb; req.ApcRoutine = file_apc; req.ApcContext = &state; s = SysReadFileAsync(&req); if (s != SYS_STATUS_PENDING) { print("async_apc: submit failed status="); print_u64(s); print("\n"); SysExitProcess(1); } while (!state.Delivered) { s = SysEventWait(event, 1); print("async_apc: alertable wait returned "); print_u64(s); print("\n"); if (s != SYS_STATUS_USER_APC && s != SYS_STATUS_SUCCESS && s != SYS_STATUS_PENDING) break; } print("async_apc: delivered="); print_u64(state.Delivered); print(" status="); print_u64(state.Status); print(" info="); print_u64(state.Information); print(" bytes="); print_hex8(buffer[0]); print(" "); print_hex8(buffer[1]); print(" "); print_hex8(buffer[2]); print(" "); print_hex8(buffer[3]); print("\n"); uint32_t ok = (state.Delivered == 1 && state.Status == SYS_STATUS_SUCCESS && state.Information == 512 && buffer[0] == 'M' && buffer[1] == 'Z'); SysCloseHandle(event); SysCloseHandle(file); SysFree(buffer); if (!ok) { print("async_apc: FAIL\n"); SysExitProcess(1); } print("async_apc: PASS\n"); SysExitProcess(0); return 0; }