Made all handles multiple of 4. Fixed semantics for pseudo-handles.

diff --git a/server/handle.c b/server/handle.c
index 8619e8b..541dc5c 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -51,6 +51,19 @@
 #define MIN_HANDLE_ENTRIES  32
 
 
+/* handle to table index conversion */
+
+/* handles are a multiple of 4 under NT; handle  0 is not used */
+static int inline index_to_handle( int index )
+{
+    return (index + 1) << 2;
+}
+static int inline handle_to_index( int handle )
+{
+    return (handle >> 2) - 1;
+}
+
+
 static void handle_table_dump( struct object *obj, int verbose );
 static void handle_table_destroy( struct object *obj );
 
@@ -85,7 +98,7 @@
     for (i = 0; i <= table->last; i++, entry++)
     {
         if (!entry->ptr) continue;
-        fprintf( stderr, "%9d: %p %08x ", i + 1, entry->ptr, entry->access );
+        fprintf( stderr, "%9d: %p %08x ", index_to_handle(i), entry->ptr, entry->access );
         entry->ptr->ops->dump( entry->ptr, 0 );
     }
 }
@@ -143,23 +156,24 @@
     return 1;
 }
 
-/* find the first free entry in the handle table */
-static struct handle_entry *get_free_entry( struct handle_table *table, int *phandle )
+/* allocate the first free entry in the handle table */
+static int alloc_entry( struct handle_table *table, void *obj, unsigned int access )
 {
     struct handle_entry *entry = table->entries + table->free;
-    int handle;
+    int i;
 
-    for (handle = table->free; handle <= table->last; handle++, entry++)
-        if (!entry->ptr) goto found;
-    if (handle >= table->count)
+    for (i = table->free; i <= table->last; i++, entry++) if (!entry->ptr) goto found;
+    if (i >= table->count)
     {
-        if (!grow_handle_table( table )) return NULL;
-        entry = table->entries + handle;  /* the entries may have moved */
+        if (!grow_handle_table( table )) return -1;
+        entry = table->entries + i;  /* the entries may have moved */
     }
-    table->last = handle;
+    table->last = i;
  found:
-    table->free = *phandle = handle + 1;  /* avoid handle 0 */
-    return entry;
+    table->free = i + 1;
+    entry->ptr    = grab_object( obj );
+    entry->access = access;
+    return index_to_handle(i);
 }
 
 /* allocate a handle for an object, incrementing its refcount */
@@ -167,37 +181,29 @@
 int alloc_handle( struct process *process, void *obj, unsigned int access, int inherit )
 {
     struct handle_table *table = (struct handle_table *)process->handles;
-    struct handle_entry *entry;
-    int handle;
 
     assert( table );
     assert( !(access & RESERVED_ALL) );
     if (inherit) access |= RESERVED_INHERIT;
-
-    if (!(entry = get_free_entry( table, &handle ))) return -1;
-    entry->ptr    = grab_object( obj );
-    entry->access = access;
-    return handle;
+    return alloc_entry( table, obj, access );
 }
 
 /* allocate a global handle for an object, incrementing its refcount */
 /* return the handle, or -1 on error */
 static int alloc_global_handle( void *obj, unsigned int access )
 {
-    struct handle_entry *entry;
     int handle;
 
     if (!global_table)
     {
         if (!(global_table = (struct handle_table *)alloc_handle_table( NULL, 0 ))) return -1;
     }
-    if (!(entry = get_free_entry( global_table, &handle ))) return -1;
-    entry->ptr    = grab_object( obj );
-    entry->access = access;
-    return HANDLE_LOCAL_TO_GLOBAL(handle);
+    if ((handle = alloc_entry( global_table, obj, access )) != -1)
+        handle = HANDLE_LOCAL_TO_GLOBAL(handle);
+    return handle;
 }
 
-/* return an handle entry, or NULL if the handle is invalid */
+/* return a handle entry, or NULL if the handle is invalid */
 static struct handle_entry *get_handle( struct process *process, int handle )
 {
     struct handle_table *table = (struct handle_table *)process->handles;
@@ -209,7 +215,7 @@
         table = global_table;
     }
     if (!table) goto error;
-    handle--;  /* handles start at 1 */
+    handle = handle_to_index( handle );
     if (handle < 0) goto error;
     if (handle > table->last) goto error;
     entry = table->entries + handle;
@@ -281,7 +287,11 @@
     struct object *obj;
 
     if (!(entry = get_handle( process, handle ))) return 0;
-    if (entry->access & RESERVED_CLOSE_PROTECT) return 0;  /* FIXME: error code */
+    if (entry->access & RESERVED_CLOSE_PROTECT)
+    {
+        set_error( ERROR_INVALID_HANDLE );
+        return 0;
+    }
     obj = entry->ptr;
     entry->ptr = NULL;
     table = HANDLE_IS_GLOBAL(handle) ? global_table : (struct handle_table *)process->handles;
@@ -301,6 +311,21 @@
     }
 }
 
+/* retrieve the object corresponding to one of the magic pseudo-handles */
+static inline struct object *get_magic_handle( int handle )
+{
+    switch(handle)
+    {
+        case 0xfffffffe:  /* current thread pseudo-handle */
+            return &current->obj;
+        case 0x7fffffff:  /* current process pseudo-handle */
+        case 0xffffffff:  /* current process pseudo-handle */
+            return (struct object *)current->process;
+        default:
+            return NULL;
+    }
+}
+
 /* retrieve the object corresponding to a handle, incrementing its refcount */
 struct object *get_handle_obj( struct process *process, int handle,
                                unsigned int access, const struct object_ops *ops )
@@ -308,15 +333,8 @@
     struct handle_entry *entry;
     struct object *obj;
 
-    switch( handle )
+    if (!(obj = get_magic_handle( handle )))
     {
-    case 0xfffffffe:  /* current thread pseudo-handle */
-        obj = &current->obj;
-        break;
-    case 0x7fffffff:  /* current process pseudo-handle */
-        obj = (struct object *)current->process;
-        break;
-    default:
         if (!(entry = get_handle( process, handle ))) return NULL;
         if ((entry->access & access) != access)
         {
@@ -324,7 +342,6 @@
             return NULL;
         }
         obj = entry->ptr;
-        break;
     }
     if (ops && (obj->ops != ops))
     {
@@ -340,6 +357,12 @@
 {
     struct handle_entry *entry;
 
+    if (get_magic_handle( handle ))
+    {
+        /* we can retrieve but not set info for magic handles */
+        if (mask) set_error( ERROR_ACCESS_DENIED );
+        return 0;
+    }
     if (!(entry = get_handle( process, handle ))) return -1;
     mask  = (mask << RESERVED_SHIFT) & RESERVED_ALL;
     flags = (flags << RESERVED_SHIFT) & mask;