* @cond LOCAL
*/
+typedef struct _Eio_Monitor_Win32_Watcher Eio_Monitor_Win32_Watcher;
+
+/* 4096 = 256 * sizeof(FILE_NOTIFY_INFORMATION) */
+# define EIO_MONITOR_WIN32_BUFFER_SIZE 4096
+
+struct _Eio_Monitor_Win32_Watcher
+{
+ char buffer[EIO_MONITOR_WIN32_BUFFER_SIZE];
+ OVERLAPPED overlapped;
+ HANDLE handle;
+ HANDLE event;
+ Eio_Monitor *monitor;
+ Ecore_Win32_Handler *h;
+ DWORD buf_length;
+ int is_dir;
+};
+
struct _Eio_Monitor_Backend
{
+ Eio_Monitor *parent;
+
+ Eio_Monitor_Win32_Watcher *file;
+ Eio_Monitor_Win32_Watcher *dir;
};
+static Eina_Bool
+_eio_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
+{
+ char filename[PATH_MAX];
+ PFILE_NOTIFY_INFORMATION fni;
+ Eio_Monitor_Win32_Watcher *w;
+ wchar_t *wname;
+ char *name;
+ DWORD filter;
+ DWORD offset;
+ DWORD buf_length;
+ int event = EIO_MONITOR_ERROR;
+
+ w = (Eio_Monitor_Win32_Watcher *)data;
+
+ if (!GetOverlappedResult(w->handle, &w->overlapped, &buf_length, TRUE))
+ return ECORE_CALLBACK_RENEW;
+
+ fni = (PFILE_NOTIFY_INFORMATION)w->buffer;
+ do {
+ if (!fni)
+ break;
+ offset = fni->NextEntryOffset;
+
+ wname = (wchar_t *)malloc(sizeof(wchar_t) * (fni->FileNameLength + 1));
+ if (!wname)
+ return 0;
+
+ memcpy(wname, fni->FileName, fni->FileNameLength);
+ wname[fni->FileNameLength]='\0';
+ name = evil_wchar_to_char(wname);
+ free(wname);
+ if (!name)
+ return ECORE_CALLBACK_CANCEL;
+
+ _snprintf(filename, PATH_MAX, "%s\\%s", w->monitor->path, name);
+ free(name);
+
+ switch (fni->Action)
+ {
+ case FILE_ACTION_ADDED:
+ if (w->is_dir)
+ event = EIO_MONITOR_DIRECTORY_CREATED;
+ else
+ event = EIO_MONITOR_FILE_CREATED;
+ break;
+ case FILE_ACTION_REMOVED:
+ if (w->is_dir)
+ event = EIO_MONITOR_DIRECTORY_DELETED;
+ else
+ event = EIO_MONITOR_FILE_DELETED;
+ break;
+ case FILE_ACTION_MODIFIED:
+ if (!w->is_dir)
+ event = EIO_MONITOR_FILE_MODIFIED;
+ break;
+ case FILE_ACTION_RENAMED_OLD_NAME:
+ if (w->is_dir)
+ event = EIO_MONITOR_DIRECTORY_DELETED;
+ else
+ event = EIO_MONITOR_FILE_DELETED;
+ break;
+ case FILE_ACTION_RENAMED_NEW_NAME:
+ if (w->is_dir)
+ event = EIO_MONITOR_DIRECTORY_CREATED;
+ else
+ event = EIO_MONITOR_FILE_CREATED;
+ break;
+ default:
+ fprintf(stderr, "unknown event\n");
+ event = EIO_MONITOR_ERROR;
+ break;
+ }
+ if (event != EIO_MONITOR_ERROR)
+ _eio_monitor_send(w->monitor, filename, event);
+
+ fni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)fni + offset);
+ } while (offset);
+
+ filter = (w->is_dir == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME;
+ filter |=
+ FILE_NOTIFY_CHANGE_ATTRIBUTES |
+ FILE_NOTIFY_CHANGE_SIZE |
+ FILE_NOTIFY_CHANGE_LAST_WRITE |
+ FILE_NOTIFY_CHANGE_LAST_ACCESS |
+ FILE_NOTIFY_CHANGE_CREATION |
+ FILE_NOTIFY_CHANGE_SECURITY;
+
+ ReadDirectoryChangesW(w->handle,
+ w->buffer,
+ EIO_MONITOR_WIN32_BUFFER_SIZE,
+ FALSE,
+ filter,
+ &w->buf_length,
+ &w->overlapped,
+ NULL);
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Eio_Monitor_Win32_Watcher *
+_eio_monitor_win32_watcher_new(Eio_Monitor *monitor, unsigned char is_dir)
+{
+ Eio_Monitor_Win32_Watcher *w;
+ DWORD filter;
+
+ w = (Eio_Monitor_Win32_Watcher *)calloc(1, sizeof(Eio_Monitor_Win32_Watcher));
+ if (!w) return NULL;
+
+ w->handle = CreateFile(monitor->path,
+ FILE_LIST_DIRECTORY,
+ FILE_SHARE_READ |
+ FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS |
+ FILE_FLAG_OVERLAPPED,
+ NULL);
+ if (w->handle == INVALID_HANDLE_VALUE)
+ goto free_w;
+
+ w->event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!w->event)
+ goto close_handle;
+
+ ZeroMemory (&w->overlapped, sizeof(w->overlapped));
+ w->overlapped.hEvent = w->event;
+
+ filter = (is_dir == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME;
+ filter |=
+ FILE_NOTIFY_CHANGE_ATTRIBUTES |
+ FILE_NOTIFY_CHANGE_SIZE |
+ FILE_NOTIFY_CHANGE_LAST_WRITE |
+ FILE_NOTIFY_CHANGE_LAST_ACCESS |
+ FILE_NOTIFY_CHANGE_CREATION |
+ FILE_NOTIFY_CHANGE_SECURITY;
+
+ if (!ReadDirectoryChangesW(w->handle,
+ w->buffer,
+ EIO_MONITOR_WIN32_BUFFER_SIZE,
+ FALSE,
+ filter,
+ &w->buf_length,
+ &w->overlapped,
+ NULL))
+ goto close_event;
+
+ w->h = ecore_main_win32_handler_add(w->event,
+ _eio_monitor_win32_cb,
+ w);
+ if (!w->h)
+ goto close_event;
+
+ w->monitor = monitor;
+ w->is_dir = is_dir;
+
+ return w;
+
+ close_event:
+ CloseHandle(w->event);
+ close_handle:
+ CloseHandle(w->handle);
+ free_w:
+ free(w);
+
+ return NULL;
+}
+
+static void
+_eio_monitor_win32_watcher_free(Eio_Monitor_Win32_Watcher *w)
+{
+ if (!w) return;
+
+ CloseHandle(w->event);
+ CloseHandle (w->handle);
+ free (w);
+}
+
/**
* @endcond
*/
void eio_monitor_backend_init(void)
{
- abort();
}
void eio_monitor_backend_shutdown(void)
void eio_monitor_backend_add(Eio_Monitor *monitor)
{
+ Eio_Monitor_Backend *backend;
+
+ backend = calloc(1, sizeof (Eio_Monitor_Backend));
+ if (!backend)
+ {
+ eio_monitor_fallback_add(monitor);
+ return;
+ }
+
+ backend->parent = monitor;
+ backend->file = _eio_monitor_win32_watcher_new(monitor, 0);
+ if (!backend->file)
+ {
+ free(backend);
+ eio_monitor_fallback_add(monitor);
+ return;
+ }
+
+ backend->dir = _eio_monitor_win32_watcher_new(monitor, 1);
+ if (!backend->dir)
+ {
+ _eio_monitor_win32_watcher_free(backend->file);
+ free(backend);
+ eio_monitor_fallback_add(monitor);
+ return;
+ }
+
+ monitor->backend = backend;
}
void eio_monitor_backend_del(Eio_Monitor *monitor)
{
+ if (!monitor->backend)
+ {
+ eio_monitor_fallback_del(monitor);
+ return ;
+ }
+
+ _eio_monitor_win32_watcher_free(monitor->backend->file);
+ _eio_monitor_win32_watcher_free(monitor->backend->dir);
+ free(monitor->backend);
+ monitor->backend = NULL;
}