Moved all references to file descriptors out of the generic object
structure.
Changed the poll()-related routines to deal with file descriptors
instead of objects and integrated poll support into fd.c.

diff --git a/server/file.c b/server/file.c
index 7518a09..2544bba 100644
--- a/server/file.c
+++ b/server/file.c
@@ -51,6 +51,7 @@
 struct file
 {
     struct object       obj;        /* object header */
+    struct fd          *fd;         /* file descriptor for this file */
     struct file        *next;       /* next file in hashing list */
     char               *name;       /* file name */
     unsigned int        access;     /* file access (GENERIC_READ/WRITE) */
@@ -66,6 +67,7 @@
 static struct file *file_hash[NAME_HASH_SIZE];
 
 static void file_dump( struct object *obj, int verbose );
+static struct fd *file_get_fd( struct object *obj );
 static void file_destroy( struct object *obj );
 
 static int file_get_poll_events( struct fd *fd );
@@ -82,7 +84,7 @@
     default_fd_remove_queue,      /* remove_queue */
     default_fd_signaled,          /* signaled */
     no_satisfied,                 /* satisfied */
-    default_get_fd,               /* get_fd */
+    file_get_fd,                  /* get_fd */
     file_destroy                  /* destroy */
 };
 
@@ -134,7 +136,7 @@
 {
     struct file *file;
 
-    if ((file = alloc_fd_object( &file_ops, &file_fd_ops, fd )))
+    if ((file = alloc_object( &file_ops )))
     {
         file->name       = NULL;
         file->next       = NULL;
@@ -147,6 +149,11 @@
             init_async_queue (&file->read_q);
             init_async_queue (&file->write_q);
         }
+        if (!(file->fd = alloc_fd( &file_fd_ops, fd, &file->obj )))
+        {
+            release_object( file );
+            return NULL;
+        }
     }
     return file;
 }
@@ -264,7 +271,7 @@
 {
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
-    fprintf( stderr, "File fd=%p flags=%08x name='%s'\n", file->obj.fd_obj, file->flags, file->name );
+    fprintf( stderr, "File fd=%p flags=%08x name='%s'\n", file->fd, file->flags, file->name );
 }
 
 static int file_get_poll_events( struct fd *fd )
@@ -395,7 +402,14 @@
     else if ( async ) destroy_async ( async );
     else set_error ( STATUS_INVALID_PARAMETER );
 
-    set_select_events( &file->obj, file_get_poll_events( fd ));
+    set_fd_events( fd, file_get_poll_events( fd ));
+}
+
+static struct fd *file_get_fd( struct object *obj )
+{
+    struct file *file = (struct file *)obj;
+    assert( obj->ops == &file_ops );
+    return (struct fd *)grab_object( file->fd );
 }
 
 static void file_destroy( struct object *obj )
@@ -418,6 +432,7 @@
         destroy_async_queue (&file->read_q);
         destroy_async_queue (&file->write_q);
     }
+    if (file->fd) release_object( file->fd );
 }
 
 /* set the last error depending on errno */
@@ -453,7 +468,7 @@
 
 int get_file_unix_fd( struct file *file )
 {
-    return get_unix_fd( file->obj.fd_obj );
+    return get_unix_fd( file->fd );
 }
 
 static int set_file_pointer( obj_handle_t handle, unsigned int *low, int *high, int whence )