parent
748ff0f985
commit
63cb0f8b99
|
@ -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 );
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ VPATH = @srcdir@
|
|||
MODULE = server
|
||||
|
||||
C_SRCS = \
|
||||
change.c \
|
||||
console.c \
|
||||
event.c \
|
||||
file.c \
|
||||
|
|
|
@ -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 );
|
||||
}
|
|
@ -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 */
|
||||
|
|
|
@ -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) );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue