parent
748ff0f985
commit
63cb0f8b99
|
@ -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 );
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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_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 */
|
||||||
|
|
|
@ -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) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
Loading…
Reference in New Issue