The MSDN says that using ReadDirectoryChangesW implies the calling process having the Backup and Restore privileges.
Does this mean that only process launched under administrator account will work correctly?
I've tried the following code, it fails to enable the required privileges when running as a restricted user.
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);
}
}
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!
Update: Here is the full code of the class:
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];
};
}
Update: 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.
I have used ReadDirectoryChangesW
without requiring administrator rights, at least on Vista. I don't think you need to manually elevate the process in order to use it on a folder the user already has permissions to see.
It would be more helpful to see the actual code you are using to call ReadDirectoryChangesW
, including how you create the handle you pass in.
I don't see where MSDN says you need either backup or restore privileges. It instructs you to call CreateFile
with the File_Flag_Backup_Semantics
flag set, and in that flag's description, MSDN says this:
The system ensures that the calling process overrides file security checks when the process has
SE_BACKUP_NAME
andSE_RESTORE_NAME
privileges.
The way I read it, if you have those privileges, then the system will override the file security checks for you. So if you don't have those privileges, then the program will simply continue to be bound by whatever file security checks would ordinarily be in effect.
Alex, in your CreateFile()
call you put FILE_FLAG_OVERLAPPED
into wrong position. It should be moved from 2nd to 6th parameter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With