Added change notifications.

Added global handle support.
This commit is contained in:
Alexandre Julliard 1998-12-31 15:43:48 +00:00
parent 748ff0f985
commit 63cb0f8b99
8 changed files with 175 additions and 16 deletions

View File

@ -127,6 +127,9 @@ struct dup_handle_request
int inherit; /* inherit flag */ int inherit; /* inherit flag */
int options; /* duplicate options (see below) */ 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 struct dup_handle_reply
{ {
int handle; /* duplicated handle in dst process */ int handle; /* duplicated handle in dst process */
@ -212,7 +215,7 @@ struct create_semaphore_request
unsigned int initial; /* initial count */ unsigned int initial; /* initial count */
unsigned int max; /* maximum count */ unsigned int max; /* maximum count */
int inherit; /* inherit flag */ int inherit; /* inherit flag */
/* char name[] */ char name[0]; /* semaphore name */
}; };
struct create_semaphore_reply struct create_semaphore_reply
{ {
@ -235,10 +238,10 @@ struct release_semaphore_reply
/* Open a named object (event, mutex, semaphore) */ /* Open a named object (event, mutex, semaphore) */
struct open_named_obj_request struct open_named_obj_request
{ {
int type; /* object type (see below) */ int type; /* object type (see below) */
unsigned int access; /* wanted access rights */ unsigned int access; /* wanted access rights */
int inherit; /* inherit flag */ int inherit; /* inherit flag */
/* char name[] */ char name[0]; /* object name */
}; };
enum open_named_obj { OPEN_EVENT, OPEN_MUTEX, OPEN_SEMAPHORE }; 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 */ /* client-side functions */
#ifndef __WINE_SERVER__ #ifndef __WINE_SERVER__
#include "server/request.h"
/* client communication functions */ /* client communication functions */
enum request;
#define CHECK_LEN(len,wanted) \ #define CHECK_LEN(len,wanted) \
if ((len) == (wanted)) ; \ if ((len) == (wanted)) ; \
else CLIENT_ProtocolError( __FUNCTION__ ": len %d != %d\n", (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_NewThread( struct _THDB *thdb, int *thandle, int *phandle );
extern int CLIENT_SetDebug( int level ); extern int CLIENT_SetDebug( int level );
extern int CLIENT_InitThread(void); 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_CloseHandle( int handle );
extern int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process, extern int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process,
int dst_handle, DWORD access, BOOL32 inherit, DWORD options ); int dst_handle, DWORD access, BOOL32 inherit, DWORD options );

View File

@ -189,6 +189,11 @@ extern int create_console( int fd, struct object *obj[2] );
extern int set_console_fd( int handle, int fd ); 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; extern int debug_level;
#endif /* __WINE_SERVER_OBJECT_H */ #endif /* __WINE_SERVER_OBJECT_H */

View File

@ -34,6 +34,7 @@ enum request
REQ_CREATE_PIPE, REQ_CREATE_PIPE,
REQ_CREATE_CONSOLE, REQ_CREATE_CONSOLE,
REQ_SET_CONSOLE_FD, REQ_SET_CONSOLE_FD,
REQ_CREATE_CHANGE_NOTIFICATION,
REQ_NB_REQUESTS REQ_NB_REQUESTS
}; };
@ -71,6 +72,7 @@ DECL_HANDLER(get_file_info);
DECL_HANDLER(create_pipe); DECL_HANDLER(create_pipe);
DECL_HANDLER(create_console); DECL_HANDLER(create_console);
DECL_HANDLER(set_console_fd); DECL_HANDLER(set_console_fd);
DECL_HANDLER(create_change_notification);
static const struct handler { static const struct handler {
void (*handler)(); void (*handler)();
@ -105,6 +107,7 @@ static const struct handler {
{ (void(*)())req_create_pipe, sizeof(struct create_pipe_request) }, { (void(*)())req_create_pipe, sizeof(struct create_pipe_request) },
{ (void(*)())req_create_console, sizeof(struct create_console_request) }, { (void(*)())req_create_console, sizeof(struct create_console_request) },
{ (void(*)())req_set_console_fd, sizeof(struct set_console_fd_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 */ #endif /* WANT_REQUEST_HANDLERS */

View File

@ -6,6 +6,7 @@ VPATH = @srcdir@
MODULE = server MODULE = server
C_SRCS = \ C_SRCS = \
change.c \
console.c \ console.c \
event.c \ event.c \
file.c \ file.c \

70
server/change.c Normal file
View File

@ -0,0 +1,70 @@
/*
* Server-side change notification management
*
* Copyright (C) 1998 Alexandre Julliard
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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 );
}

View File

@ -25,6 +25,12 @@
#define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE << RESERVED_SHIFT) #define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE << RESERVED_SHIFT)
#define RESERVED_ALL (RESERVED_INHERIT | RESERVED_CLOSE_PROTECT) #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 handle_entry
{ {
struct object *ptr; struct object *ptr;
@ -49,6 +55,7 @@ struct process
}; };
static struct process *first_process; static struct process *first_process;
static struct process *initial_process;
#define MIN_HANDLE_ENTRIES 32 #define MIN_HANDLE_ENTRIES 32
@ -94,6 +101,11 @@ struct process *create_process(void)
if (first_process) first_process->prev = process; if (first_process) first_process->prev = process;
first_process = 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 ); gettimeofday( &process->start_time, NULL );
/* alloc a handle for the process itself */ /* alloc a handle for the process itself */
@ -106,6 +118,7 @@ static void process_destroy( struct object *obj )
{ {
struct process *process = (struct process *)obj; struct process *process = (struct process *)obj;
assert( obj->ops == &process_ops ); assert( obj->ops == &process_ops );
assert( process != initial_process );
/* we can't have a thread remaining */ /* we can't have a thread remaining */
assert( !process->thread_list ); assert( !process->thread_list );
@ -288,6 +301,11 @@ static struct handle_entry *get_handle( struct process *process, int handle )
{ {
struct handle_entry *entry; struct handle_entry *entry;
if (HANDLE_IS_GLOBAL(handle))
{
handle = HANDLE_GLOBAL_TO_LOCAL(handle);
process = initial_process;
}
handle--; /* handles start at 1 */ handle--; /* handles start at 1 */
if ((handle < 0) || (handle > process->handle_last)) goto error; if ((handle < 0) || (handle > process->handle_last)) goto error;
entry = process->entries + handle; entry = process->entries + handle;
@ -370,6 +388,11 @@ int close_handle( struct process *process, int handle )
struct handle_entry *entry; struct handle_entry *entry;
struct object *obj; 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 = get_handle( process, handle ))) return 0;
if (entry->access & RESERVED_CLOSE_PROTECT) return 0; /* FIXME: error code */ if (entry->access & RESERVED_CLOSE_PROTECT) return 0; /* FIXME: error code */
obj = entry->ptr; 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 duplicate_handle( struct process *src, int src_handle, struct process *dst,
int dst_handle, unsigned int access, int inherit, int options ) int dst_handle, unsigned int access, int inherit, int options )
{ {
int res;
struct handle_entry *entry = get_handle( src, src_handle ); struct handle_entry *entry = get_handle( src, src_handle );
if (!entry) return -1; 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; 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 */ /* open a new handle to an existing object */

View File

@ -204,14 +204,19 @@ DECL_HANDLER(dup_handle)
if ((src = get_process_from_handle( req->src_process, PROCESS_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, reply.handle = duplicate_handle( src, req->src_handle, dst, req->dst_handle,
req->access, req->inherit, req->options ); req->access, req->inherit, req->options );
release_object( dst ); release_object( dst );
} }
/* close the handle no matter what happened */ /* 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 ); close_handle( src, req->src_handle );
release_object( src ); release_object( src );
} }
@ -531,3 +536,19 @@ DECL_HANDLER(set_console_fd)
set_console_fd( req->handle, fd ); set_console_fd( req->handle, fd );
send_reply( current, -1, 0 ); 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) );
}

View File

@ -172,8 +172,9 @@ static int dump_create_semaphore_request( struct create_semaphore_request *req,
{ {
printf( " initial=%08x,", req->initial ); printf( " initial=%08x,", req->initial );
printf( " max=%08x,", req->max ); printf( " max=%08x,", req->max );
printf( " inherit=%d", req->inherit ); printf( " inherit=%d,", req->inherit );
return (int)sizeof(*req); 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 ) 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( " type=%d,", req->type );
printf( " access=%08x,", req->access ); printf( " access=%08x,", req->access );
printf( " inherit=%d", req->inherit ); printf( " inherit=%d,", req->inherit );
return (int)sizeof(*req); 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 ) 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); 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 struct dumper
{ {
int (*dump_req)( void *data, int len ); int (*dump_req)( void *data, int len );
@ -387,6 +402,8 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
(void(*)())dump_create_console_reply }, (void(*)())dump_create_console_reply },
{ (int(*)(void *,int))dump_set_console_fd_request, { (int(*)(void *,int))dump_set_console_fd_request,
(void(*)())0 }, (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] = 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_pipe",
"create_console", "create_console",
"set_console_fd", "set_console_fd",
"create_change_notification",
}; };
void trace_request( enum request req, void *data, int len, int fd ) void trace_request( enum request req, void *data, int len, int fd )