148 lines
3.7 KiB
C
148 lines
3.7 KiB
C
#pragma once
|
|
|
|
#include <ioringapi.h>
|
|
#include <ntioring_x.h>
|
|
// #include "ioringapi.c"
|
|
#include <winerror.h>
|
|
|
|
// Initialize I/O Ring
|
|
HIORING io_ring_init(void) {
|
|
|
|
// if (!io_ring_load_functions()) {
|
|
// printf("[I/O Ring] Failed to load functions\n");
|
|
// return NULL;
|
|
// }
|
|
|
|
IORING_CAPABILITIES caps;
|
|
ZeroMemory(&caps, sizeof(caps));
|
|
|
|
HRESULT hr = QueryIoRingCapabilities(&caps);
|
|
if (FAILED(hr)) {
|
|
printf("[I/O Ring] QueryIoRingCapabilities failed: 0x%08lx\n", hr);
|
|
return NULL;
|
|
}
|
|
|
|
// printf("[I/O Ring] MaxVersion=%d, MaxSubmission=%u, MaxCompletion=%u\n",
|
|
// (int)caps.MaxVersion, caps.MaxSubmissionQueueSize,
|
|
// caps.MaxCompletionQueueSize);
|
|
|
|
if (caps.MaxVersion < IORING_VERSION_1) {
|
|
printf("[I/O Ring] Version too old\n");
|
|
return NULL;
|
|
}
|
|
|
|
IORING_CREATE_FLAGS flags = {0};
|
|
HIORING ring = NULL;
|
|
|
|
// hr = CreateIoRing(IORING_VERSION_1, flags, 256, 512, &ring);
|
|
hr = CreateIoRing(caps.MaxVersion, flags, 256, 512, &ring);
|
|
if (FAILED(hr)) {
|
|
printf("[I/O Ring] CreateIoRing failed: 0x%08lx\n", hr);
|
|
return NULL;
|
|
}
|
|
|
|
// printf("[I/O Ring] Created successfully\n");
|
|
|
|
// Check if read operation is supported
|
|
|
|
// HRESULT io_ring_support = IsIoRingOpSupported(ring, IORING_OP_READ);
|
|
// if (io_ring_support == S_FALSE) {
|
|
// printf("[I/O Ring] Not supported, %ld /n", io_ring_support);
|
|
// }
|
|
|
|
// Get ring info
|
|
IORING_INFO info;
|
|
ZeroMemory(&info, sizeof(info));
|
|
GetIoRingInfo(ring, &info);
|
|
// printf("[I/O Ring] Submission: %u, Completion: %u\n",
|
|
// info.SubmissionQueueSize, info.CompletionQueueSize);
|
|
|
|
return ring;
|
|
}
|
|
|
|
void io_ring_cleanup(HIORING ring) {
|
|
if (ring) {
|
|
CloseIoRing(ring);
|
|
// printf("[I/O Ring] Closed\n");
|
|
}
|
|
}
|
|
|
|
// Read file using I/O Ring
|
|
int io_ring_read_file(HIORING ring, HANDLE hFile, void *buffer, DWORD size,
|
|
UINT64 offset) {
|
|
|
|
IORING_HANDLE_REF file_ref = IoRingHandleRefFromHandle(hFile);
|
|
IORING_BUFFER_REF buf_ref = IoRingBufferRefFromPointer(buffer);
|
|
|
|
HRESULT hr = BuildIoRingReadFile(ring, file_ref, buf_ref, size, offset,
|
|
(UINT_PTR)buffer, IOSQE_FLAGS_NONE);
|
|
|
|
if (FAILED(hr))
|
|
return -1;
|
|
|
|
UINT32 submitted = 0;
|
|
hr = SubmitIoRing(ring, 1, INFINITE, &submitted);
|
|
if (FAILED(hr) || submitted == 0)
|
|
return -1;
|
|
|
|
for (;;) {
|
|
IORING_CQE cqe;
|
|
hr = PopIoRingCompletion(ring, &cqe);
|
|
|
|
if (FAILED(hr))
|
|
continue;
|
|
|
|
if (cqe.UserData != (UINT_PTR)buffer)
|
|
continue;
|
|
|
|
if (FAILED(cqe.ResultCode))
|
|
return -1;
|
|
|
|
return (int)cqe.Information;
|
|
}
|
|
}
|
|
|
|
// Test function
|
|
void test_io_ring(void) {
|
|
printf("\n=== Testing I/O Ring ===\n");
|
|
|
|
HIORING ring = io_ring_init();
|
|
if (!ring) {
|
|
printf("I/O Ring not available\n");
|
|
return;
|
|
}
|
|
|
|
// Create test file
|
|
HANDLE hFile = CreateFileA("test.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
char test_data[] =
|
|
"Hello, I/O Ring! This is a test of the Windows I/O Ring API.";
|
|
DWORD written;
|
|
WriteFile(hFile, test_data, sizeof(test_data), &written, NULL);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
// Read using I/O Ring
|
|
hFile = CreateFileA("test.txt", GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
char buffer[512] = {0};
|
|
int bytes = io_ring_read_file(ring, hFile, buffer, sizeof(buffer), 0);
|
|
if (bytes > 0) {
|
|
printf("Read %d bytes: %s\n", bytes, buffer);
|
|
} else {
|
|
printf("Failed to read file\n");
|
|
}
|
|
CloseHandle(hFile);
|
|
} else {
|
|
printf("Failed to open test file\n");
|
|
}
|
|
|
|
// Cleanup
|
|
DeleteFileA("test.txt");
|
|
io_ring_cleanup(ring);
|
|
|
|
printf("=== Test complete ===\n\n");
|
|
}
|