f51d42 | 2012-07-25 | Bill Welliver | | /*! @module System
*/
/*! @module Wnotify
*!
*! An interface to Windows filesystem change information.
*!
*/
#include "global.h"
#include "interpret.h"
#include "module.h"
#include "program.h"
#include "stralloc.h"
#include "svalue.h"
#include "threads.h"
#include "object.h"
#include "pike_types.h"
#include "builtin_functions.h"
#include "wnotify_config.h"
#define ADD_ICONST(name) do { \
add_integer_constant(#name, name, 0); \
} while(0);
#ifdef HAVE_FILEAPI_H
#include <FileAPI.h>
#endif /* HAVE_FILEAPI_H */
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif /* HAVE_WINDOWS_H */
#ifdef HAVE_WINBASE_H
#include <winbase.h>
#endif /* HAVE_WINBASE_H */
#ifndef MAX_LEN
#define MAX_LEN 255
#endif /* !MAX_LEN */
DECLARATIONS
#ifdef HAVE_FINDFIRSTCHANGENOTIFICATION
/*! @class NotificationHandle
*/
PIKECLASS NotificationHandle
{
CVAR HANDLE handle;
PIKEVAR string path;
PIKEVAR int watch_subtree;
PIKEVAR int filter;
PIKEVAR int triggered;
|
126fa4 | 2013-04-03 | Henrik Grubbström (Grubba) | | /*! @decl void create(string path, int watch_subtree, int filter)
|
f51d42 | 2012-07-25 | Bill Welliver | | */
PIKEFUN void create(string path, int watch_subtree, int filter)
{
HANDLE h;
THIS->path = path;
add_ref(path);
THIS->watch_subtree = watch_subtree;
THIS->filter = filter;
if(string_has_null(path))
{
pop_n_elems(args);
Pike_error("NotificationHandle: path cannot contain null.\n");
}
if((1 << path->size_shift)>1)
{
pop_n_elems(args);
Pike_error("NotificationHandle: path cannot be a wide string.\n");
}
if(THIS->path->len > MAX_LEN)
{
pop_n_elems(args);
Pike_error("NotificationHandle: length of path is too long.\n");
}
h = FindFirstChangeNotification(path->str, (BOOL)THIS->watch_subtree, (DWORD)THIS->filter);
if(h == INVALID_HANDLE_VALUE)
{
pop_n_elems(args);
Pike_error("NotificationHandle: failed to create handle.\n");
}
else
THIS->handle = h;
pop_n_elems(args);
return;
}
/*! @decl int get_error()
*/
PIKEFUN int get_error()
{
DWORD e;
e = GetLastError();
push_int(e);
}
PIKEFUN void read_change()
{
|
71f9cf | 2012-07-25 | Bill Welliver | | /*
|
f51d42 | 2012-07-25 | Bill Welliver | | BOOL res;
|
71f9cf | 2012-07-25 | Bill Welliver | | */
|
f51d42 | 2012-07-25 | Bill Welliver | | if(!THIS->triggered)
{
Pike_error("NotificationHandle.read_change(): no change event triggered.\n");
}
/* res = ReadDirectoryChangesW(THIS->handle, ); */
}
INIT
{
}
EXIT
{
if(THIS->path) free_string(THIS->path);
if(THIS->handle) FindCloseChangeNotification(THIS->handle);
}
}
|
126fa4 | 2013-04-03 | Henrik Grubbström (Grubba) | | /*! @endclass */
|
f51d42 | 2012-07-25 | Bill Welliver | | /*! @class EventPoller
*/
PIKECLASS EventPoller
{
/* Do not meddle with this array; it must be kept in sync with the handles array. */
PIKEVAR array phandles
flags ID_PRIVATE;
CVAR HANDLE * handles;
CVAR int handles_size;
CVAR int handles_used;
/*! @decl void add_handle(NotificationHandle handle)
*/
PIKEFUN void add_handle(object handle)
{
void * h;
|
71f9cf | 2012-07-25 | Bill Welliver | | int s, n;
|
f51d42 | 2012-07-25 | Bill Welliver | | struct array * ph;
HANDLE nh;
HANDLE * handles;
h = get_storage(handle, NotificationHandle_program);
if(!h)
{
pop_stack();
Pike_error("add_handle: invalid object type.\n");
}
ph = append_array(THIS->phandles, &Pike_sp[-args]);
THIS->phandles = ph;
nh = OBJ2_NOTIFICATIONHANDLE(handle)->handle;
if(THIS->handles_size <= THIS->handles_used)
{
s = n = THIS->handles_size || 1;
s*=2;
handles = realloc(THIS->handles, sizeof(HANDLE) * s);
if(!handles)
{
pop_stack();
Pike_error("add_handle: failed to allocate memory.\n");
}
THIS->handles = handles;
}
THIS->handles[THIS->handles_used++] = nh;
pop_stack();
}
|
f87cb9 | 2012-07-27 | Tobias S. Josefowitz | | /*! @decl NotificationHandle|int poll(void|float timeout)
*/
|
f51d42 | 2012-07-25 | Bill Welliver | | PIKEFUN int poll(void|float timeout)
{
DWORD res;
DWORD to;
if(THIS->handles_used < 1)
{
pop_stack();
Pike_error("poll: no paths to monitor.\n");
}
if(!timeout || (timeout->type == PIKE_T_INT && timeout->u.integer == 0))
{
to = INFINITE;
}
else if(timeout->type == PIKE_T_FLOAT)
{
to = (DWORD)timeout->u.float_number * 1000;
}
else
{
Pike_error("poll: invalid timeout.\n");
}
pop_n_elems(args);
res = WaitForMultipleObjects(THIS->handles_used, THIS->handles, FALSE, to);
if(res >= WAIT_OBJECT_0 && res <= (WAIT_OBJECT_0 + THIS->handles_used - 1))
{
/* we have a hit. */
struct svalue * sv;
sv = THIS->phandles->item+res;
/* TODO: proper value checking of the items in the array! */
OBJ2_NOTIFICATIONHANDLE(sv->u.object)->triggered = 1;
push_svalue(&ITEM(THIS->phandles)[res]);
FindNextChangeNotification(THIS->handles+res);
}
else if(res >= WAIT_ABANDONED_0 && res <= (WAIT_ABANDONED_0 + THIS->handles_used - 1))
{
/* don't think this applies to us, so let's flag an exception. */
Pike_error("poll: unexpected result (WAIT_ABANDONED)\n");
}
else if(res == WAIT_TIMEOUT)
{
push_int(0);
}
}
INIT
{
struct array * a;
a = allocate_array(0);
THIS->phandles = a;
}
EXIT
{
if(THIS->handles)
free(THIS->handles);
if(THIS->phandles)
free_array(THIS->phandles);
}
}
|
126fa4 | 2013-04-03 | Henrik Grubbström (Grubba) | | /*! @endclass */
|
f51d42 | 2012-07-25 | Bill Welliver | | #endif /* HAVE_FINDFIRSTCHANGENOTIFICATION */
PIKE_MODULE_INIT
{
INIT;
/*! @decl constant FILE_NOTIFY_CHANGE_FILE_NAME
*/
/*! @decl constant FILE_NOTIFY_CHANGE_DIR_NAME
*/
/*! @decl constant FILE_NOTIFY_CHANGE_ATTRIBUTES
*/
/*! @decl constant FILE_NOTIFY_CHANGE_SIZE
*/
/*! @decl constant FILE_NOTIFY_CHANGE_LAST_WRITE
*/
/*! @decl constant FILE_NOTIFY_CHANGE_SECURITY
*/
#ifdef HAVE_FINDFIRSTCHANGENOTIFICATION
ADD_ICONST(FILE_NOTIFY_CHANGE_FILE_NAME);
ADD_ICONST(FILE_NOTIFY_CHANGE_DIR_NAME);
ADD_ICONST(FILE_NOTIFY_CHANGE_ATTRIBUTES);
ADD_ICONST(FILE_NOTIFY_CHANGE_SIZE);
ADD_ICONST(FILE_NOTIFY_CHANGE_LAST_WRITE);
ADD_ICONST(FILE_NOTIFY_CHANGE_SECURITY);
#endif /* HAVE_FINDFIRSTCHANGENOTIFICATION */
}
PIKE_MODULE_EXIT
{
EXIT;
}
/*! @endmodule
*/
/*! @endmodule
*/
|