diff --git a/include/server.h b/include/server.h index 106b9ac1807..4c0e9ee95c7 100644 --- a/include/server.h +++ b/include/server.h @@ -127,6 +127,9 @@ struct dup_handle_request int inherit; /* inherit flag */ int options; /* duplicate options (see below) */ }; +#define DUP_HANDLE_CLOSE_SOURCE DUPLICATE_CLOSE_SOURCE +#define DUP_HANDLE_SAME_ACCESS DUPLICATE_SAME_ACCESS +#define DUP_HANDLE_MAKE_GLOBAL 0x80000000 /* Not a Windows flag */ struct dup_handle_reply { int handle; /* duplicated handle in dst process */ @@ -212,7 +215,7 @@ struct create_semaphore_request unsigned int initial; /* initial count */ unsigned int max; /* maximum count */ int inherit; /* inherit flag */ - /* char name[] */ + char name[0]; /* semaphore name */ }; struct create_semaphore_reply { @@ -235,10 +238,10 @@ struct release_semaphore_reply /* Open a named object (event, mutex, semaphore) */ struct open_named_obj_request { - int type; /* object type (see below) */ - unsigned int access; /* wanted access rights */ - int inherit; /* inherit flag */ - /* char name[] */ + int type; /* object type (see below) */ + unsigned int access; /* wanted access rights */ + int inherit; /* inherit flag */ + char name[0]; /* object name */ }; enum open_named_obj { OPEN_EVENT, OPEN_MUTEX, OPEN_SEMAPHORE }; @@ -361,12 +364,25 @@ struct set_console_fd_request }; +/* Create a console */ +struct create_change_notification_request +{ + int subtree; /* watch all the subtree */ + int filter; /* notification filter */ +}; +struct create_change_notification_reply +{ + int handle; /* handle to the change notification */ +}; + + /* client-side functions */ #ifndef __WINE_SERVER__ +#include "server/request.h" + /* client communication functions */ -enum request; #define CHECK_LEN(len,wanted) \ if ((len) == (wanted)) ; \ else CLIENT_ProtocolError( __FUNCTION__ ": len %d != %d\n", (len), (wanted) ); @@ -380,8 +396,6 @@ struct _THDB; extern int CLIENT_NewThread( struct _THDB *thdb, int *thandle, int *phandle ); extern int CLIENT_SetDebug( int level ); extern int CLIENT_InitThread(void); -extern int CLIENT_TerminateProcess( int handle, int exit_code ); -extern int CLIENT_TerminateThread( int handle, int exit_code ); extern int CLIENT_CloseHandle( int handle ); extern int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process, int dst_handle, DWORD access, BOOL32 inherit, DWORD options ); diff --git a/include/server/object.h b/include/server/object.h index f0c4938eeca..fc34f166f33 100644 --- a/include/server/object.h +++ b/include/server/object.h @@ -189,6 +189,11 @@ extern int create_console( int fd, struct object *obj[2] ); extern int set_console_fd( int handle, int fd ); +/* change notification functions */ + +extern struct object *create_change_notification( int subtree, int filter ); + + extern int debug_level; #endif /* __WINE_SERVER_OBJECT_H */ diff --git a/include/server/request.h b/include/server/request.h index bd8ceaaed8b..993ae6e1e40 100644 --- a/include/server/request.h +++ b/include/server/request.h @@ -34,6 +34,7 @@ enum request REQ_CREATE_PIPE, REQ_CREATE_CONSOLE, REQ_SET_CONSOLE_FD, + REQ_CREATE_CHANGE_NOTIFICATION, REQ_NB_REQUESTS }; @@ -71,6 +72,7 @@ DECL_HANDLER(get_file_info); DECL_HANDLER(create_pipe); DECL_HANDLER(create_console); DECL_HANDLER(set_console_fd); +DECL_HANDLER(create_change_notification); static const struct handler { void (*handler)(); @@ -105,6 +107,7 @@ static const struct handler { { (void(*)())req_create_pipe, sizeof(struct create_pipe_request) }, { (void(*)())req_create_console, sizeof(struct create_console_request) }, { (void(*)())req_set_console_fd, sizeof(struct set_console_fd_request) }, + { (void(*)())req_create_change_notification, sizeof(struct create_change_notification_request) }, }; #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/Makefile.in b/server/Makefile.in index ae2e19cbc6e..6ea40846ef7 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -6,6 +6,7 @@ VPATH = @srcdir@ MODULE = server C_SRCS = \ + change.c \ console.c \ event.c \ file.c \ diff --git a/server/change.c b/server/change.c new file mode 100644 index 00000000000..6c7d38bb9f9 --- /dev/null +++ b/server/change.c @@ -0,0 +1,70 @@ +/* + * Server-side change notification management + * + * Copyright (C) 1998 Alexandre Julliard + */ + +#include +#include +#include + +#include "winerror.h" +#include "winnt.h" +#include "server/thread.h" + +struct change +{ + struct object obj; /* object header */ + int subtree; /* watch all the subtree */ + int filter; /* notification filter */ +}; + +static void change_dump( struct object *obj, int verbose ); +static int change_signaled( struct object *obj, struct thread *thread ); +static void change_destroy( struct object *obj ); + +static const struct object_ops change_ops = +{ + change_dump, + add_queue, + remove_queue, + change_signaled, + no_satisfied, + no_read_fd, + no_write_fd, + no_flush, + change_destroy +}; + + +struct object *create_change_notification( int subtree, int filter ) +{ + struct change *change; + if (!(change = mem_alloc( sizeof(*change) ))) return NULL; + init_object( &change->obj, &change_ops, NULL ); + change->subtree = subtree; + change->filter = filter; + return &change->obj; +} + +static void change_dump( struct object *obj, int verbose ) +{ + struct change *change = (struct change *)obj; + assert( obj->ops == &change_ops ); + printf( "Change notification sub=%d filter=%08x\n", + change->subtree, change->filter ); +} + +static int change_signaled( struct object *obj, struct thread *thread ) +{ +/* struct change *change = (struct change *)obj;*/ + assert( obj->ops == &change_ops ); + return 0; /* never signaled for now */ +} + +static void change_destroy( struct object *obj ) +{ + struct change *change = (struct change *)obj; + assert( obj->ops == &change_ops ); + free( change ); +} diff --git a/server/process.c b/server/process.c index 061218d232d..24dbde53a2e 100644 --- a/server/process.c +++ b/server/process.c @@ -25,6 +25,12 @@ #define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE << RESERVED_SHIFT) #define RESERVED_ALL (RESERVED_INHERIT | RESERVED_CLOSE_PROTECT) +/* global handle macros */ +#define HANDLE_OBFUSCATOR 0x544a4def +#define HANDLE_IS_GLOBAL(h) (((h) ^ HANDLE_OBFUSCATOR) < 0x10000) +#define HANDLE_LOCAL_TO_GLOBAL(h) ((h) ^ HANDLE_OBFUSCATOR) +#define HANDLE_GLOBAL_TO_LOCAL(h) ((h) ^ HANDLE_OBFUSCATOR) + struct handle_entry { struct object *ptr; @@ -49,6 +55,7 @@ struct process }; static struct process *first_process; +static struct process *initial_process; #define MIN_HANDLE_ENTRIES 32 @@ -94,6 +101,11 @@ struct process *create_process(void) if (first_process) first_process->prev = process; first_process = process; + if (!initial_process) + { + initial_process = process; + grab_object( initial_process ); /* so that we never free it */ + } gettimeofday( &process->start_time, NULL ); /* alloc a handle for the process itself */ @@ -106,6 +118,7 @@ static void process_destroy( struct object *obj ) { struct process *process = (struct process *)obj; assert( obj->ops == &process_ops ); + assert( process != initial_process ); /* we can't have a thread remaining */ assert( !process->thread_list ); @@ -288,6 +301,11 @@ static struct handle_entry *get_handle( struct process *process, int handle ) { struct handle_entry *entry; + if (HANDLE_IS_GLOBAL(handle)) + { + handle = HANDLE_GLOBAL_TO_LOCAL(handle); + process = initial_process; + } handle--; /* handles start at 1 */ if ((handle < 0) || (handle > process->handle_last)) goto error; entry = process->entries + handle; @@ -370,6 +388,11 @@ int close_handle( struct process *process, int handle ) struct handle_entry *entry; struct object *obj; + if (HANDLE_IS_GLOBAL(handle)) + { + handle = HANDLE_GLOBAL_TO_LOCAL(handle); + process = initial_process; + } if (!(entry = get_handle( process, handle ))) return 0; if (entry->access & RESERVED_CLOSE_PROTECT) return 0; /* FIXME: error code */ obj = entry->ptr; @@ -429,12 +452,16 @@ int set_handle_info( struct process *process, int handle, int mask, int flags ) int duplicate_handle( struct process *src, int src_handle, struct process *dst, int dst_handle, unsigned int access, int inherit, int options ) { + int res; struct handle_entry *entry = get_handle( src, src_handle ); if (!entry) return -1; - if (options & DUPLICATE_SAME_ACCESS) access = entry->access; + if (options & DUP_HANDLE_SAME_ACCESS) access = entry->access; + if (options & DUP_HANDLE_MAKE_GLOBAL) dst = initial_process; access &= ~RESERVED_ALL; - return alloc_specific_handle( dst, entry->ptr, dst_handle, access, inherit ); + res = alloc_specific_handle( dst, entry->ptr, dst_handle, access, inherit ); + if (options & DUP_HANDLE_MAKE_GLOBAL) res = HANDLE_LOCAL_TO_GLOBAL(res); + return res; } /* open a new handle to an existing object */ diff --git a/server/request.c b/server/request.c index 4d15d3b6b93..4913cf19898 100644 --- a/server/request.c +++ b/server/request.c @@ -204,14 +204,19 @@ DECL_HANDLER(dup_handle) if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE ))) { - if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE ))) + if (req->options & DUP_HANDLE_MAKE_GLOBAL) + { + reply.handle = duplicate_handle( src, req->src_handle, NULL, -1, + req->access, req->inherit, req->options ); + } + else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE ))) { reply.handle = duplicate_handle( src, req->src_handle, dst, req->dst_handle, req->access, req->inherit, req->options ); release_object( dst ); } /* close the handle no matter what happened */ - if (req->options & DUPLICATE_CLOSE_SOURCE) + if (req->options & DUP_HANDLE_CLOSE_SOURCE) close_handle( src, req->src_handle ); release_object( src ); } @@ -531,3 +536,19 @@ DECL_HANDLER(set_console_fd) set_console_fd( req->handle, fd ); send_reply( current, -1, 0 ); } + +/* create a change notification */ +DECL_HANDLER(create_change_notification) +{ + struct object *obj; + struct create_change_notification_reply reply = { -1 }; + + if ((obj = create_change_notification( req->subtree, req->filter ))) + { + reply.handle = alloc_handle( current->process, obj, + STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + diff --git a/server/trace.c b/server/trace.c index 199f8a677aa..1bc83ca8bc4 100644 --- a/server/trace.c +++ b/server/trace.c @@ -172,8 +172,9 @@ static int dump_create_semaphore_request( struct create_semaphore_request *req, { printf( " initial=%08x,", req->initial ); printf( " max=%08x,", req->max ); - printf( " inherit=%d", req->inherit ); - return (int)sizeof(*req); + printf( " inherit=%d,", req->inherit ); + printf( " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) ); + return len; } static int dump_create_semaphore_reply( struct create_semaphore_reply *req, int len ) @@ -199,8 +200,9 @@ static int dump_open_named_obj_request( struct open_named_obj_request *req, int { printf( " type=%d,", req->type ); printf( " access=%08x,", req->access ); - printf( " inherit=%d", req->inherit ); - return (int)sizeof(*req); + printf( " inherit=%d,", req->inherit ); + printf( " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) ); + return len; } static int dump_open_named_obj_reply( struct open_named_obj_reply *req, int len ) @@ -321,6 +323,19 @@ static int dump_set_console_fd_request( struct set_console_fd_request *req, int return (int)sizeof(*req); } +static int dump_create_change_notification_request( struct create_change_notification_request *req, int len ) +{ + printf( " subtree=%d,", req->subtree ); + printf( " filter=%d", req->filter ); + return (int)sizeof(*req); +} + +static int dump_create_change_notification_reply( struct create_change_notification_reply *req, int len ) +{ + printf( " handle=%d", req->handle ); + return (int)sizeof(*req); +} + struct dumper { int (*dump_req)( void *data, int len ); @@ -387,6 +402,8 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] = (void(*)())dump_create_console_reply }, { (int(*)(void *,int))dump_set_console_fd_request, (void(*)())0 }, + { (int(*)(void *,int))dump_create_change_notification_request, + (void(*)())dump_create_change_notification_reply }, }; static const char * const req_names[REQ_NB_REQUESTS] = @@ -420,6 +437,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = "create_pipe", "create_console", "set_console_fd", + "create_change_notification", }; void trace_request( enum request req, void *data, int len, int fd )