Created
November 18, 2023 09:00
-
-
Save rbmm/d81717283e2ca33828be34d5a8edbcf0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define FILE_NOTIFY_VALID_MASK 0x00000fff | |
class RDC : OVERLAPPED | |
{ | |
HANDLE _M_hFile = 0; | |
SRWLOCK _M_lock {}; | |
LONG _M_dwRef = 1; | |
union { | |
FILE_NOTIFY_INFORMATION _M_fni; | |
UCHAR _M_buf[0x1000]; | |
}; | |
~RDC() | |
{ | |
if (_M_hFile) CloseHandle(_M_hFile); | |
} | |
void Dump(PFILE_NOTIFY_INFORMATION pfni) | |
{ | |
DWORD NextEntryOffset = 0; | |
do | |
{ | |
(PBYTE&)pfni += NextEntryOffset; | |
DbgPrint("[%x]: %.*S\n", pfni->Action, pfni->FileNameLength / sizeof(WCHAR), pfni->FileName); | |
} while (NextEntryOffset = pfni->NextEntryOffset); | |
} | |
VOID WINAPI cb( | |
_In_ DWORD dwErrorCode, | |
_In_ DWORD dwNumberOfBytesTransfered) | |
{ | |
switch (dwErrorCode) | |
{ | |
case NOERROR: | |
if (dwNumberOfBytesTransfered) | |
{ | |
Dump(&_M_fni); | |
} | |
Read(); | |
break; | |
case ERROR_NOTIFY_ENUM_DIR: | |
DbgPrint("ERROR_NOTIFY_CLEANUP\n"); | |
Read(); | |
break; | |
case ERROR_NOTIFY_CLEANUP: | |
DbgPrint("ERROR_NOTIFY_CLEANUP\n"); | |
default: | |
DbgPrint("!! IoResult=%u\n", dwErrorCode); | |
break; | |
} | |
Release(); | |
} | |
static VOID WINAPI _M_cb( | |
_In_ DWORD status, | |
_In_ DWORD dwNumberOfBytesTransfered, | |
_Inout_ LPOVERLAPPED lpOverlapped) | |
{ | |
static_cast<RDC*>(lpOverlapped)->cb(RtlNtStatusToDosError(status), dwNumberOfBytesTransfered); | |
} | |
void Read() | |
{ | |
AddRef(); | |
AcquireSRWLockShared(&_M_lock); | |
ULONG IoResult = _M_hFile ? (ReadDirectoryChangesW(_M_hFile, &_M_buf, sizeof(_M_buf), TRUE, | |
FILE_NOTIFY_VALID_MASK, 0, this, 0) ? NOERROR : GetLastError()) : ERROR_NOTIFY_CLEANUP; | |
ReleaseSRWLockShared(&_M_lock); | |
if (NOERROR != IoResult) | |
{ | |
// this is not 100% correct due bug in ReadDirectoryChangesW | |
// STATUS_DATATYPE_MISALIGNMENT in case _M_buf wrong aligned is not recognized | |
cb(IoResult, 0); | |
} | |
} | |
public: | |
ULONG Init(PCWSTR psz) | |
{ | |
HANDLE hFile = CreateFileW(psz, FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, | |
FILE_FLAG_OVERLAPPED|FILE_FLAG_BACKUP_SEMANTICS, 0); | |
if (INVALID_HANDLE_VALUE != hFile) | |
{ | |
_M_hFile = hFile; | |
if (BindIoCompletionCallback(hFile, _M_cb, 0)) | |
{ | |
hEvent = 0; | |
Read(); | |
return NOERROR; | |
} | |
} | |
return GetLastError(); | |
} | |
void Stop() | |
{ | |
AcquireSRWLockExclusive(&_M_lock); | |
if (_M_hFile) CloseHandle(_M_hFile), _M_hFile = 0; | |
ReleaseSRWLockExclusive(&_M_lock); | |
} | |
void AddRef() | |
{ | |
InterlockedIncrementNoFence(&_M_dwRef); | |
} | |
void Release() | |
{ | |
if (!InterlockedDecrement(&_M_dwRef)) | |
{ | |
delete this; | |
} | |
} | |
}; | |
void test(PCWSTR psz) | |
{ | |
if (RDC* p = new RDC) | |
{ | |
if (NOERROR == p->Init(psz)) | |
{ | |
MessageBoxW(0, 0, 0, 0); | |
p->Stop(); | |
} | |
p->Release(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment