Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results


Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging

The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.

Check out The OSR Learning Library at:

Using ThreadPoolIO function with IO completion port

shiro96shiro96 Member Posts: 16

I am trying to do the following:
1. From usermode , create a thread pool which waits for asynchronous operation(on a file) to complete.
2. The threads will wait for async operation to complete using IO completion port.

However, When implementing the logic, I get a runtime error when calling CreateThreadPoolIO function. The function returns NULL and upon calling GetLastError() shows error code 87(which means parameter passed to it is incorrect).
I am not sure why it generates this error and I could not find an example on web which demonstrates what I have been trying to do. I am currently referring to MSDN documentation
to implement most of my code.


VOID CALLBACK mycompletionRoutine(
    PTP_CALLBACK_INSTANCE pInstance, // See "Callback Termination Actions" section
    PVOID pvContext,
    PVOID pOverlapped,
    ULONG IoResult,
    ULONG_PTR NumberOfBytesTransferred,
    PTP_IO pIo)
    std::cout << "Completion routine is invoked" << std::endl;

int main()
    // Open handle to existing file in overlapped mode
    HANDLE hFile = CreateFile(L"C:\\test\\text.txt",                // name of the write
        GENERIC_READ,          // open for read
        0,                      // do not share
        NULL,                   // default security
        OPEN_EXISTING,             // ppen existing file only
        FILE_FLAG_OVERLAPPED,  // normal file
        NULL);                  // no attr. template

    if (hFile == INVALID_HANDLE_VALUE)
        std::cout << "Invalid Handle value" << std::endl;
        return -1;

    // Create a new completion port
    HANDLE Iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,NULL,0);
    if (Iocp == NULL)
        DWORD status = GetLastError();
        std::cout << "Iocp is NULL" << status<< std::endl;
        return -1;

    // Associate completion port with file handle
    ULONG ckey = 2;
    HANDLE newIocp = CreateIoCompletionPort(hFile, Iocp, ckey, 0);
    if (newIocp != Iocp)
        DWORD status = GetLastError();
        std::cout << "newIocp is NULL" << status << std::endl;
        return -1;

    // Create a thread pool object and associate it with a file handle.
    PTP_IO thread_pool_obj =  CreateThreadpoolIo(hFile, mycompletionRoutine, NULL, NULL);
    if (thread_pool_obj == NULL)
        DWORD status = GetLastError();
        std::cout << "**Thread pool obj is NULL**" << status << std::endl;
        return -1;

    std::cout << "Program ran successfully" << std::endl;

    return 0;


  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,832

    I believe you EITHER call CreateIoCompletionPort, or you call CreateThreadpoolIo. My understanding is that CreateThreadpoolIo will create the completion port as part of its duties.

    I may have misunderstood the docs, so I'll delete this if challenged.

    Tim Roberts, [email protected]
    Software Wizard Emeritus

  • shiro96shiro96 Member Posts: 16

    Maybe your theory is correct. When I delete either piece of code(CreateThreadpoolIo / CreateCompletion port), the program works successfully. But I still don't understand how many threads will be created when I use CreateThreadpoolIo since there is no explicit parameter(similar to CreateCompletionPort) which allows you to specify the number of concurrent thread that will be created

  • Doron_HolanDoron_Holan Member - All Emails Posts: 10,828

    correct on both. CreateThreadPoolIo is used on its own, not with a user IOCP (underneath the covers it has used an IOCP in the past, I don't know the current implementation). You don't control the number of threads, you let the thread pool manage it (hence, thread pool) and scale it as needed based on use.

  • MBond2MBond2 Member Posts: 707

    You cannot use both the thread pool APIs and a completion port with the same HANDLE

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 13-17 May 2024 Live, Online
Developing Minifilters 1-5 Apr 2024 Live, Online
Internals & Software Drivers 11-15 Mar 2024 Live, Online
Writing WDF Drivers 20-24 May 2024 Live, Online