Implemented waitable timers.

diff --git a/server/timer.c b/server/timer.c
new file mode 100644
index 0000000..0a20ca1
--- /dev/null
+++ b/server/timer.c
@@ -0,0 +1,200 @@
+/*
+ * Waitable timers management
+ *
+ * Copyright (C) 1999 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "winerror.h"
+
+#include "handle.h"
+#include "request.h"
+
+/* FIXME: check values and move to standard header */
+#define TIMER_MODIFY_STATE  0x0001
+#define TIMER_QUERY_STATE   0x0002
+#define TIMER_ALL_ACCESS    (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
+
+struct timer
+{
+    struct object        obj;       /* object header */
+    int                  manual;    /* manual reset */
+    int                  signaled;  /* current signaled state */
+    int                  period;    /* timer period in ms */
+    struct timeval       when;      /* next expiration */
+    struct timeout_user *timeout;   /* timeout user */
+    void                *callback;  /* callback APC function */
+    void                *arg;       /* callback argument */
+};
+
+static void timer_dump( struct object *obj, int verbose );
+static int timer_signaled( struct object *obj, struct thread *thread );
+static int timer_satisfied( struct object *obj, struct thread *thread );
+static void timer_destroy( struct object *obj );
+
+static const struct object_ops timer_ops =
+{
+    sizeof(struct timer),
+    timer_dump,
+    add_queue,
+    remove_queue,
+    timer_signaled,
+    timer_satisfied,
+    no_read_fd,
+    no_write_fd,
+    no_flush,
+    no_get_file_info,
+    timer_destroy
+};
+
+
+/* create a timer object */
+static struct timer *create_timer( const WCHAR *name, size_t len, int manual )
+{
+    struct timer *timer;
+
+    if ((timer = create_named_object( &timer_ops, name, len )))
+    {
+        if (get_error() != ERROR_ALREADY_EXISTS)
+        {
+            /* initialize it if it didn't already exist */
+            timer->manual       = manual;
+            timer->signaled     = 0;
+            timer->when.tv_sec  = 0;
+            timer->when.tv_usec = 0;
+            timer->period       = 0;
+            timer->timeout      = NULL;
+        }
+    }
+    return timer;
+}
+
+/* callback on timer expiration */
+static void timer_callback( void *private )
+{
+    struct timer *timer = (struct timer *)private;
+
+    if (timer->period)  /* schedule the next expiration */
+    {
+        make_timeout( &timer->when, timer->period );
+        timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
+    }
+    else timer->timeout = NULL;
+
+    /* wake up waiters */
+    timer->signaled = 1;
+    wake_up( &timer->obj, 0 );
+}
+
+/* set the timer expiration and period */
+static void set_timer( struct timer *timer, int sec, int usec, int period,
+                       void *callback, void *arg )
+{
+    if (timer->manual)
+    {
+        period = 0;  /* period doesn't make any sense for a manual timer */
+        timer->signaled = 0;
+    }
+    if (timer->timeout) remove_timeout_user( timer->timeout );
+    timer->when.tv_sec  = sec;
+    timer->when.tv_usec = usec;
+    timer->period       = period;
+    timer->callback     = callback;
+    timer->arg          = arg;
+    timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
+}
+
+/* cancel a running timer */
+static void cancel_timer( struct timer *timer )
+{
+    if (timer->timeout)
+    {
+        remove_timeout_user( timer->timeout );
+        timer->timeout = NULL;
+    }
+}
+
+static void timer_dump( struct object *obj, int verbose )
+{
+    struct timer *timer = (struct timer *)obj;
+    assert( obj->ops == &timer_ops );
+    fprintf( stderr, "Timer manual=%d when=%ld.%06ld period=%d ",
+             timer->manual, timer->when.tv_sec, timer->when.tv_usec, timer->period );
+    dump_object_name( &timer->obj );
+    fputc( '\n', stderr );
+}
+
+static int timer_signaled( struct object *obj, struct thread *thread )
+{
+    struct timer *timer = (struct timer *)obj;
+    assert( obj->ops == &timer_ops );
+    return timer->signaled;
+}
+
+static int timer_satisfied( struct object *obj, struct thread *thread )
+{
+    struct timer *timer = (struct timer *)obj;
+    assert( obj->ops == &timer_ops );
+    if (!timer->manual) timer->signaled = 0;
+    return 0;
+}
+
+static void timer_destroy( struct object *obj )
+{
+    struct timer *timer = (struct timer *)obj;
+    assert( obj->ops == &timer_ops );
+
+    if (timer->timeout) remove_timeout_user( timer->timeout );
+}
+
+/* create a timer */
+DECL_HANDLER(create_timer)
+{
+    size_t len = get_req_strlenW( req->name );
+    struct timer *timer;
+
+    req->handle = -1;
+    if ((timer = create_timer( req->name, len, req->manual )))
+    {
+        req->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
+        release_object( timer );
+    }
+}
+
+/* open a handle to a timer */
+DECL_HANDLER(open_timer)
+{
+    size_t len = get_req_strlenW( req->name );
+    req->handle = open_object( req->name, len, &timer_ops, req->access, req->inherit );
+}
+
+/* set a waitable timer */
+DECL_HANDLER(set_timer)
+{
+    struct timer *timer;
+
+    if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
+                                                 TIMER_MODIFY_STATE, &timer_ops )))
+    {
+        set_timer( timer, req->sec, req->usec, req->period, req->callback, req->arg );
+        release_object( timer );
+    }
+}
+
+/* cancel a waitable timer */
+DECL_HANDLER(cancel_timer)
+{
+    struct timer *timer;
+
+    if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
+                                                 TIMER_MODIFY_STATE, &timer_ops )))
+    {
+        cancel_timer( timer );
+        release_object( timer );
+    }
+}