0

The code is below and it is part of a thread. pFileChange->m_hDirectory is of type HANDLE and pFileChange->m_eventFileChange if of type CEvent. CreateFile and ReadDirectoryChangesW return with a success. I am not able to figure out why i am getting an invalid handle status, please help!

UINT CFileChange::FileMontiorThread(LPVOID pArgs)
{
  CFileChange* pFileChange = NULL;

  pFileChange = (CFileChange*)pArgs;

  pFileChange = (CFileChange*)pArgs;

  CString str = pFileChange->m_strDirectory;

  LPSTR  strDirectory;
  strDirectory = str.GetBuffer(str.GetLength());
  PathRemoveFileSpec(strDirectory);

  DWORD dwBytes = 0;    
  vector<BYTE> m_Buffer;
  BOOL      m_bChildren;
  OVERLAPPED    m_Overlapped;
  HANDLE arrHandles[2] = { pFileChange->m_hDirectory,  pFileChange->m_eventFileChange };

  ::ZeroMemory(&m_Overlapped, sizeof(OVERLAPPED));
  DWORD dwBufferSize = 16384;
  m_Buffer.resize(dwBufferSize);
  m_bChildren = false;


  pFileChange->m_hDirectory = ::CreateFile(
     (LPCSTR)(LPCTSTR)strDirectory,
    FILE_LIST_DIRECTORY,                
    FILE_SHARE_READ                     
    | FILE_SHARE_WRITE
    | FILE_SHARE_DELETE,
    NULL,                               
    OPEN_EXISTING,                      
    FILE_FLAG_BACKUP_SEMANTICS          
    | FILE_FLAG_OVERLAPPED,
    NULL);                              

  if (pFileChange->m_hDirectory == INVALID_HANDLE_VALUE)
  {
    return false;
  }

  BOOL success = ::ReadDirectoryChangesW(
    pFileChange->m_hDirectory,  // handle to directory
    &m_Buffer[0],                       // read results buffer
    m_Buffer.size(),                    // length of buffer
    m_bChildren,                        // monitoring option
    FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION |  FILE_NOTIFY_CHANGE_FILE_NAME,        // filter conditions
    &dwBytes,                           // bytes returned
    &m_Overlapped,                      // overlapped buffer
    NULL);           // no completion routine

  DWORD dwWaitStatus;

  while (!pFileChange->m_bKillThread)
  {
    dwWaitStatus = WaitForMultipleObjects(2, arrHandles, FALSE, INFINITE);

   Switch(dwWaitStatus)
   {
     case WAIT_FAILED:
        {
            ULONG rc = 0;
            rc = ::GetLastError();
            LPVOID lpMsgBuf = NULL;
            ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL,
                rc,
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default  language
                (LPTSTR)&lpMsgBuf,
                0,
                NULL);
            CString strErrMsg;
            strErrMsg.Format(_T("%s, %s, Reason:%s"), "", "",         (LPTSTR)lpMsgBuf);
            break;
        }
    }
  }
    return 0;
}

2 Answers2

0

Note that, as it specifies in the documentation, you can't wait on any type of handle.

wait

Waiting on a directory handle isn't going to do what you think it should. Read this related question and its answers for more information and background reading.

As it seems you're trying to create a folder monitor, perhaps read this blog post for the correct way to use ReadDirectoryChangesW.

Community
  • 1
  • 1
Roger Rowland
  • 25,885
  • 11
  • 72
  • 113
-2

The answer was provided by Hans Passant in a comment:

You copy the handles into arrHandles too soon, before they are created. That cannot work of course.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574