pike.git / src / modules / Wnotify / wnotify.cmod

version» Context lines:

pike.git/src/modules/Wnotify/wnotify.cmod:1: + /*! @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; +  + /*! @decl create(string path, int watch_subtree, int filter) +  */ +  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() +  { + /* +  BOOL res; + */ +  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); +  } + } +  + /*! @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; +  int s, n; +  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(); +  } +  +  /*! @decl NotificationHandle|int poll(void|float timeout) +  */ +  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); +  } + } +  + #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; + } +  + /*! @endclass +  */ +  + /*! @endmodule +  */ +  + /*! @endmodule +  */   Newline at end of file added.