Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5968723
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T20:07:48+00:00 2026-05-22T20:07:48+00:00

Exactly as it sounds, I’m attempting asynchronous ReadDirectoryChangesW with IO Completion and it isn’t

  • 0

Exactly as it sounds, I’m attempting asynchronous ReadDirectoryChangesW with IO Completion and it isn’t working, specifically, GetLastError repeatedly returns 258 (GetQueuedCompletionStatus timeout).

I have structs:

typedef struct dirinfo_struct
{
    HANDLE hDirFH;           // directory handle
    OVERLAPPED Overlapped;   // overlapped storage
    int len_buffer;          // buffer length
    wchar_t* buffer;         // buffer itself
    wchar_t* directory_name; // target name
} dirinfo_t;

typedef struct dirmon_struct
{
    HANDLE hDirOPPort;       // handle to the IO port.
    dirinfo_t* dirinfo;      // pointer to the struct above.
} dirmon_t;

for storing the relevant information. This is initialised:

dirinfo_t* t = malloc(1*sizeof(dirinfo_t));
dirmon_t* d = malloc(1*sizeof(dirmon_t));
dirinfo_init(t); // does t->buffer = malloc(8192*sizeof(wchar_t));

Then I create my Directory Handle and com port:

t->hDirFH = CreateFile(L"C:\\test",
                        FILE_LIST_DIRECTORY,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        NULL,
                        OPEN_EXISTING,
                        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
                        NULL); 
d->dirinfo = t;
d->hDirOPPort = CreateIoCompletionPort(d->dirinfo->hDirFH, 
                                       NULL,       
                                       (ULONG_PTR)(d->dirinfo), 
                                       1); 

Then I pass this information via d to a new thread. Now on said new thread I have:

bResultQ = GetQueuedCompletionStatus(d->hDirOPPort, lpBytes, 
                                     (ULONG_PTR*)d->dirinfo,    
                                     lpOverlapped, 1000);

if ( bResultQ )
{
    bResultR = ReadDirectoryChangesW(d->dirinfo->hDirFH, 
                                     (void*)d->dirinfo->buffer, 
                                     8192, TRUE,
                                     FILE_NOTIFY_CHANGE_FILE_NAME | 
                                     FILE_NOTIFY_CHANGE_DIR_NAME |
                                     FILE_NOTIFY_CHANGE_ATTRIBUTES | 
                                     FILE_NOTIFY_CHANGE_SIZE |
                                     FILE_NOTIFY_CHANGE_LAST_WRITE | 
                                     FILE_NOTIFY_CHANGE_LAST_ACCESS | 
                                     FILE_NOTIFY_CHANGE_CREATION | 
                                     FILE_NOTIFY_CHANGE_SECURITY,
                                     lpReadDirBytes,
                                     &d->dirinfo->Overlapped,
                                     NULL );
} 
else
{
    printf("GetQueuedCompletionStatus(): Failed, ");
    errorcode = GetLastError();
    printf("Error Code %d\n", errorcode);
    Sleep(500);
}

So I set this off running and I merrily get timeouts (258 errors) as I should since the directory hasn’t changed. However, even if I alter the directory, I’m still getting error messages; in other words those alterations are not being picked up. Which leads me to believe I’ve got this set up incorrectly.

Any ideas?

Caveats:

  • Ironically, this will eventually be converted to Python via pywin32. However, until I understand how this is supposed to work in C, I’m not going there.
  • Synchronous ReadDirectoryChangesW is not an option. If no events are fired, I need the thread this is on to timeout so it can check if it should still be running.
  • I am writing in C specifically, not C++.
  • FindFirstChangeNotification etc not an option either – I don’t want to continually be comparing directory listings to work out what has changed.

Other notes:

  • The Directory exists, that handle is not NULL. Likewise for the comport handle.
  • Everything’s being passed to the thread

I’ve taken a look at CDirectoryChangeWatcher from code project, but use of C++ and many more threads aside, I can’t see what I’m doing differently. Feel free to point it out if I’m missing something though!

Output, if it helps, is basically on repeat, no matter how much I alter the directory in question.

GetQueuedCompletionStatus(): Failed, Error Code 258
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T20:07:49+00:00Added an answer on May 22, 2026 at 8:07 pm

    I realise posting walls of code is generally considered horrendous, but here’s how I got this working:

    New structs:

    BOOL runthread;
    
    typedef struct overlapped_struct
    {
        OVERLAPPED overlapped;
        wchar_t* buffer;
    } overlapped_t;
    
    typedef struct dirinfo_struct
    {
    
        HANDLE hDirOPPort;
        HANDLE hDirFH;
        overlapped_t* o;
        int len_buffer;
        wchar_t* buffer;
        wchar_t* directory_name;
        ULONG_PTR CompletionKey;
    } dirinfo_t;
    
    int somekey = 1;
    

    Allocation methods:

    void dirinfo_init(dirinfo_t* t)
    {
        t->buffer = malloc(16777216*sizeof(wchar_t));
        t->len_buffer = 16777216;
        t->o = calloc(1, sizeof(overlapped_t));
        t->o->buffer = calloc(16777216, sizeof(wchar_t));
        memset(t->o->buffer, 0, 16777216);
        memset(t->o, 0, sizeof(OVERLAPPED));
    }
    
    void dirinfo_free(dirinfo_t* t)
    {
        free(t->buffer);
        free(t->o->buffer);
        free(t->o);
        free(t);
    }
    

    The important stuff from main() does this:

    dirinfo_t* d = malloc(1*sizeof(dirinfo_t));
    d->CompletionKey = (ULONG_PTR)&somekey;
    dirinfo_init(d);
    
    /* set up */
    runthread = TRUE;
    d->hDirFH = CreateFile(L"C:\\hydratest",
                    FILE_LIST_DIRECTORY,
                    FILE_SHARE_READ|FILE_SHARE_WRITE,
                    NULL,
                    OPEN_EXISTING,
                    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
                    NULL); 
    
    d->hDirOPPort = CreateIoCompletionPort(d->hDirFH, NULL, 
                          (ULONG_PTR)d->CompletionKey, 1);  
    

    Then finally my waiting thread. Here’s the key: I’m not passing an overlapped structure in. I’m passing in a structure containing an OVERLAPPED plus a fair amount of wchar_t based storage. For reasons I don’t fully understand, this works. Edit see this answer. I believe the data region here acts as the overlapped buffer.

    DWORD WINAPI WaitingThread(void* args)
    {
        DWORD errorcode = 0;    // an error code
        BOOL bResultQ = FALSE;  // obvios=us
        BOOL bResultR = FALSE;
        DWORD NumBytes = 0; 
        FILE_NOTIFY_INFORMATION* pInfo = NULL; // the data incoming is a pointer
                                               // to this struct.
        int i = 0;
        dirinfo_t* d = (dirinfo_t*) args;      // rescue struct from thread arg.
    

    Then we get onto the main thread itself. Trial and error suggests you’re supposed to call both ReadDirectoryW AND GetQueueCompletionStatus. I think what this means is that we’re supposed to not touch the buffer from ReadDirectoryChangeW **unless* we’re told we can by GetQueue. Corrections on that hypothesis welcome however.

        while ( runthread )
        {
            bResultR = ReadDirectoryChangesW(d->hDirFH, (void*)d->buffer, 
                                              16777216, TRUE,
                   FILE_NOTIFY_CHANGE_FILE_NAME  | FILE_NOTIFY_CHANGE_DIR_NAME |
                   FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE |
                   FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | 
                   FILE_NOTIFY_CHANGE_CREATION   | FILE_NOTIFY_CHANGE_SECURITY,
                                              NULL,
                                              &d->o->overlapped,
                                              NULL );
            bResultQ = GetQueuedCompletionStatus(d->hDirOPPort, 
                                                 &NumBytes, &(d->CompletionKey), 
                                                 (LPOVERLAPPED*)(d->o), 1000);
    

    So, now we’ve called those functions, we then test that they both returned true. big ugly warning if you’ve got your parameters set up right bResultR always returns true, or so it seems to me. bResultQ however varies depending on whether new data is on the port.

            if ( bResultQ && bResultR )
            {
    

    So here we cast that buffer from ReadDirectoryChangesW and access the info from the struct.

                wprintf(L"\n");
                pInfo = (FILE_NOTIFY_INFORMATION*) d->buffer;
                wprintf(L"File %s", pInfo->FileName);
                wprintf(L" changes %d\n", pInfo->Action);
                memset(d->buffer, 0, 16777216);
            }
    

    Otherwise, and thanks to Tony for this, you can safely ignore WAIT_TIMEOUT errors, but anything else probably means you’re in trouble.

            else
            {
                errorcode = GetLastError();
    
                if ( errorcode == WAIT_TIMEOUT )
                {
                    printf("GetQueuedCompletionStatus(): Timeout\n");
                }
                else
                {
                    printf("GetQueuedCompletionStatus(): Failed\n");
                    printf("Error Code %d\n", errorcode);
                }
                Sleep(500);
            }
        }   
    
        return 0;
    }
    

    And that completes what I think is a working example.

    Some notes:

    • I’ve set the buffer size to be huge. I noticed copying 100 files or so that the buffer ran out of space set to 8192 and missed off an item or two, here and there. So I don’t expect this will always pick up everything. My solution would be to say every 100 events, verify the file tree is what you think it is if using this method. An infinitely better solution, however, to constantly enumerating the potentially large tree.
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I found this answer and it sounds like almost exactly what I'm doing. I
Exactly as the question sounds. I want to subtract say 20120115 from 20120203 and
Hey all.. exactly as it sounds. currently using @fontface, lettering.js, and kern.js to get
It sounds strange but this is exactly what I want because I am using
I'm working on an iOS application that needs to play some sounds using the
Exactly like it sounds.. Is there some magical and easy way to say: if
I know the question sounds too vague so let me explain exactly what I
Pretty much exactly as it sounds. I have buttons in a Wx.Frame that are
Exactly what the title says. Note, this is not about subscriptable objects.
Exactly what the title says. I'm using MSVC++ 2008 express, and my class constructor

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.