2010-04-14 3 views
6

MSDN afferma che l'utilizzo di ReadDirectoryChangesW implica che il processo chiamante disponga dei privilegi di backup e ripristino.L'uso di ReadDirectoryChangesW richiede diritti di amministratore?

Ciò significa che solo il processo avviato con l'account amministratore funzionerà correttamente?

Ho provato il seguente codice, non riesce a abilitare i privilegi richiesti quando è in esecuzione come utente con restrizioni.

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); 
    } 
} 

Sto facendo qualcosa di sbagliato? C'è qualche soluzione alternativa per l'utilizzo di ReadDirectoryChangesW da un account utente non amministratore? Sembra che FileSystemWatcher di .NET possa farlo. Grazie!

Aggiornamento: Ecco il codice completo della classe:

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]; 
    }; 

} 

Aggiornamento: Buone notizie! Si è scoperto che il problema era in realtà nel flag FILE_SHARE_WRITE nella chiamata a CreateFile. Le notifiche non sono arrivate a meno che non fossi un amministratore. Quando ho rimosso questo flag, ora tutto funziona anche su un account non amministratore.

+0

Come si chiama ReadDirectoryChangesW? Con la radice del drive o su una cartella? – MSN

+0

Dove dice esattamente MSDN? – avakar

+0

Lo sto usando su una cartella. Ma GetLastError dopo AdjustTokenPrivileges restituisce ERROR_NOT_ALL_ASSIGNED. –

risposta

4

Ho usato ReadDirectoryChangesW senza richiedere i diritti di amministratore, almeno su Vista. Non penso che sia necessario elevare manualmente il processo per poterlo utilizzare su una cartella che l'utente ha già le autorizzazioni per vedere.

Sarebbe più utile per vedere il codice vero e proprio che si utilizza per chiamare ReadDirectoryChangesW, tra cui come si crea il manico si passa.

+0

Grazie! Hai capito bene: la creazione dell'handle conteneva un errore - il flag FILE_SHARE_WRITE non necessario –

3

Non vedo dove MSDN dice che è necessario sia il backup o il ripristino dei privilegi . Si incarica di chiamare CreateFile con il flag impostato File_Flag_Backup_Semantics, e nella descrizione di quella bandiera, MSDN says this:

Il sistema garantisce che le sostituzioni processo chiamante depositare i controlli di sicurezza quando il processo ha SE_BACKUP_NAME e SE_RESTORE_NAME privilegi.

Il modo in cui l'ho letta, se avete questi privilegi, allora il sistema ignorare i controlli di sicurezza di file per voi. Quindi se si dispone di tali privilegi, se lo non ha, il programma continuerà a essere vincolato da qualunque controllo di sicurezza dei file sarà normalmente in vigore.

+0

Hai ragione, ho frainteso ciò che dice realmente MSDN. Il problema era nel flag FILE_SHARE_WRITE nella chiamata a CreateFile. –

2

Alex, nella tua chiamata CreateFile(), inserisci FILE_FLAG_OVERLAPPED nella posizione sbagliata. Dovrebbe essere spostato dal 2 ° al 6 ° parametro.