27 #include "precompiled.h"
51 const DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
52 const DWORD flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
53 m_hDir = CreateFileW(
OsString(path).c_str(), FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0);
64 m_hDir = INVALID_HANDLE_VALUE;
88 m_ovl = (OVERLAPPED*)calloc(1,
sizeof(OVERLAPPED));
92 const BOOL manualReset = TRUE;
93 const BOOL initialState = FALSE;
94 m_ovl->hEvent = CreateEvent(0, manualReset, initialState, 0);
110 const DWORD ret = WaitForSingleObject(
m_ovl->hEvent, 1000);
112 if(ret == WAIT_OBJECT_0 || GetLastError() == ERROR_OPERATION_ABORTED)
122 debug_printf(L
"WARNING: IO may still be pending; to avoid memory corruption, we won't free the buffer.\n");
145 const BOOL watchSubtree = TRUE;
146 const DWORD filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
147 FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE |
148 FILE_NOTIFY_CHANGE_CREATION;
161 const FILE_NOTIFY_INFORMATION* fni = (
const FILE_NOTIFY_INFORMATION*)
m_data;
165 cassert(
sizeof(
wchar_t) ==
sizeof(WCHAR));
166 const size_t length = fni->FileNameLength /
sizeof(WCHAR);
174 if(!fni->NextEntryOffset)
176 fni = (
const FILE_NOTIFY_INFORMATION*)(uintptr_t(fni) + fni->NextEntryOffset);
185 case FILE_ACTION_ADDED:
186 case FILE_ACTION_RENAMED_NEW_NAME:
189 case FILE_ACTION_REMOVED:
190 case FILE_ACTION_RENAMED_OLD_NAME:
193 case FILE_ACTION_MODIFIED:
284 :
link(sentinel), request(request)
327 request->AttachTo(
hIOCP);
336 DWORD bytesTransferred; ULONG_PTR
key; OVERLAPPED* ovl;
361 return s_dirWatchManager->
Add(path, dirWatch);
367 return s_dirWatchManager->
Poll(notifications);
std::vector< DirWatchNotification > DirWatchNotifications
static const size_t dataSize
shared_ptr< DirWatchRequest > PDirWatchRequest
some WinAPI functions SetLastError(0) on success, which is bad because it can hide previous errors...
DirHandle(const OsPath &path)
const OsPath & Path() const
LIB_API Status dir_watch_Add(const OsPath &path, PDirWatch &dirWatch)
start watching a single directory for changes.
#define WINIT_REGISTER_MAIN_SHUTDOWN(func)
Status Add(const OsPath &path, PDirWatch &dirWatch)
void AttachToCompletionPort(HANDLE hFile, HANDLE &hIOCP, ULONG_PTR key, DWORD numConcurrentThreads)
NONCOPYABLE(DirWatchRequest)
void AttachTo(HANDLE &hIOCP) const
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
Status Poll(DirWatchNotifications ¬ifications)
shared_ptr< DirWatch > PDirWatch
LIB_API Status dir_watch_Poll(DirWatchNotifications ¬ifications)
return all pending directory watch notifications.
Status PollCompletionPort(HANDLE hIOCP, DWORD timeout, DWORD &bytesTransferred, ULONG_PTR &key, OVERLAPPED *&ovl)
#define SAFE_DELETE(p)
delete memory ensuing from new and set the pointer to zero (thus making double-frees safe / a no-op) ...
i64 Status
Error handling system.
static DirWatchNotification::EType TypeFromAction(const DWORD action)
void RetrieveNotifications(DirWatchNotifications ¬ifications) const
(call when completion port indicates data is available)
DirWatchRequest(const OsPath &path)
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
bool path_is_subpath(const wchar_t *s1, const wchar_t *s2)
is s2 a subpath of s1, or vice versa? (equal counts as subpath)
#define WINIT_REGISTER_MAIN_INIT(func)
DirWatch(IntrusiveLink *sentinel, const PDirWatchRequest &request)
static Status wdir_watch_Init()
#define WARN_IF_FALSE(expression)
#define WARN_RETURN(status)
IntrusiveLink(IntrusiveLink *sentinel)
static Status wdir_watch_Shutdown()
#define cassert(expr)
Compile-time assertion.
static DirWatchManager * s_dirWatchManager
IntrusiveLink * Next() const
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).
const Status PATH_NOT_FOUND
static std::string OsString(const OsPath &path)
#define RETURN_STATUS_IF_ERR(expression)