Added serial port object to the server.

diff --git a/server/serial.c b/server/serial.c
new file mode 100644
index 0000000..e5b6066
--- /dev/null
+++ b/server/serial.c
@@ -0,0 +1,198 @@
+/*
+ * Server-side serial port communications management
+ *
+ * Copyright (C) 1998 Alexandre Julliard
+ * Copyright (C) 2000 Mike McCormack
+ *
+ * TODO:
+ *  Add async read, write and WaitCommEvent handling.
+ *
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef HAVE_SYS_ERRNO_H
+#include <sys/errno.h>
+#endif
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <utime.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "winerror.h"
+#include "winbase.h"
+
+#include "handle.h"
+#include "thread.h"
+#include "request.h"
+
+static void serial_dump( struct object *obj, int verbose );
+static void serial_destroy( struct object *obj );
+static int serial_get_read_fd( struct object *obj );
+static int serial_get_write_fd( struct object *obj );
+static int serial_get_info( struct object *obj, struct get_file_info_request *req );
+static int serial_get_poll_events( struct object *obj );
+
+struct serial
+{
+    struct object       obj;
+    char                name[16]; /* eg. /dev/ttyS1 */
+    int                 access;
+
+    /* timeout values */
+    unsigned int        readinterval;
+    unsigned int        readconst;
+    unsigned int        readmult;
+    unsigned int        writeconst;
+    unsigned int        writemult;
+
+    unsigned int        eventmask;
+    unsigned int        commerror;
+
+    struct termios      original;
+
+    /* FIXME: add dcb, comm status, handler module, sharing */
+};
+
+static const struct object_ops serial_ops =
+{
+    sizeof(struct serial),        /* size */
+    serial_dump,                  /* dump */
+    default_poll_add_queue,       /* add_queue */
+    default_poll_remove_queue,    /* remove_queue */
+    default_poll_signaled,        /* signaled */
+    no_satisfied,                 /* satisfied */
+    serial_get_poll_events,       /* get_poll_events */
+    default_poll_event,           /* poll_event */
+    serial_get_read_fd,           /* get_read_fd */
+    serial_get_write_fd,          /* get_write_fd */
+    no_flush,                     /* flush */
+    serial_get_info,              /* get_file_info */
+    serial_destroy                /* destroy */
+};
+
+/* SERIAL PORT functions */
+
+static void serial_dump( struct object *obj, int verbose )
+{
+    struct serial *serial = (struct serial *)obj;
+    assert( obj->ops == &serial_ops );
+
+    fprintf( stderr, "Port fd=%d name='%s' mask=%x\n", 
+             serial->obj.fd, serial->name,serial->eventmask);
+}
+
+/* same as file_destroy, but don't delete comm ports */
+static void serial_destroy( struct object *obj )
+{
+    assert( obj->ops == &serial_ops );
+}
+
+struct serial *get_serial_obj( struct process *process, int handle, unsigned int access )
+{
+    return (struct serial *)get_handle_obj( process, handle, access, &serial_ops );
+}
+
+static int serial_get_poll_events( struct object *obj )
+{
+    struct serial *serial = (struct serial *)obj;
+    int events = 0;
+    assert( obj->ops == &serial_ops );
+    if (serial->access & GENERIC_READ) events |= POLLIN;
+    if (serial->access & GENERIC_WRITE) events |= POLLOUT;
+    return events;
+}
+
+static int serial_get_read_fd( struct object *obj )
+{
+    struct serial *serial = (struct serial *)obj;
+    assert( obj->ops == &serial_ops );
+    return dup( serial->obj.fd );
+}
+
+static int serial_get_write_fd( struct object *obj )
+{
+    struct serial *serial = (struct serial *)obj;
+    assert( obj->ops == &serial_ops );
+    return dup( serial->obj.fd );
+}
+
+static int serial_get_info( struct object *obj, struct get_file_info_request *req )
+{
+    assert( obj->ops == &serial_ops );
+    req->type        = FILE_TYPE_CHAR;
+    req->attr        = 0;
+    req->access_time = 0;
+    req->write_time  = 0;
+    req->size_high   = 0;
+    req->size_low    = 0;
+    req->links       = 0;
+    req->index_high  = 0;
+    req->index_low   = 0;
+    req->serial      = 0;
+    return 1;
+}
+
+/* create a serial */
+DECL_HANDLER(create_serial)
+{
+    struct serial *serial;
+    int fd,flags;
+    struct termios tios;
+
+    req->handle = -1;
+
+    flags = 0;
+    switch(req->access & (GENERIC_READ | GENERIC_WRITE))
+    {
+    case GENERIC_READ:  flags |= O_RDONLY; break;
+    case GENERIC_WRITE: flags |= O_WRONLY; break;
+    case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break;
+    default: break;
+    }
+
+    fd = open( req->name, flags );
+    if(fd < 0)
+    {
+        file_set_error();
+        return;
+    }
+
+    /* check its really a serial port */
+    if(0>tcgetattr(fd,&tios))
+    {
+        file_set_error();
+        close(fd);
+        return;
+    }
+
+    serial = alloc_object( &serial_ops, fd );
+    if (serial)
+    {
+        strncpy(serial->name,req->name,sizeof serial->name);
+        serial->name[sizeof(serial->name)-1] = 0;
+
+        serial->access       = req->access;
+        serial->readinterval = 0;
+        serial->readmult     = 0;
+        serial->readconst    = 0;
+        serial->writemult    = 0;
+        serial->writeconst   = 0;
+        serial->eventmask    = 0;
+        serial->commerror    = 0;
+
+        req->handle = alloc_handle( current->process, serial, req->access, req->inherit );
+        release_object( serial );
+    }
+}
+