2013-12-17 7 views
1

Мне удалось использовать ReadDirectoryChangesW синхронно, но когда я пытаюсь использовать порты завершения, ReadDirectoryChangesW всегда возвращает ERROR_INVALID_PARAMETER. Я предполагаю, что в моем коде должна быть очевидная ошибка, но я не могу понять.Асинхронный 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; 
     }  
    } 
+0

Вы не указали notifyFilter и myFileIOCompletionRoutine определения. –

+1

CreateIoCompletionPort возвращает NULL, если сбой, ваш тест неверен. Может быть, CreateIoCompletionPort терпит неудачу? –

+0

@AlexFarber, спасибо, что указали его, но CreateIoCompletionPort возвращает действительный дескриптор. – Javier

ответ

1

Как Ганс 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; 
    } 
    } 
Смежные вопросы