Added support for multiple object namespaces, and a bunch functions
for managing linked lists.
This commit is contained in:
parent
c401270d60
commit
526a28de51
|
@ -65,7 +65,7 @@ struct event *create_event( const WCHAR *name, size_t len,
|
|||
{
|
||||
struct event *event;
|
||||
|
||||
if ((event = create_named_object( &event_ops, name, len )))
|
||||
if ((event = create_named_object( sync_namespace, &event_ops, name, len )))
|
||||
{
|
||||
if (get_error() != STATUS_OBJECT_NAME_COLLISION)
|
||||
{
|
||||
|
@ -145,7 +145,7 @@ DECL_HANDLER(create_event)
|
|||
/* open a handle to an event */
|
||||
DECL_HANDLER(open_event)
|
||||
{
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(),
|
||||
&event_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ static void handle_table_destroy( struct object *obj )
|
|||
}
|
||||
|
||||
/* allocate a new handle table */
|
||||
struct object *alloc_handle_table( struct process *process, int count )
|
||||
struct handle_table *alloc_handle_table( struct process *process, int count )
|
||||
{
|
||||
struct handle_table *table;
|
||||
|
||||
|
@ -165,7 +165,7 @@ struct object *alloc_handle_table( struct process *process, int count )
|
|||
table->count = count;
|
||||
table->last = -1;
|
||||
table->free = 0;
|
||||
if ((table->entries = mem_alloc( count * sizeof(*table->entries) ))) return &table->obj;
|
||||
if ((table->entries = mem_alloc( count * sizeof(*table->entries) ))) return table;
|
||||
release_object( table );
|
||||
return NULL;
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ static obj_handle_t alloc_entry( struct handle_table *table, void *obj, unsigned
|
|||
/* return the handle, or 0 on error */
|
||||
obj_handle_t 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 = process->handles;
|
||||
|
||||
assert( table );
|
||||
assert( !(access & RESERVED_ALL) );
|
||||
|
@ -236,7 +236,7 @@ static obj_handle_t alloc_global_handle( void *obj, unsigned int access )
|
|||
/* return a handle entry, or NULL if the handle is invalid */
|
||||
static struct handle_entry *get_handle( struct process *process, obj_handle_t handle )
|
||||
{
|
||||
struct handle_table *table = (struct handle_table *)process->handles;
|
||||
struct handle_table *table = process->handles;
|
||||
struct handle_entry *entry;
|
||||
int index;
|
||||
|
||||
|
@ -281,9 +281,9 @@ static void shrink_handle_table( struct handle_table *table )
|
|||
|
||||
/* copy the handle table of the parent process */
|
||||
/* return 1 if OK, 0 on error */
|
||||
struct object *copy_handle_table( struct process *process, struct process *parent )
|
||||
struct handle_table *copy_handle_table( struct process *process, struct process *parent )
|
||||
{
|
||||
struct handle_table *parent_table = (struct handle_table *)parent->handles;
|
||||
struct handle_table *parent_table = parent->handles;
|
||||
struct handle_table *table;
|
||||
int i;
|
||||
|
||||
|
@ -307,7 +307,7 @@ struct object *copy_handle_table( struct process *process, struct process *paren
|
|||
}
|
||||
/* attempt to shrink the table */
|
||||
shrink_handle_table( table );
|
||||
return &table->obj;
|
||||
return table;
|
||||
}
|
||||
|
||||
/* close a handle and decrement the refcount of the associated object */
|
||||
|
@ -329,7 +329,7 @@ int close_handle( struct process *process, obj_handle_t handle, int *fd )
|
|||
if (fd) *fd = entry->fd;
|
||||
else if (entry->fd != -1) return 1; /* silently ignore close attempt if we cannot close the fd */
|
||||
entry->fd = -1;
|
||||
table = handle_is_global(handle) ? global_table : (struct handle_table *)process->handles;
|
||||
table = handle_is_global(handle) ? global_table : process->handles;
|
||||
if (entry < table->entries + table->free) table->free = entry - table->entries;
|
||||
if (entry == table->entries + table->last) shrink_handle_table( table );
|
||||
release_object( obj );
|
||||
|
@ -400,10 +400,28 @@ int get_handle_fd( struct process *process, obj_handle_t handle, unsigned int ac
|
|||
return entry->fd;
|
||||
}
|
||||
|
||||
/* find the first inherited handle of the given type */
|
||||
/* this is needed for window stations and desktops (don't ask...) */
|
||||
obj_handle_t find_inherited_handle( struct process *process, const struct object_ops *ops )
|
||||
{
|
||||
struct handle_table *table = process->handles;
|
||||
struct handle_entry *ptr;
|
||||
int i;
|
||||
|
||||
if (!table) return 0;
|
||||
|
||||
for (i = 0, ptr = table->entries; i <= table->last; i++, ptr++)
|
||||
{
|
||||
if (!ptr->ptr) continue;
|
||||
if (ptr->ptr->ops != ops) continue;
|
||||
if (ptr->access & RESERVED_INHERIT) return index_to_handle(i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get/set the handle reserved flags */
|
||||
/* return the old flags (or -1 on error) */
|
||||
static int set_handle_info( struct process *process, obj_handle_t handle,
|
||||
int mask, int flags, int *fd )
|
||||
int set_handle_info( struct process *process, obj_handle_t handle, int mask, int flags, int *fd )
|
||||
{
|
||||
struct handle_entry *entry;
|
||||
unsigned int old_access;
|
||||
|
@ -454,11 +472,11 @@ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, str
|
|||
}
|
||||
|
||||
/* open a new handle to an existing object */
|
||||
obj_handle_t open_object( const WCHAR *name, size_t len, const struct object_ops *ops,
|
||||
unsigned int access, int inherit )
|
||||
obj_handle_t open_object( const struct namespace *namespace, const WCHAR *name, size_t len,
|
||||
const struct object_ops *ops, unsigned int access, int inherit )
|
||||
{
|
||||
obj_handle_t handle = 0;
|
||||
struct object *obj = find_object( name, len );
|
||||
struct object *obj = find_object( namespace, name, len );
|
||||
if (obj)
|
||||
{
|
||||
if (ops && obj->ops != ops)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
struct process;
|
||||
struct object_ops;
|
||||
struct namespace;
|
||||
|
||||
/* handle functions */
|
||||
|
||||
|
@ -38,12 +39,14 @@ extern int close_handle( struct process *process, obj_handle_t handle, int *fd )
|
|||
extern struct object *get_handle_obj( struct process *process, obj_handle_t handle,
|
||||
unsigned int access, const struct object_ops *ops );
|
||||
extern int get_handle_fd( struct process *process, obj_handle_t handle, unsigned int access );
|
||||
extern int set_handle_info( struct process *process, obj_handle_t handle, int mask, int flags, int *fd );
|
||||
extern obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, struct process *dst,
|
||||
unsigned int access, int inherit, int options );
|
||||
extern obj_handle_t open_object( const WCHAR *name, size_t len, const struct object_ops *ops,
|
||||
unsigned int access, int inherit );
|
||||
extern struct object *alloc_handle_table( struct process *process, int count );
|
||||
extern struct object *copy_handle_table( struct process *process, struct process *parent );
|
||||
extern obj_handle_t open_object( const struct namespace *namespace, const WCHAR *name, size_t len,
|
||||
const struct object_ops *ops, unsigned int access, int inherit );
|
||||
extern obj_handle_t find_inherited_handle( struct process *process, const struct object_ops *ops );
|
||||
extern struct handle_table *alloc_handle_table( struct process *process, int count );
|
||||
extern struct handle_table *copy_handle_table( struct process *process, struct process *parent );
|
||||
extern void close_global_handles(void);
|
||||
|
||||
#endif /* __WINE_SERVER_HANDLE_H */
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Linked lists support
|
||||
*
|
||||
* Copyright (C) 2002 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_SERVER_LIST_H
|
||||
#define __WINE_SERVER_LIST_H
|
||||
|
||||
struct list
|
||||
{
|
||||
struct list *next;
|
||||
struct list *prev;
|
||||
};
|
||||
|
||||
/* add element at the head of the list */
|
||||
inline static void list_add_head( struct list *list, struct list *elem )
|
||||
{
|
||||
elem->next = list->next;
|
||||
elem->prev = list;
|
||||
list->next->prev = elem;
|
||||
list->next = elem;
|
||||
}
|
||||
|
||||
/* add element at the tail of the list */
|
||||
inline static void list_add_tail( struct list *list, struct list *elem )
|
||||
{
|
||||
elem->next = list;
|
||||
elem->prev = list->prev;
|
||||
list->prev->next = elem;
|
||||
list->prev = elem;
|
||||
}
|
||||
|
||||
/* remove an element from its list */
|
||||
inline static void list_remove( struct list *elem )
|
||||
{
|
||||
elem->next->prev = elem->prev;
|
||||
elem->prev->next = elem->next;
|
||||
}
|
||||
|
||||
/* initialize a list */
|
||||
inline static void list_init( struct list *list )
|
||||
{
|
||||
list->next = list->prev = list;
|
||||
}
|
||||
|
||||
/* iterate through the list */
|
||||
#define LIST_FOR_EACH(cursor,list) \
|
||||
for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)
|
||||
|
||||
/* macros for statically initialized lists */
|
||||
#define LIST_INIT(list) { &(list), &(list) }
|
||||
|
||||
/* get pointer to object containing list element */
|
||||
#define LIST_ENTRY(elem, type, field) \
|
||||
((type *)((char *)(elem) - (unsigned int)(&((type *)0)->field)))
|
||||
|
||||
#endif /* __WINE_SERVER_LIST_H */
|
|
@ -36,6 +36,9 @@ int debug_level = 0;
|
|||
int master_socket_timeout = 3; /* master socket timeout in seconds, default is 3 s */
|
||||
const char *server_argv0;
|
||||
|
||||
/* name space for synchronization objects */
|
||||
struct namespace *sync_namespace;
|
||||
|
||||
/* parse-line args */
|
||||
/* FIXME: should probably use getopt, and add a (more complete?) help option */
|
||||
|
||||
|
@ -118,6 +121,7 @@ int main( int argc, char *argv[] )
|
|||
signal_init();
|
||||
sock_init();
|
||||
open_master_socket();
|
||||
sync_namespace = create_namespace( 37, TRUE );
|
||||
setvbuf( stderr, NULL, _IOLBF, 0 );
|
||||
|
||||
if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
|
||||
|
|
|
@ -263,7 +263,7 @@ static struct object *create_mapping( int size_high, int size_low, int protect,
|
|||
|
||||
if (!page_mask) init_page_size();
|
||||
|
||||
if (!(mapping = create_named_object( &mapping_ops, name, len )))
|
||||
if (!(mapping = create_named_object( sync_namespace, &mapping_ops, name, len )))
|
||||
return NULL;
|
||||
if (get_error() == STATUS_OBJECT_NAME_COLLISION)
|
||||
return &mapping->obj; /* Nothing else to do */
|
||||
|
@ -383,7 +383,7 @@ DECL_HANDLER(create_mapping)
|
|||
/* open a handle to a mapping */
|
||||
DECL_HANDLER(open_mapping)
|
||||
{
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(),
|
||||
&mapping_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ static struct mutex *create_mutex( const WCHAR *name, size_t len, int owned )
|
|||
{
|
||||
struct mutex *mutex;
|
||||
|
||||
if ((mutex = create_named_object( &mutex_ops, name, len )))
|
||||
if ((mutex = create_named_object( sync_namespace, &mutex_ops, name, len )))
|
||||
{
|
||||
if (get_error() != STATUS_OBJECT_NAME_COLLISION)
|
||||
{
|
||||
|
@ -169,7 +169,7 @@ DECL_HANDLER(create_mutex)
|
|||
/* open a handle to a mutex */
|
||||
DECL_HANDLER(open_mutex)
|
||||
{
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(),
|
||||
&mutex_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ static struct named_pipe *create_named_pipe( const WCHAR *name, size_t len )
|
|||
{
|
||||
struct named_pipe *pipe;
|
||||
|
||||
if ((pipe = create_named_object( &named_pipe_ops, name, len )))
|
||||
if ((pipe = create_named_object( sync_namespace, &named_pipe_ops, name, len )))
|
||||
{
|
||||
if (get_error() != STATUS_OBJECT_NAME_COLLISION)
|
||||
{
|
||||
|
|
110
server/object.c
110
server/object.c
|
@ -30,32 +30,37 @@
|
|||
|
||||
#include "thread.h"
|
||||
#include "unicode.h"
|
||||
#include "list.h"
|
||||
|
||||
|
||||
struct object_name
|
||||
{
|
||||
struct object_name *next;
|
||||
struct object_name *prev;
|
||||
struct list entry; /* entry in the hash list */
|
||||
struct object *obj;
|
||||
size_t len;
|
||||
WCHAR name[1];
|
||||
};
|
||||
|
||||
#define NAME_HASH_SIZE 37
|
||||
struct namespace
|
||||
{
|
||||
unsigned int hash_size; /* size of hash table */
|
||||
int case_sensitive; /* are names case sensitive? */
|
||||
struct list names[1]; /* array of hash entry lists */
|
||||
};
|
||||
|
||||
static struct object_name *names[NAME_HASH_SIZE];
|
||||
|
||||
#ifdef DEBUG_OBJECTS
|
||||
static struct object *first;
|
||||
static struct list object_list = LIST_INIT(object_list);
|
||||
|
||||
void dump_objects(void)
|
||||
{
|
||||
struct object *ptr = first;
|
||||
while (ptr)
|
||||
struct list *p;
|
||||
|
||||
LIST_FOR_EACH( p, &object_list )
|
||||
{
|
||||
struct object *ptr = LIST_ENTRY( p, struct object, obj_list );
|
||||
fprintf( stderr, "%p:%d: ", ptr, ptr->refcount );
|
||||
ptr->ops->dump( ptr, 1 );
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -83,12 +88,13 @@ void *memdup( const void *data, size_t len )
|
|||
|
||||
/*****************************************************************/
|
||||
|
||||
static int get_name_hash( const WCHAR *name, size_t len )
|
||||
static int get_name_hash( const struct namespace *namespace, const WCHAR *name, size_t len )
|
||||
{
|
||||
WCHAR hash = 0;
|
||||
len /= sizeof(WCHAR);
|
||||
while (len--) hash ^= *name++;
|
||||
return hash % NAME_HASH_SIZE;
|
||||
if (namespace->case_sensitive) while (len--) hash ^= *name++;
|
||||
else while (len--) hash ^= tolowerW(*name++);
|
||||
return hash % namespace->hash_size;
|
||||
}
|
||||
|
||||
/* allocate a name for an object */
|
||||
|
@ -108,31 +114,18 @@ static struct object_name *alloc_name( const WCHAR *name, size_t len )
|
|||
static void free_name( struct object *obj )
|
||||
{
|
||||
struct object_name *ptr = obj->name;
|
||||
if (ptr->next) ptr->next->prev = ptr->prev;
|
||||
if (ptr->prev) ptr->prev->next = ptr->next;
|
||||
else
|
||||
{
|
||||
int hash;
|
||||
for (hash = 0; hash < NAME_HASH_SIZE; hash++)
|
||||
if (names[hash] == ptr)
|
||||
{
|
||||
names[hash] = ptr->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
list_remove( &ptr->entry );
|
||||
free( ptr );
|
||||
}
|
||||
|
||||
/* set the name of an existing object */
|
||||
static void set_object_name( struct object *obj, struct object_name *ptr )
|
||||
static void set_object_name( struct namespace *namespace,
|
||||
struct object *obj, struct object_name *ptr )
|
||||
{
|
||||
int hash = get_name_hash( ptr->name, ptr->len );
|
||||
int hash = get_name_hash( namespace, ptr->name, ptr->len );
|
||||
|
||||
if ((ptr->next = names[hash]) != NULL) ptr->next->prev = ptr;
|
||||
list_add_head( &namespace->names[hash], &ptr->entry );
|
||||
ptr->obj = obj;
|
||||
ptr->prev = NULL;
|
||||
names[hash] = ptr;
|
||||
assert( !obj->name );
|
||||
obj->name = ptr;
|
||||
}
|
||||
|
||||
|
@ -157,9 +150,7 @@ void *alloc_object( const struct object_ops *ops, int fd )
|
|||
return NULL;
|
||||
}
|
||||
#ifdef DEBUG_OBJECTS
|
||||
obj->prev = NULL;
|
||||
if ((obj->next = first) != NULL) obj->next->prev = obj;
|
||||
first = obj;
|
||||
list_add_head( &object_list, &obj->obj_list );
|
||||
#endif
|
||||
return obj;
|
||||
}
|
||||
|
@ -167,17 +158,16 @@ void *alloc_object( const struct object_ops *ops, int fd )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void *create_named_object( const struct object_ops *ops, const WCHAR *name, size_t len )
|
||||
void *create_named_object( struct namespace *namespace, const struct object_ops *ops,
|
||||
const WCHAR *name, size_t len )
|
||||
{
|
||||
struct object *obj;
|
||||
struct object_name *name_ptr;
|
||||
|
||||
if (!name || !len) return alloc_object( ops, -1 );
|
||||
if (!(name_ptr = alloc_name( name, len ))) return NULL;
|
||||
|
||||
if ((obj = find_object( name_ptr->name, name_ptr->len )))
|
||||
if ((obj = find_object( namespace, name, len )))
|
||||
{
|
||||
free( name_ptr ); /* we no longer need it */
|
||||
if (obj->ops == ops)
|
||||
{
|
||||
set_error( STATUS_OBJECT_NAME_COLLISION );
|
||||
|
@ -186,9 +176,10 @@ void *create_named_object( const struct object_ops *ops, const WCHAR *name, size
|
|||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
return NULL;
|
||||
}
|
||||
if (!(name_ptr = alloc_name( name, len ))) return NULL;
|
||||
if ((obj = alloc_object( ops, -1 )))
|
||||
{
|
||||
set_object_name( obj, name_ptr );
|
||||
set_object_name( namespace, obj, name_ptr );
|
||||
clear_error();
|
||||
}
|
||||
else free( name_ptr );
|
||||
|
@ -231,9 +222,7 @@ void release_object( void *ptr )
|
|||
if (obj->select != -1) remove_select_user( obj );
|
||||
if (obj->fd != -1) close( obj->fd );
|
||||
#ifdef DEBUG_OBJECTS
|
||||
if (obj->next) obj->next->prev = obj->prev;
|
||||
if (obj->prev) obj->prev->next = obj->next;
|
||||
else first = obj->next;
|
||||
list_remove( &obj->obj_list );
|
||||
memset( obj, 0xaa, obj->ops->size );
|
||||
#endif
|
||||
free( obj );
|
||||
|
@ -241,19 +230,50 @@ void release_object( void *ptr )
|
|||
}
|
||||
|
||||
/* find an object by its name; the refcount is incremented */
|
||||
struct object *find_object( const WCHAR *name, size_t len )
|
||||
struct object *find_object( const struct namespace *namespace, const WCHAR *name, size_t len )
|
||||
{
|
||||
struct object_name *ptr;
|
||||
const struct list *list, *p;
|
||||
|
||||
if (!name || !len) return NULL;
|
||||
for (ptr = names[ get_name_hash( name, len ) ]; ptr; ptr = ptr->next)
|
||||
|
||||
list = &namespace->names[ get_name_hash( namespace, name, len ) ];
|
||||
if (namespace->case_sensitive)
|
||||
{
|
||||
if (ptr->len != len) continue;
|
||||
if (!memcmp( ptr->name, name, len )) return grab_object( ptr->obj );
|
||||
LIST_FOR_EACH( p, list )
|
||||
{
|
||||
struct object_name *ptr = LIST_ENTRY( p, struct object_name, entry );
|
||||
if (ptr->len != len) continue;
|
||||
if (!memcmp( ptr->name, name, len )) return grab_object( ptr->obj );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST_FOR_EACH( p, list )
|
||||
{
|
||||
struct object_name *ptr = LIST_ENTRY( p, struct object_name, entry );
|
||||
if (ptr->len != len) continue;
|
||||
if (!strncmpiW( ptr->name, name, len/sizeof(WCHAR) )) return grab_object( ptr->obj );
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* allocate a namespace */
|
||||
struct namespace *create_namespace( unsigned int hash_size, int case_sensitive )
|
||||
{
|
||||
struct namespace *namespace;
|
||||
unsigned int i;
|
||||
|
||||
namespace = mem_alloc( sizeof(*namespace) + (hash_size - 1) * sizeof(namespace->names[0]) );
|
||||
if (namespace)
|
||||
{
|
||||
namespace->hash_size = hash_size;
|
||||
namespace->case_sensitive = case_sensitive;
|
||||
for (i = 0; i < hash_size; i++) list_init( &namespace->names[i] );
|
||||
}
|
||||
return namespace;
|
||||
}
|
||||
|
||||
/* functions for unimplemented/default object operations */
|
||||
|
||||
int no_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
||||
|
|
|
@ -24,11 +24,13 @@
|
|||
#include <sys/poll.h>
|
||||
#include <sys/time.h>
|
||||
#include "wine/server_protocol.h"
|
||||
#include "list.h"
|
||||
|
||||
#define DEBUG_OBJECTS
|
||||
|
||||
/* kernel objects */
|
||||
|
||||
struct namespace;
|
||||
struct object;
|
||||
struct object_name;
|
||||
struct thread;
|
||||
|
@ -79,8 +81,7 @@ struct object
|
|||
struct wait_queue_entry *tail;
|
||||
struct object_name *name;
|
||||
#ifdef DEBUG_OBJECTS
|
||||
struct object *prev;
|
||||
struct object *next;
|
||||
struct list obj_list;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -96,12 +97,14 @@ extern void *mem_alloc( size_t size ); /* malloc wrapper */
|
|||
extern void *memdup( const void *data, size_t len );
|
||||
extern void *alloc_object( const struct object_ops *ops, int fd );
|
||||
extern void dump_object_name( struct object *obj );
|
||||
extern void *create_named_object( const struct object_ops *ops, const WCHAR *name, size_t len );
|
||||
extern void *create_named_object( struct namespace *namespace, const struct object_ops *ops,
|
||||
const WCHAR *name, size_t len );
|
||||
extern struct namespace *create_namespace( unsigned int hash_size, int case_sensitive );
|
||||
/* grab/release_object can take any pointer, but you better make sure */
|
||||
/* that the thing pointed to starts with a struct object... */
|
||||
extern struct object *grab_object( void *obj );
|
||||
extern void release_object( void *obj );
|
||||
extern struct object *find_object( const WCHAR *name, size_t len );
|
||||
extern struct object *find_object( const struct namespace *namespace, const WCHAR *name, size_t len );
|
||||
extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||
extern int no_satisfied( struct object *obj, struct thread *thread );
|
||||
extern int no_get_fd( struct object *obj );
|
||||
|
@ -209,4 +212,7 @@ extern const char *server_argv0;
|
|||
/* server start time used for GetTickCount() */
|
||||
extern unsigned int server_start_ticks;
|
||||
|
||||
/* name space for synchronization objects */
|
||||
extern struct namespace *sync_namespace;
|
||||
|
||||
#endif /* __WINE_SERVER_OBJECT_H */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
struct msg_queue;
|
||||
struct atom_table;
|
||||
struct handle_table;
|
||||
struct startup_info;
|
||||
|
||||
/* process startup state */
|
||||
|
@ -54,7 +55,7 @@ struct process
|
|||
struct process *parent; /* parent process */
|
||||
struct thread *thread_list; /* head of the thread list */
|
||||
struct thread *debugger; /* thread debugging this process */
|
||||
struct object *handles; /* handle entries */
|
||||
struct handle_table *handles; /* handle entries */
|
||||
int exit_code; /* process exit code */
|
||||
int running_threads; /* number of threads running in this process */
|
||||
struct timeval start_time; /* absolute time at process start */
|
||||
|
|
|
@ -70,7 +70,7 @@ static struct semaphore *create_semaphore( const WCHAR *name, size_t len,
|
|||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return NULL;
|
||||
}
|
||||
if ((sem = create_named_object( &semaphore_ops, name, len )))
|
||||
if ((sem = create_named_object( sync_namespace, &semaphore_ops, name, len )))
|
||||
{
|
||||
if (get_error() != STATUS_OBJECT_NAME_COLLISION)
|
||||
{
|
||||
|
@ -153,7 +153,7 @@ DECL_HANDLER(create_semaphore)
|
|||
/* open a handle to a semaphore */
|
||||
DECL_HANDLER(open_semaphore)
|
||||
{
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(),
|
||||
&semaphore_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ 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 ((timer = create_named_object( sync_namespace, &timer_ops, name, len )))
|
||||
{
|
||||
if (get_error() != STATUS_OBJECT_NAME_COLLISION)
|
||||
{
|
||||
|
@ -211,7 +211,7 @@ DECL_HANDLER(create_timer)
|
|||
/* open a handle to a timer */
|
||||
DECL_HANDLER(open_timer)
|
||||
{
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(),
|
||||
&timer_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue