Made all handles multiple of 4. Fixed semantics for pseudo-handles.
This commit is contained in:
parent
1d22c531da
commit
ceeb69371c
|
@ -51,6 +51,19 @@ static struct handle_table *global_table;
|
||||||
#define MIN_HANDLE_ENTRIES 32
|
#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_dump( struct object *obj, int verbose );
|
||||||
static void handle_table_destroy( struct object *obj );
|
static void handle_table_destroy( struct object *obj );
|
||||||
|
|
||||||
|
@ -85,7 +98,7 @@ static void handle_table_dump( struct object *obj, int verbose )
|
||||||
for (i = 0; i <= table->last; i++, entry++)
|
for (i = 0; i <= table->last; i++, entry++)
|
||||||
{
|
{
|
||||||
if (!entry->ptr) continue;
|
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 );
|
entry->ptr->ops->dump( entry->ptr, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,23 +156,24 @@ static int grow_handle_table( struct handle_table *table )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find the first free entry in the handle table */
|
/* allocate the first free entry in the handle table */
|
||||||
static struct handle_entry *get_free_entry( struct handle_table *table, int *phandle )
|
static int alloc_entry( struct handle_table *table, void *obj, unsigned int access )
|
||||||
{
|
{
|
||||||
struct handle_entry *entry = table->entries + table->free;
|
struct handle_entry *entry = table->entries + table->free;
|
||||||
int handle;
|
int i;
|
||||||
|
|
||||||
for (handle = table->free; handle <= table->last; handle++, entry++)
|
for (i = table->free; i <= table->last; i++, entry++) if (!entry->ptr) goto found;
|
||||||
if (!entry->ptr) goto found;
|
if (i >= table->count)
|
||||||
if (handle >= table->count)
|
|
||||||
{
|
{
|
||||||
if (!grow_handle_table( table )) return NULL;
|
if (!grow_handle_table( table )) return -1;
|
||||||
entry = table->entries + handle; /* the entries may have moved */
|
entry = table->entries + i; /* the entries may have moved */
|
||||||
}
|
}
|
||||||
table->last = handle;
|
table->last = i;
|
||||||
found:
|
found:
|
||||||
table->free = *phandle = handle + 1; /* avoid handle 0 */
|
table->free = i + 1;
|
||||||
return entry;
|
entry->ptr = grab_object( obj );
|
||||||
|
entry->access = access;
|
||||||
|
return index_to_handle(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a handle for an object, incrementing its refcount */
|
/* allocate a handle for an object, incrementing its refcount */
|
||||||
|
@ -167,37 +181,29 @@ static struct handle_entry *get_free_entry( struct handle_table *table, int *pha
|
||||||
int alloc_handle( struct process *process, void *obj, unsigned int access, int inherit )
|
int alloc_handle( struct process *process, void *obj, unsigned int access, int inherit )
|
||||||
{
|
{
|
||||||
struct handle_table *table = (struct handle_table *)process->handles;
|
struct handle_table *table = (struct handle_table *)process->handles;
|
||||||
struct handle_entry *entry;
|
|
||||||
int handle;
|
|
||||||
|
|
||||||
assert( table );
|
assert( table );
|
||||||
assert( !(access & RESERVED_ALL) );
|
assert( !(access & RESERVED_ALL) );
|
||||||
if (inherit) access |= RESERVED_INHERIT;
|
if (inherit) access |= RESERVED_INHERIT;
|
||||||
|
return alloc_entry( table, obj, access );
|
||||||
if (!(entry = get_free_entry( table, &handle ))) return -1;
|
|
||||||
entry->ptr = grab_object( obj );
|
|
||||||
entry->access = access;
|
|
||||||
return handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a global handle for an object, incrementing its refcount */
|
/* allocate a global handle for an object, incrementing its refcount */
|
||||||
/* return the handle, or -1 on error */
|
/* return the handle, or -1 on error */
|
||||||
static int alloc_global_handle( void *obj, unsigned int access )
|
static int alloc_global_handle( void *obj, unsigned int access )
|
||||||
{
|
{
|
||||||
struct handle_entry *entry;
|
|
||||||
int handle;
|
int handle;
|
||||||
|
|
||||||
if (!global_table)
|
if (!global_table)
|
||||||
{
|
{
|
||||||
if (!(global_table = (struct handle_table *)alloc_handle_table( NULL, 0 ))) return -1;
|
if (!(global_table = (struct handle_table *)alloc_handle_table( NULL, 0 ))) return -1;
|
||||||
}
|
}
|
||||||
if (!(entry = get_free_entry( global_table, &handle ))) return -1;
|
if ((handle = alloc_entry( global_table, obj, access )) != -1)
|
||||||
entry->ptr = grab_object( obj );
|
handle = HANDLE_LOCAL_TO_GLOBAL(handle);
|
||||||
entry->access = access;
|
return handle;
|
||||||
return HANDLE_LOCAL_TO_GLOBAL(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 )
|
static struct handle_entry *get_handle( struct process *process, int handle )
|
||||||
{
|
{
|
||||||
struct handle_table *table = (struct handle_table *)process->handles;
|
struct handle_table *table = (struct handle_table *)process->handles;
|
||||||
|
@ -209,7 +215,7 @@ static struct handle_entry *get_handle( struct process *process, int handle )
|
||||||
table = global_table;
|
table = global_table;
|
||||||
}
|
}
|
||||||
if (!table) goto error;
|
if (!table) goto error;
|
||||||
handle--; /* handles start at 1 */
|
handle = handle_to_index( handle );
|
||||||
if (handle < 0) goto error;
|
if (handle < 0) goto error;
|
||||||
if (handle > table->last) goto error;
|
if (handle > table->last) goto error;
|
||||||
entry = table->entries + handle;
|
entry = table->entries + handle;
|
||||||
|
@ -281,7 +287,11 @@ int close_handle( struct process *process, int handle )
|
||||||
struct object *obj;
|
struct object *obj;
|
||||||
|
|
||||||
if (!(entry = get_handle( process, handle ))) return 0;
|
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;
|
obj = entry->ptr;
|
||||||
entry->ptr = NULL;
|
entry->ptr = NULL;
|
||||||
table = HANDLE_IS_GLOBAL(handle) ? global_table : (struct handle_table *)process->handles;
|
table = HANDLE_IS_GLOBAL(handle) ? global_table : (struct handle_table *)process->handles;
|
||||||
|
@ -301,6 +311,21 @@ void close_global_handles(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 ¤t->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 */
|
/* retrieve the object corresponding to a handle, incrementing its refcount */
|
||||||
struct object *get_handle_obj( struct process *process, int handle,
|
struct object *get_handle_obj( struct process *process, int handle,
|
||||||
unsigned int access, const struct object_ops *ops )
|
unsigned int access, const struct object_ops *ops )
|
||||||
|
@ -308,15 +333,8 @@ struct object *get_handle_obj( struct process *process, int handle,
|
||||||
struct handle_entry *entry;
|
struct handle_entry *entry;
|
||||||
struct object *obj;
|
struct object *obj;
|
||||||
|
|
||||||
switch( handle )
|
if (!(obj = get_magic_handle( handle )))
|
||||||
{
|
{
|
||||||
case 0xfffffffe: /* current thread pseudo-handle */
|
|
||||||
obj = ¤t->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 = get_handle( process, handle ))) return NULL;
|
||||||
if ((entry->access & access) != access)
|
if ((entry->access & access) != access)
|
||||||
{
|
{
|
||||||
|
@ -324,7 +342,6 @@ struct object *get_handle_obj( struct process *process, int handle,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
obj = entry->ptr;
|
obj = entry->ptr;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (ops && (obj->ops != ops))
|
if (ops && (obj->ops != ops))
|
||||||
{
|
{
|
||||||
|
@ -340,6 +357,12 @@ static int set_handle_info( struct process *process, int handle, int mask, int f
|
||||||
{
|
{
|
||||||
struct handle_entry *entry;
|
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;
|
if (!(entry = get_handle( process, handle ))) return -1;
|
||||||
mask = (mask << RESERVED_SHIFT) & RESERVED_ALL;
|
mask = (mask << RESERVED_SHIFT) & RESERVED_ALL;
|
||||||
flags = (flags << RESERVED_SHIFT) & mask;
|
flags = (flags << RESERVED_SHIFT) & mask;
|
||||||
|
|
Loading…
Reference in New Issue