8

MSDNによると、ReadDirectoryChangesWを使用することは、バックアップと復元の権限を持つ呼び出しプロセスを意味します。

これは、管理者アカウントで起動されたプロセスのみが正しく機能することを意味しますか?

次のコードを試しましたが、制限付きユーザーとして実行しているときに必要な権限を有効にできません。

void enablePrivileges() 
{       
    enablePrivilege(SE_BACKUP_NAME);
    enablePrivilege(SE_RESTORE_NAME);
}

void enablePrivilege(LPCTSTR name) 
{       
    HANDLE hToken;    
    DWORD status;
    if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))  
    {        
        TOKEN_PRIVILEGES tp = { 1 };   
        if( ::LookupPrivilegeValue(NULL, name,  &tp.Privileges[0].Luid) )
        {
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            BOOL result = ::AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
            verify (result != FALSE);
            status = ::GetLastError();      
        }
        ::CloseHandle(hToken); 
    } 
}

私は何か間違ったことをしていますか?管理者以外のユーザーアカウントからReadDirectoryChangesWを使用するための回避策はありますか?.NETのFileSystemWatcherがこれを実行できるようです。ありがとう!

更新:クラスの完全なコードは次のとおりです。

  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(&overlapped, sizeof(OVERLAPPED));
    overlapped.hEvent = dirChangedEvent.getHandle();  
   }

   ~DirectoryChangesWatcher() { ::CloseHandle(hDir); }

  public:
   Event& getEvent() { return dirChangedEvent; }

   FILE_NOTIFY_INFORMATION* getBuffer() { return buffer; }

  public:
   void startAsyncWatch()
   {
    DWORD bytesReturned;   

    const BOOL res = ::ReadDirectoryChangesW(
     hDir,                                  
     &buffer,                                    
     sizeof(buffer),                                
     TRUE,                                 
     FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE,
     &bytesReturned,              
     &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, &hToken))  
    {        
     TOKEN_PRIVILEGES tp = { 1 };   
     if( ::LookupPrivilegeValue(NULL, name,  &tp.Privileges[0].Luid) )
     {
      tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
      BOOL result = ::AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
      verify (result != FALSE);
      status = ::GetLastError();      
     }
     ::CloseHandle(hToken); 
    } 
   }

  private:
   HANDLE hDir;
   OVERLAPPED overlapped;
   Event dirChangedEvent;
   FILE_NOTIFY_INFORMATION buffer[1024];   
  };

 }

更新:朗報です!問題は、CreateFileの呼び出しのFILE_SHARE_WRITEフラグに実際にあることが判明しました。私が管理者でない限り、通知は届きませんでした。このフラグを削除すると、すべてが管理者以外のアカウントでも機能するようになりました。

4

3 に答える 3

5

ReadDirectoryChangesW少なくともVistaでは、管理者権限を必要とせずに使用しました。ユーザーが既に表示する権限を持っているフォルダーでプロセスを使用するために、プロセスを手動で昇格させる必要はないと思います。

ReadDirectoryChangesW渡すハンドルの作成方法など、呼び出しに使用している実際のコードを確認するとさらに便利です。

于 2010-04-14T20:17:07.773 に答える
4

MSDNがバックアップまたは復元の権限が必要だと言っている場所がわかりません。CreateFileフラグを設定して呼び出すように指示File_Flag_Backup_Semanticsされ、そのフラグの説明で、MSDNは次のように述べています

システムは、プロセスが特権を持っSE_BACKUP_NAMEている場合、呼び出し元のプロセスがファイルのセキュリティチェックを上書きすることを保証します。SE_RESTORE_NAME

私が読んだ方法ではあなたがそれらの特権を持っている場合、システムはあなたのためにファイルセキュリティチェックを上書きします。したがって、これらの特権がない場合、プログラムは、通常有効なファイルセキュリティチェックに拘束され続けます。

于 2010-04-14T20:51:37.707 に答える
2

アレックス、あなたのCreateFile()電話であなたはFILE_FLAG_OVERLAPPED間違った位置に置きました。2番目から6番目のパラメーターに移動する必要があります。

于 2015-11-13T15:52:08.760 に答える