title: Does using ReadDirectoryChangesW require administrator rights?
body: <p>The MSDN says that using ReadDirectoryChangesW implies the calling process having the Backup and Restore privileges.</p>
  
  <p>Does this mean that only process launched under administrator account will work correctly?</p>
  
  <p>I've tried the following code, it fails to enable the required privileges when running as a restricted user.</p>
  
  <pre><code>void enablePrivileges() 
  {       
      enablePrivilege(SE_BACKUP_NAME);
      enablePrivilege(SE_RESTORE_NAME);
  }
  
  void enablePrivilege(LPCTSTR name) 
  {       
      HANDLE hToken;    
      DWORD status;
      if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &amp;hToken))  
      {        
          TOKEN_PRIVILEGES tp = { 1 };   
          if( ::LookupPrivilegeValue(NULL, name,  &amp;tp.Privileges[0].Luid) )
          {
              tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
              BOOL result = ::AdjustTokenPrivileges(hToken, FALSE, &amp;tp, 0, NULL, NULL);
              verify (result != FALSE);
              status = ::GetLastError();      
          }
          ::CloseHandle(hToken); 
      } 
  }
  </code></pre>
  
  <p>Am I doing something wrong? Is there any workaround for using ReadDirectoryChangesW from a non-administrator user account? It seems that the .NET's FileSystemWatcher can do this. Thanks!</p>
  
  <p><strong>Update</strong>: Here is the full code of the class:</p>
  
  <pre><code>  class DirectoryChangesWatcher
    {
    public:
     DirectoryChangesWatcher(wstring directory)
     {
      enablePrivileges();
  
      hDir = ::CreateFile(directory.c_str(), 
       FILE_LIST_DIRECTORY | FILE_FLAG_OVERLAPPED, 
       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 
       FILE_FLAG_BACKUP_SEMANTICS, NULL);
  
      ensure (hDir != INVALID_HANDLE_VALUE, err::SystemException);
  
      ::ZeroMemory(&amp;overlapped, sizeof(OVERLAPPED));
      overlapped.hEvent = dirChangedEvent.getHandle();  
     }
  
     ~DirectoryChangesWatcher() { ::CloseHandle(hDir); }
  
    public:
     Event&amp; getEvent() { return dirChangedEvent; }
  
     FILE_NOTIFY_INFORMATION* getBuffer() { return buffer; }
  
    public:
     void startAsyncWatch()
     {
      DWORD bytesReturned;   
  
      const BOOL res = ::ReadDirectoryChangesW(
       hDir,                                  
       &amp;buffer,                                    
       sizeof(buffer),                                
       TRUE,                                 
       FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE,
       &amp;bytesReturned,              
       &amp;overlapped,                          
       NULL);
  
      ensure(res != FALSE, err::SystemException);
     }
  
    private:
     void enablePrivileges() 
     {       
      enablePrivilege(SE_BACKUP_NAME);
      enablePrivilege(SE_RESTORE_NAME);
     }
  
     void enablePrivilege(LPCTSTR name) 
     {       
      HANDLE hToken;    
      DWORD status;
      if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &amp;hToken))  
      {        
       TOKEN_PRIVILEGES tp = { 1 };   
       if( ::LookupPrivilegeValue(NULL, name,  &amp;tp.Privileges[0].Luid) )
       {
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        BOOL result = ::AdjustTokenPrivileges(hToken, FALSE, &amp;tp, 0, NULL, NULL);
        verify (result != FALSE);
        status = ::GetLastError();      
       }
       ::CloseHandle(hToken); 
      } 
     }
  
    private:
     HANDLE hDir;
     OVERLAPPED overlapped;
     Event dirChangedEvent;
     FILE_NOTIFY_INFORMATION buffer[1024];   
    };
  
   }
  </code></pre>
  
  <p><strong>Update</strong>: Good news! It turned out the problem really was in the FILE_SHARE_WRITE flag in the call to CreateFile. The notifications did not come unless I was an admin. When I removed this flag, everything is now working ona non-admin account too.</p>