异步ReadDirectoryChangesW失败,出现ERROR_INVALID_PARAMETER

时间:2013-12-17 15:29:48

标签: winapi asynchronous

我设法同步使用ReadDirectoryChangesW,但当我尝试使用完成端口时,ReadDirectoryChangesW始终返回ERROR_INVALID_PARAMETER。我想我的代码中应该有一些明显的错误,但我无法理解它。

我的代码基于How to use ReadDirectoryChangesW() method with completion routine?

   const wchar_t *directory = L"X:\\X";
   HANDLE h = CreateFile(
      directory,
      FILE_LIST_DIRECTORY,
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
      NULL, OPEN_EXISTING, 
      FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL);

   if (h==INVALID_HANDLE_VALUE) return;

   HANDLE p = CreateIoCompletionPort(h,0,0,1);
   if (p==NULL) {CloseHandle(h); return;}

   DWORD *buffer =new DWORD[4096];
   DWORD bytesReturned;

   DWORD notifyFilter =  FILE_NOTIFY_CHANGE_FILE_NAME 
                      | FILE_NOTIFY_CHANGE_DIR_NAME 
                      | FILE_NOTIFY_CHANGE_SIZE 
                      | FILE_NOTIFY_CHANGE_LAST_WRITE;

   while (true) {

       OVERLAPPED overlapped;
       memset(&overlapped,0,sizeof(overlapped));

       BOOL success = ReadDirectoryChangesW(h,
            &buffer[0],            
            4096*sizeof(DWORD),
            FALSE, notifyFilter,
            NULL, //&bytesReturned,
            &overlapped,myFileIOCompletionRoutine);

       if (!success) {    
          //always ERROR_INVALID_PARAMETER       
          CloseHandle(h);
          CloseHandle(p);
          return;
       }       
    }

1 个答案:

答案 0 :(得分:1)

正如Hans Passant所提醒的,the documentation已经说过,如果目录与完成端口相关联,则不得使用 。在这种情况下,我通过等待完成端口解决了问题,即ReadDirectoryChangesW(...,&overlapped,0);

完整代码如下。

while (true) {
    OVERLAPPED overlapped;
    memset(&overlapped,0,sizeof(overlapped));
    BOOL success = ReadDirectoryChangesW(h,
            &buffer[0],
            4096*sizeof(DWORD),
            FALSE, notifyFilter, 0, &overlapped,0);

    if (!success) {
      if (GetLastError()==ERROR_INVALID_HANDLE) {
        //asynchronously closed by cancel
        CloseHandle(p); //close completion port
        return 0;
      } else {
        CloseHandle(h); //close directory handle
        CloseHandle(p); //close completion port
        return 1;
      }
    }

    DWORD di;
    LPOVERLAPPED lpOverlapped;
    if (!GetQueuedCompletionStatus(p,&bytesReturned,&di,&lpOverlapped,1000)) {
        int ret;
        if (GetLastError()==WAIT_TIMEOUT) {
            if (GetFileAttributes(directory)!=INVALID_FILE_ATTRIBUTES) {
                continue; //timeout
            } else {
                //directory has been deleted or renamed
                ret=0;
            }
        } else {
            //other failure
            ret=1;
        }
        CloseHandle(h); //close directory handle
        CloseHandle(p); //close completion port
        return ret;
    }

    char* ptr = (char*)&buffer[0];
    char* end = ptr+bytesReturned;
    while (ptr<end) {
      FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*) ptr;
      //process FILE_NOTIFY_INFORMATION
      ptr+=info->NextEntryOffset;
      if (!info->NextEntryOffset) break;
    }
  }