From d549f6909edff44ed671d80bd066aeb4cd5f3fa3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 22 Dec 2000 02:04:15 +0000 Subject: [PATCH] Use a separate FIFO pair for server requests that don't need to pass a file descriptor. Associate file descriptors with handles on the server side so that we don't need to pass the fd every time the client wants to use it. --- dlls/ntdll/om.c | 2 + files/file.c | 23 ++++-- include/server.h | 22 +++--- include/thread.h | 10 ++- loader/ne/module.c | 8 +- memory/virtual.c | 43 ++++++++--- scheduler/client.c | 185 ++++++++++++++++++++++++++++----------------- scheduler/handle.c | 17 ++++- scheduler/thread.c | 11 ++- server/console.c | 2 +- server/debugger.c | 16 ++-- server/file.c | 8 +- server/handle.c | 60 +++++++++++---- server/handle.h | 3 +- server/mapping.c | 24 ++++-- server/object.h | 1 - server/pipe.c | 2 +- server/request.c | 146 ++++++++++++++++++++++++++++------- server/request.h | 5 +- server/thread.c | 23 +++++- server/thread.h | 4 +- server/trace.c | 31 ++++---- 22 files changed, 443 insertions(+), 203 deletions(-) diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c index 3e31fc8c3aa..e8a70cff6a1 100644 --- a/dlls/ntdll/om.c +++ b/dlls/ntdll/om.c @@ -4,6 +4,7 @@ #include #include +#include #include "debugtools.h" #include "ntddk.h" @@ -221,6 +222,7 @@ NTSTATUS WINAPI NtClose( HANDLE Handle ) struct close_handle_request *req = server_alloc_req( sizeof(*req), 0 ); req->handle = Handle; ret = server_call_noerr( REQ_CLOSE_HANDLE ); + if (!ret && req->fd != -1) close( req->fd ); } SERVER_END_REQ; return ret; diff --git a/files/file.c b/files/file.c index 3d957aac431..3d5e0e475e9 100644 --- a/files/file.c +++ b/files/file.c @@ -185,7 +185,7 @@ HFILE FILE_DupUnixHandle( int fd, DWORD access ) { struct alloc_file_handle_request *req = get_req_buffer(); req->access = access; - server_call_fd( REQ_ALLOC_FILE_HANDLE, fd, NULL ); + server_call_fd( REQ_ALLOC_FILE_HANDLE, fd ); return req->handle; } @@ -197,12 +197,21 @@ HFILE FILE_DupUnixHandle( int fd, DWORD access ) */ int FILE_GetUnixHandle( HANDLE handle, DWORD access ) { - int unix_handle = -1; - struct get_handle_fd_request *req = get_req_buffer(); - req->handle = handle; - req->access = access; - server_call_fd( REQ_GET_HANDLE_FD, -1, &unix_handle ); - return unix_handle; + int ret, fd = -1; + SERVER_START_REQ + { + struct get_handle_fd_request *req = wine_server_alloc_req( sizeof(*req), 0 ); + req->handle = handle; + req->access = access; + if (!(ret = server_call( REQ_GET_HANDLE_FD ))) fd = req->fd; + } + SERVER_END_REQ; + if (!ret) + { + if (fd == -1) return wine_server_recv_fd( handle, 1 ); + fd = dup(fd); + } + return fd; } diff --git a/include/server.h b/include/server.h index f0a614d6a48..d7c7075f393 100644 --- a/include/server.h +++ b/include/server.h @@ -359,15 +359,7 @@ struct close_handle_request { REQUEST_HEADER; /* request header */ IN int handle; /* handle to close */ -}; - - -/* Get information about a handle */ -struct get_handle_info_request -{ - REQUEST_HEADER; /* request header */ - IN int handle; /* handle we are interested in */ - OUT int flags; /* handle flags */ + OUT int fd; /* associated fd to close */ }; @@ -378,6 +370,9 @@ struct set_handle_info_request IN int handle; /* handle we are interested in */ IN int flags; /* new handle flags */ IN int mask; /* mask for flags to set */ + IN int fd; /* file descriptor or -1 */ + OUT int old_flags; /* old flag value */ + OUT int cur_fd; /* current file descriptor */ }; @@ -392,6 +387,7 @@ struct dup_handle_request IN int inherit; /* inherit flag */ IN int options; /* duplicate options (see below) */ OUT int handle; /* duplicated handle in dst process */ + OUT int fd; /* associated fd to close */ }; #define DUP_HANDLE_CLOSE_SOURCE DUPLICATE_CLOSE_SOURCE #define DUP_HANDLE_SAME_ACCESS DUPLICATE_SAME_ACCESS @@ -860,6 +856,7 @@ struct get_mapping_info_request OUT void* base; /* default base addr (for VPROT_IMAGE mapping) */ OUT int shared_file; /* shared mapping file handle */ OUT int shared_size; /* shared mapping size */ + OUT int anonymous; /* anonymous mapping? */ }; @@ -1373,7 +1370,6 @@ enum request REQ_QUEUE_APC, REQ_GET_APC, REQ_CLOSE_HANDLE, - REQ_GET_HANDLE_INFO, REQ_SET_HANDLE_INFO, REQ_DUP_HANDLE, REQ_OPEN_PROCESS, @@ -1489,7 +1485,6 @@ union generic_request struct queue_apc_request queue_apc; struct get_apc_request get_apc; struct close_handle_request close_handle; - struct get_handle_info_request get_handle_info; struct set_handle_info_request set_handle_info; struct dup_handle_request dup_handle; struct open_process_request open_process; @@ -1579,7 +1574,7 @@ union generic_request struct async_result_request async_result; }; -#define SERVER_PROTOCOL_VERSION 30 +#define SERVER_PROTOCOL_VERSION 31 /* ### make_requests end ### */ /* Everything above this line is generated automatically by tools/make_requests */ @@ -1605,9 +1600,10 @@ struct server_buffer_info /* client communication functions */ extern unsigned int wine_server_call( enum request req ); -extern unsigned int server_call_fd( enum request req, int fd_out, int *fd_in ); +extern unsigned int server_call_fd( enum request req, int fd_out ); extern void server_protocol_error( const char *err, ... ) WINE_NORETURN; extern void *wine_server_alloc_req( size_t fixed_size, size_t var_size ); +extern int wine_server_recv_fd( int handle, int cache ); extern const char *get_config_dir(void); /* compatibility macros */ diff --git a/include/thread.h b/include/thread.h index 72a3ea800b5..572b981f8fb 100644 --- a/include/thread.h +++ b/include/thread.h @@ -94,13 +94,15 @@ typedef struct _TEB DWORD cleanup; /* --3 1fc Cleanup service handle */ int socket; /* --3 200 Socket for server communication */ void *buffer; /* --3 204 Buffer shared with server */ - struct server_buffer_info *buffer_info; /* --3 208 Buffer information */ - void *debug_info; /* --3 20c Info for debugstr functions */ - void *pthread_data; /* --3 210 Data for pthread emulation */ + int request_fd; /* --3 208 fd for sending server requests */ + int reply_fd; /* --3 20c fd for receiving server replies */ + struct server_buffer_info *buffer_info; /* --3 210 Buffer information */ + void *debug_info; /* --3 214 Info for debugstr functions */ + void *pthread_data; /* --3 218 Data for pthread emulation */ /* here is plenty space for wine specific fields (don't forget to change pad6!!) */ /* the following are nt specific fields */ - DWORD pad6[633]; /* --n 214 */ + DWORD pad6[631]; /* --n 21c */ UNICODE_STRING StaticUnicodeString; /* -2- bf8 used by advapi32 */ USHORT StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */ DWORD pad7; /* --n e0c */ diff --git a/loader/ne/module.c b/loader/ne/module.c index 3cc10d79938..f4fc76a8905 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -1019,7 +1019,7 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock ) LPSTR cmdline; WORD cmdShow; HANDLE hThread = -1; - int socket; + int socket = -1; /* Load module */ @@ -1066,7 +1066,11 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock ) struct new_thread_request *req = server_alloc_req( sizeof(*req), 0 ); req->suspend = 0; req->inherit = 0; - if (!server_call_fd( REQ_NEW_THREAD, -1, &socket )) hThread = req->handle; + if (!server_call( REQ_NEW_THREAD )) + { + hThread = req->handle; + socket = wine_server_recv_fd( hThread, 0 ); + } } SERVER_END_REQ; if (hThread == -1) return 0; diff --git a/memory/virtual.c b/memory/virtual.c index e1043366650..a94d3a5891e 100644 --- a/memory/virtual.c +++ b/memory/virtual.c @@ -1478,8 +1478,10 @@ LPVOID WINAPI MapViewOfFileEx( UINT ptr = (UINT)-1, size = 0; int flags = MAP_PRIVATE; int unix_handle = -1; - int prot; - struct get_mapping_info_request *req = get_req_buffer(); + int prot, anonymous, res; + void *base; + DWORD size_low, size_high, header_size, shared_size; + HANDLE shared_file; /* Check parameters */ @@ -1490,25 +1492,44 @@ LPVOID WINAPI MapViewOfFileEx( return NULL; } - req->handle = handle; - if (server_call_fd( REQ_GET_MAPPING_INFO, -1, &unix_handle )) goto error; - prot = req->protect; + SERVER_START_REQ + { + struct get_mapping_info_request *req = server_alloc_req( sizeof(*req), 0 ); + req->handle = handle; + res = server_call( REQ_GET_MAPPING_INFO ); + prot = req->protect; + base = req->base; + size_low = req->size_low; + size_high = req->size_high; + header_size = req->header_size; + shared_file = req->shared_file; + shared_size = req->shared_size; + anonymous = req->anonymous; + } + SERVER_END_REQ; + if (res) goto error; + + if (!anonymous) + { + if ((unix_handle = FILE_GetUnixHandle( handle, 0 )) == -1) goto error; + } if (prot & VPROT_IMAGE) - return map_image( handle, unix_handle, req->base, req->size_low, req->header_size, - req->shared_file, req->shared_size ); + return map_image( handle, unix_handle, base, size_low, header_size, + shared_file, shared_size ); - if (req->size_high || offset_high) + + if (size_high || offset_high) ERR("Offsets larger than 4Gb not supported\n"); - if ((offset_low >= req->size_low) || - (count > req->size_low - offset_low)) + if ((offset_low >= size_low) || + (count > size_low - offset_low)) { SetLastError( ERROR_INVALID_PARAMETER ); goto error; } if (count) size = ROUND_SIZE( offset_low, count ); - else size = req->size_low - offset_low; + else size = size_low - offset_low; switch(access) { diff --git a/scheduler/client.c b/scheduler/client.c index a936f73fdd3..607e5661322 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -157,7 +157,7 @@ static void send_request( enum request req, struct request_header *header ) header->req = req; NtCurrentTeb()->buffer_info->cur_req = (char *)header - (char *)NtCurrentTeb()->buffer; /* write a single byte; the value is ignored anyway */ - if (write( NtCurrentTeb()->socket, header, 1 ) == -1) + if (write( NtCurrentTeb()->request_fd, header, 1 ) == -1) { if (errno == EPIPE) SYSDEPS_ExitThread(0); server_perror( "sendmsg" ); @@ -220,7 +220,7 @@ static void wait_reply(void) for (;;) { - if ((ret = read( NtCurrentTeb()->socket, dummy, 1 )) > 0) return; + if ((ret = read( NtCurrentTeb()->reply_fd, dummy, 1 )) > 0) return; if (!ret) break; if (errno == EINTR) continue; if (errno == EPIPE) break; @@ -231,62 +231,6 @@ static void wait_reply(void) } -/*********************************************************************** - * wait_reply_fd - * - * Wait for a reply from the server, when a file descriptor is passed. - */ -static void wait_reply_fd( int *fd ) -{ - struct iovec vec; - int ret; - char dummy[1]; - -#ifdef HAVE_MSGHDR_ACCRIGHTS - struct msghdr msghdr; - - *fd = -1; - msghdr.msg_accrights = (void *)fd; - msghdr.msg_accrightslen = sizeof(*fd); -#else /* HAVE_MSGHDR_ACCRIGHTS */ - struct msghdr msghdr; - struct cmsg_fd cmsg; - - cmsg.len = sizeof(cmsg); - cmsg.level = SOL_SOCKET; - cmsg.type = SCM_RIGHTS; - cmsg.fd = -1; - msghdr.msg_control = &cmsg; - msghdr.msg_controllen = sizeof(cmsg); - msghdr.msg_flags = 0; -#endif /* HAVE_MSGHDR_ACCRIGHTS */ - - msghdr.msg_name = NULL; - msghdr.msg_namelen = 0; - msghdr.msg_iov = &vec; - msghdr.msg_iovlen = 1; - vec.iov_base = (void *)dummy; - vec.iov_len = 1; - - for (;;) - { - if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) > 0) - { -#ifndef HAVE_MSGHDR_ACCRIGHTS - *fd = cmsg.fd; -#endif - return; - } - if (!ret) break; - if (errno == EINTR) continue; - if (errno == EPIPE) break; - server_perror("recvmsg"); - } - /* the server closed the connection; time to die... */ - SYSDEPS_ExitThread(0); -} - - /*********************************************************************** * wine_server_call * @@ -305,19 +249,14 @@ unsigned int wine_server_call( enum request req ) * server_call_fd * * Perform a server call, passing a file descriptor. - * If *fd is != -1, it will be passed to the server. - * If the server passes an fd, it will be stored into *fd. */ -unsigned int server_call_fd( enum request req, int fd_out, int *fd_in ) +unsigned int server_call_fd( enum request req, int fd_out ) { unsigned int res; void *req_ptr = get_req_buffer(); - if (fd_out == -1) send_request( req, req_ptr ); - else send_request_fd( req, req_ptr, fd_out ); - - if (fd_in) wait_reply_fd( fd_in ); - else wait_reply(); + send_request_fd( req, req_ptr, fd_out ); + wait_reply(); if ((res = ((struct request_header *)req_ptr)->error)) SetLastError( RtlNtStatusToDosError(res) ); @@ -325,6 +264,105 @@ unsigned int server_call_fd( enum request req, int fd_out, int *fd_in ) } +/*********************************************************************** + * set_handle_fd + * + * Store the fd for a given handle in the server + */ +static int set_handle_fd( int handle, int fd ) +{ + SERVER_START_REQ + { + struct set_handle_info_request *req = wine_server_alloc_req( sizeof(*req), 0 ); + req->handle = handle; + req->flags = 0; + req->mask = 0; + req->fd = fd; + if (!server_call( REQ_SET_HANDLE_INFO )) + { + if (req->cur_fd != fd) + { + /* someone was here before us */ + close( fd ); + fd = req->cur_fd; + } + else fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */ + } + else + { + close( fd ); + fd = -1; + } + } + SERVER_END_REQ; + return fd; +} + + +/*********************************************************************** + * wine_server_recv_fd + * + * Receive a file descriptor passed from the server. + * The file descriptor must be closed after use. + */ +int wine_server_recv_fd( int handle, int cache ) +{ + struct iovec vec; + int ret, fd, server_handle; + +#ifdef HAVE_MSGHDR_ACCRIGHTS + struct msghdr msghdr; + + fd = -1; + msghdr.msg_accrights = (void *)&fd; + msghdr.msg_accrightslen = sizeof(fd); +#else /* HAVE_MSGHDR_ACCRIGHTS */ + struct msghdr msghdr; + struct cmsg_fd cmsg; + + cmsg.len = sizeof(cmsg); + cmsg.level = SOL_SOCKET; + cmsg.type = SCM_RIGHTS; + cmsg.fd = -1; + msghdr.msg_control = &cmsg; + msghdr.msg_controllen = sizeof(cmsg); + msghdr.msg_flags = 0; +#endif /* HAVE_MSGHDR_ACCRIGHTS */ + + msghdr.msg_name = NULL; + msghdr.msg_namelen = 0; + msghdr.msg_iov = &vec; + msghdr.msg_iovlen = 1; + vec.iov_base = (void *)&server_handle; + vec.iov_len = sizeof(server_handle); + + for (;;) + { + if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) > 0) + { +#ifndef HAVE_MSGHDR_ACCRIGHTS + fd = cmsg.fd; +#endif + if (handle != server_handle) + server_protocol_error( "recv_fd: got handle %d, expected %d\n", + server_handle, handle ); + if (cache) + { + fd = set_handle_fd( handle, fd ); + if (fd != -1) fd = dup(fd); + } + return fd; + } + if (!ret) break; + if (errno == EINTR) continue; + if (errno == EPIPE) break; + server_perror("recvmsg"); + } + /* the server closed the connection; time to die... */ + SYSDEPS_ExitThread(0); +} + + /*********************************************************************** * get_config_dir * @@ -564,8 +602,16 @@ int CLIENT_InitThread(void) /* ignore SIGPIPE so that we get a EPIPE error instead */ signal( SIGPIPE, SIG_IGN ); - wait_reply_fd( &fd ); - if (fd == -1) server_protocol_error( "no fd passed on first request\n" ); + teb->request_fd = wine_server_recv_fd( -1, 0 ); + if (teb->request_fd == -1) server_protocol_error( "no request fd passed on first request\n" ); + fcntl( teb->request_fd, F_SETFD, 1 ); /* set close on exec flag */ + + teb->reply_fd = wine_server_recv_fd( -1, 0 ); + if (teb->reply_fd == -1) server_protocol_error( "no reply fd passed on first request\n" ); + fcntl( teb->reply_fd, F_SETFD, 1 ); /* set close on exec flag */ + + fd = wine_server_recv_fd( -1, 0 ); + if (fd == -1) server_protocol_error( "no fd received for thread buffer\n" ); if ((size = lseek( fd, 0, SEEK_END )) == -1) server_perror( "lseek" ); teb->buffer = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); @@ -573,6 +619,8 @@ int CLIENT_InitThread(void) if (teb->buffer == (void*)-1) server_perror( "mmap" ); teb->buffer_info = (struct server_buffer_info *)((char *)teb->buffer + size) - 1; + wait_reply(); + req = (struct get_thread_buffer_request *)teb->buffer; teb->pid = req->pid; teb->tid = req->tid; @@ -597,6 +645,7 @@ int CLIENT_InitThread(void) return ret; } + /*********************************************************************** * CLIENT_BootDone * diff --git a/scheduler/handle.c b/scheduler/handle.c index 21c60213a69..f60d4b851d8 100644 --- a/scheduler/handle.c +++ b/scheduler/handle.c @@ -6,6 +6,7 @@ #include #include +#include #include "winbase.h" #include "server.h" #include "winerror.h" @@ -40,10 +41,13 @@ BOOL WINAPI GetHandleInformation( HANDLE handle, LPDWORD flags ) BOOL ret; SERVER_START_REQ { - struct get_handle_info_request *req = server_alloc_req( sizeof(*req), 0 ); + struct set_handle_info_request *req = server_alloc_req( sizeof(*req), 0 ); req->handle = handle; - ret = !server_call( REQ_GET_HANDLE_INFO ); - if (ret && flags) *flags = req->flags; + req->flags = 0; + req->mask = 0; + req->fd = -1; + ret = !server_call( REQ_SET_HANDLE_INFO ); + if (ret && flags) *flags = req->old_flags; } SERVER_END_REQ; return ret; @@ -62,6 +66,7 @@ BOOL WINAPI SetHandleInformation( HANDLE handle, DWORD mask, DWORD flags ) req->handle = handle; req->flags = flags; req->mask = mask; + req->fd = -1; ret = !server_call( REQ_SET_HANDLE_INFO ); } SERVER_END_REQ; @@ -89,7 +94,11 @@ BOOL WINAPI DuplicateHandle( HANDLE source_process, HANDLE source, req->options = options; ret = !server_call( REQ_DUP_HANDLE ); - if (ret && dest) *dest = req->handle; + if (ret) + { + if (dest) *dest = req->handle; + if (req->fd != -1) close( req->fd ); + } } SERVER_END_REQ; return ret; diff --git a/scheduler/thread.c b/scheduler/thread.c index e8942925e20..afc1a117a98 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -91,7 +91,9 @@ static BOOL THREAD_InitTEB( TEB *teb ) teb->tls_ptr = teb->tls_array; teb->exit_code = STILL_ACTIVE; teb->socket = -1; - teb->stack_top = (void *)~0UL; + teb->request_fd = -1; + teb->reply_fd = -1; + teb->stack_top = (void *)~0UL; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer; teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT ); @@ -113,6 +115,8 @@ static void CALLBACK THREAD_FreeTEB( TEB *teb ) /* Free the associated memory */ if (teb->socket != -1) close( teb->socket ); + close( NtCurrentTeb()->request_fd ); + close( NtCurrentTeb()->reply_fd ); if (teb->stack_sel) FreeSelector16( teb->stack_sel ); FreeSelector16( teb->teb_sel ); if (teb->buffer) munmap( (void *)teb->buffer, @@ -280,7 +284,7 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack, LPTHREAD_START_ROUTINE start, LPVOID param, DWORD flags, LPDWORD id ) { - int socket, handle = -1; + int socket = -1, handle = -1; TEB *teb; void *tid = 0; @@ -290,10 +294,11 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack, req->suspend = ((flags & CREATE_SUSPENDED) != 0); req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle); - if (!server_call_fd( REQ_NEW_THREAD, -1, &socket )) + if (!server_call( REQ_NEW_THREAD )) { handle = req->handle; tid = req->tid; + socket = wine_server_recv_fd( handle, 0 ); } } SERVER_END_REQ; diff --git a/server/console.c b/server/console.c index 6f72ade2ac6..dcdc28722eb 100644 --- a/server/console.c +++ b/server/console.c @@ -419,7 +419,7 @@ DECL_HANDLER(alloc_console) if ((out = alloc_handle( current->process, current->process->console_out, req->access, req->inherit )) != -1) goto done; /* everything is fine */ - close_handle( current->process, in ); + close_handle( current->process, in, NULL ); in = -1; } free_console( current->process ); diff --git a/server/debugger.c b/server/debugger.c index c88f82ef27e..7f84410b4e7 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -118,7 +118,7 @@ static int fill_create_process_event( struct debug_event *event, void *arg ) /* documented: THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME */ if ((handle = alloc_handle( debugger, thread, THREAD_ALL_ACCESS, FALSE )) == -1) { - close_handle( debugger, event->data.info.create_process.process ); + close_handle( debugger, event->data.info.create_process.process, NULL ); return 0; } event->data.info.create_process.thread = handle; @@ -128,8 +128,8 @@ static int fill_create_process_event( struct debug_event *event, void *arg ) /* the doc says write access too, but this doesn't seem a good idea */ ((handle = alloc_handle( debugger, process->exe.file, GENERIC_READ, FALSE )) == -1)) { - close_handle( debugger, event->data.info.create_process.process ); - close_handle( debugger, event->data.info.create_process.thread ); + close_handle( debugger, event->data.info.create_process.process, NULL ); + close_handle( debugger, event->data.info.create_process.thread, NULL ); return 0; } event->data.info.create_process.file = handle; @@ -316,17 +316,17 @@ static void debug_event_destroy( struct object *obj ) switch(event->data.code) { case CREATE_THREAD_DEBUG_EVENT: - close_handle( debugger, event->data.info.create_thread.handle ); + close_handle( debugger, event->data.info.create_thread.handle, NULL ); break; case CREATE_PROCESS_DEBUG_EVENT: if (event->data.info.create_process.file != -1) - close_handle( debugger, event->data.info.create_process.file ); - close_handle( debugger, event->data.info.create_process.thread ); - close_handle( debugger, event->data.info.create_process.process ); + close_handle( debugger, event->data.info.create_process.file, NULL ); + close_handle( debugger, event->data.info.create_process.thread, NULL ); + close_handle( debugger, event->data.info.create_process.process, NULL ); break; case LOAD_DLL_DEBUG_EVENT: if (event->data.info.load_dll.handle != -1) - close_handle( debugger, event->data.info.load_dll.handle ); + close_handle( debugger, event->data.info.load_dll.handle, NULL ); break; } } diff --git a/server/file.c b/server/file.c index 5c0f59a285e..e0ce8a76285 100644 --- a/server/file.c +++ b/server/file.c @@ -325,11 +325,6 @@ struct file *get_file_obj( struct process *process, int handle, unsigned int acc return (struct file *)get_handle_obj( process, handle, access, &file_ops ); } -int file_get_mmap_fd( struct file *file ) -{ - return dup( file->obj.fd ); -} - static int set_file_pointer( int handle, int *low, int *high, int whence ) { struct file *file; @@ -479,7 +474,8 @@ DECL_HANDLER(get_handle_fd) req->fd = -1; if ((obj = get_handle_obj( current->process, req->handle, req->access, NULL ))) { - set_reply_fd( current, obj->ops->get_fd( obj ) ); + if ((req->fd = get_handle_fd( current->process, req->handle, req->access )) == -1) + send_client_fd( current, obj->ops->get_fd( obj ), req->handle ); release_object( obj ); } } diff --git a/server/handle.c b/server/handle.c index 1d1317f7f89..6a3e1f613c3 100644 --- a/server/handle.c +++ b/server/handle.c @@ -19,8 +19,9 @@ struct handle_entry { - struct object *ptr; - unsigned int access; + struct object *ptr; /* object */ + unsigned int access; /* access rights */ + int fd; /* file descriptor (in client process) */ }; struct handle_table @@ -173,6 +174,7 @@ static int alloc_entry( struct handle_table *table, void *obj, unsigned int acce table->free = i + 1; entry->ptr = grab_object( obj ); entry->access = access; + entry->fd = -1; return index_to_handle(i); } @@ -269,6 +271,7 @@ struct object *copy_handle_table( struct process *process, struct process *paren for (i = 0; i <= table->last; i++, ptr++) { if (!ptr->ptr) continue; + ptr->fd = -1; if (ptr->access & RESERVED_INHERIT) grab_object( ptr->ptr ); else ptr->ptr = NULL; /* don't inherit this entry */ } @@ -280,7 +283,7 @@ struct object *copy_handle_table( struct process *process, struct process *paren /* close a handle and decrement the refcount of the associated object */ /* return 1 if OK, 0 on error */ -int close_handle( struct process *process, int handle ) +int close_handle( struct process *process, int handle, int *fd ) { struct handle_table *table; struct handle_entry *entry; @@ -294,6 +297,9 @@ int close_handle( struct process *process, int handle ) } obj = entry->ptr; entry->ptr = NULL; + 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; if (entry < table->entries + table->free) table->free = entry - table->entries; if (entry == table->entries + table->last) shrink_handle_table( table ); @@ -351,12 +357,28 @@ struct object *get_handle_obj( struct process *process, int handle, return grab_object( obj ); } -/* get/set the handle reserved flags */ -/* return the new flags (or -1 on error) */ -static int set_handle_info( struct process *process, int handle, int mask, int flags ) +/* retrieve the cached fd for a given handle */ +int get_handle_fd( struct process *process, int handle, unsigned int access ) { struct handle_entry *entry; + if (HANDLE_IS_GLOBAL(handle)) return -1; /* no fd cache for global handles */ + if (!(entry = get_handle( process, handle ))) return -1; + if ((entry->access & access) != access) + { + set_error( STATUS_ACCESS_DENIED ); + return -1; + } + return entry->fd; +} + +/* get/set the handle reserved flags */ +/* return the old flags (or -1 on error) */ +static int set_handle_info( struct process *process, int handle, int mask, int flags, int *fd ) +{ + struct handle_entry *entry; + unsigned int old_access; + if (get_magic_handle( handle )) { /* we can retrieve but not set info for magic handles */ @@ -364,10 +386,14 @@ static int set_handle_info( struct process *process, int handle, int mask, int f return 0; } if (!(entry = get_handle( process, handle ))) return -1; + old_access = entry->access; mask = (mask << RESERVED_SHIFT) & RESERVED_ALL; flags = (flags << RESERVED_SHIFT) & mask; entry->access = (entry->access & ~mask) | flags; - return (entry->access & RESERVED_ALL) >> RESERVED_SHIFT; + /* if no current fd set it, otherwise return current fd */ + if (entry->fd == -1) entry->fd = *fd; + *fd = entry->fd; + return (old_access & RESERVED_ALL) >> RESERVED_SHIFT; } /* duplicate a handle */ @@ -420,19 +446,17 @@ int open_object( const WCHAR *name, size_t len, const struct object_ops *ops, /* close a handle */ DECL_HANDLER(close_handle) { - close_handle( current->process, req->handle ); -} - -/* get information about a handle */ -DECL_HANDLER(get_handle_info) -{ - req->flags = set_handle_info( current->process, req->handle, 0, 0 ); + close_handle( current->process, req->handle, &req->fd ); } /* set a handle information */ DECL_HANDLER(set_handle_info) { - set_handle_info( current->process, req->handle, req->mask, req->flags ); + int fd = req->fd; + + if (HANDLE_IS_GLOBAL(req->handle)) fd = -1; /* no fd cache for global handles */ + req->old_flags = set_handle_info( current->process, req->handle, req->mask, req->flags, &fd ); + req->cur_fd = fd; } /* duplicate a handle */ @@ -441,6 +465,7 @@ DECL_HANDLER(dup_handle) struct process *src, *dst; req->handle = -1; + req->fd = -1; if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE ))) { if (req->options & DUP_HANDLE_MAKE_GLOBAL) @@ -456,7 +481,10 @@ DECL_HANDLER(dup_handle) } /* close the handle no matter what happened */ if (req->options & DUP_HANDLE_CLOSE_SOURCE) - close_handle( src, req->src_handle ); + { + if (src == current->process) close_handle( src, req->src_handle, &req->fd ); + else close_handle( src, req->src_handle, NULL ); + } release_object( src ); } } diff --git a/server/handle.h b/server/handle.h index 7bba30b4861..d648dd7de66 100644 --- a/server/handle.h +++ b/server/handle.h @@ -23,9 +23,10 @@ struct object_ops; /* that the thing pointed to starts with a struct object... */ extern int alloc_handle( struct process *process, void *obj, unsigned int access, int inherit ); -extern int close_handle( struct process *process, int handle ); +extern int close_handle( struct process *process, int handle, int *fd ); extern struct object *get_handle_obj( struct process *process, int handle, unsigned int access, const struct object_ops *ops ); +extern int get_handle_fd( struct process *process, int handle, unsigned int access ); extern int duplicate_handle( struct process *src, int src_handle, struct process *dst, unsigned int access, int inherit, int options ); extern int open_object( const WCHAR *name, size_t len, const struct object_ops *ops, diff --git a/server/mapping.c b/server/mapping.c index a68e8fb8285..38d1d899bef 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -30,6 +30,7 @@ struct mapping int shared_size; /* shared mapping total size */ }; +static int mapping_get_fd( struct object *obj ); static void mapping_dump( struct object *obj, int verbose ); static void mapping_destroy( struct object *obj ); @@ -43,7 +44,7 @@ static const struct object_ops mapping_ops = NULL, /* satisfied */ NULL, /* get_poll_events */ NULL, /* poll_event */ - no_get_fd, /* get_fd */ + mapping_get_fd, /* get_fd */ no_flush, /* flush */ no_get_file_info, /* get_file_info */ mapping_destroy /* destroy */ @@ -86,6 +87,13 @@ static void init_page_size(void) #define ROUND_SIZE(addr,size) \ (((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask) +/* get the fd to use for mmaping a file */ +inline static int get_mmap_fd( struct file *file ) +{ + struct object *obj; + if (!(obj = (struct object *)file)) return -1; + return obj->ops->get_fd( obj ); +} /* allocate and fill the temp file for a shared PE image mapping */ static int build_shared_mapping( struct mapping *mapping, int fd, @@ -115,7 +123,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd, if (!(mapping->shared_file = create_temp_file( GENERIC_READ|GENERIC_WRITE ))) goto error; if (!grow_file( mapping->shared_file, 0, total_size )) goto error; - if ((shared_fd = file_get_mmap_fd( mapping->shared_file )) == -1) goto error; + if ((shared_fd = get_mmap_fd( mapping->shared_file )) == -1) goto error; if (!(buffer = malloc( max_size ))) goto error; @@ -159,7 +167,7 @@ static int get_image_params( struct mapping *mapping ) /* load the headers */ - if ((fd = file_get_mmap_fd( mapping->file )) == -1) return 0; + if ((fd = get_mmap_fd( mapping->file )) == -1) return 0; filepos = lseek( fd, 0, SEEK_SET ); if (read( fd, &dos, sizeof(dos) ) != sizeof(dos)) goto error; if (dos.e_magic != IMAGE_DOS_SIGNATURE) goto error; @@ -270,6 +278,13 @@ static void mapping_dump( struct object *obj, int verbose ) fputc( '\n', stderr ); } +static int mapping_get_fd( struct object *obj ) +{ + struct mapping *mapping = (struct mapping *)obj; + assert( obj->ops == &mapping_ops ); + return get_mmap_fd( mapping->file ); +} + static void mapping_destroy( struct object *obj ) { struct mapping *mapping = (struct mapping *)obj; @@ -323,11 +338,10 @@ DECL_HANDLER(get_mapping_info) req->base = mapping->base; req->shared_file = -1; req->shared_size = mapping->shared_size; + req->anonymous = !mapping->file; if (mapping->shared_file) req->shared_file = alloc_handle( current->process, mapping->shared_file, GENERIC_READ|GENERIC_WRITE, 0 ); - if (mapping->file) set_reply_fd( current, file_get_mmap_fd( mapping->file ) ); release_object( mapping ); } } - diff --git a/server/object.h b/server/object.h index 7a7d1a3d013..deec306b32f 100644 --- a/server/object.h +++ b/server/object.h @@ -148,7 +148,6 @@ extern void abandon_mutexes( struct thread *thread ); extern struct file *get_file_obj( struct process *process, int handle, unsigned int access ); -extern int file_get_mmap_fd( struct file *file ); extern int grow_file( struct file *file, int size_high, int size_low ); extern int create_anonymous_file(void); extern struct file *create_temp_file( int access ); diff --git a/server/pipe.c b/server/pipe.c index 5c830c0897b..7838c12caf5 100644 --- a/server/pipe.c +++ b/server/pipe.c @@ -165,7 +165,7 @@ DECL_HANDLER(create_pipe) STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE, req->inherit ); if (hwrite == -1) - close_handle( current->process, hread ); + close_handle( current->process, hread, NULL ); } release_object( obj[0] ); release_object( obj[1] ); diff --git a/server/request.c b/server/request.c index c3928e5ccb0..fff02dd4531 100644 --- a/server/request.c +++ b/server/request.c @@ -71,6 +71,32 @@ static const struct object_ops master_socket_ops = }; +struct request_socket +{ + struct object obj; /* object header */ + struct thread *thread; /* owning thread */ +}; + +static void request_socket_dump( struct object *obj, int verbose ); +static void request_socket_poll_event( struct object *obj, int event ); + +static const struct object_ops request_socket_ops = +{ + sizeof(struct request_socket), /* size */ + request_socket_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + NULL, /* get_poll_events */ + request_socket_poll_event, /* poll_event */ + no_get_fd, /* get_fd */ + no_flush, /* flush */ + no_get_file_info, /* get_file_info */ + no_destroy /* destroy */ +}; + + struct thread *current = NULL; /* thread handling the current request */ unsigned int global_error = 0; /* global error code for when no thread is current */ @@ -149,13 +175,6 @@ static inline void call_req_handler( struct thread *thread ) fatal_protocol_error( current, "bad request %d\n", req ); } -/* set the fd to pass to the thread */ -void set_reply_fd( struct thread *thread, int pass_fd ) -{ - assert( thread->pass_fd == -1 ); - thread->pass_fd = pass_fd; -} - /* send a reply to a thread */ void send_reply( struct thread *thread ) { @@ -213,29 +232,9 @@ int write_request( struct thread *thread ) header->error = thread->error; - if (thread->pass_fd == -1) - { - /* write a single byte; the value is ignored anyway */ - ret = write( thread->obj.fd, header, 1 ); - } - else /* we have an fd to send */ - { -#ifdef HAVE_MSGHDR_ACCRIGHTS - msghdr.msg_accrightslen = sizeof(int); - msghdr.msg_accrights = (void *)&thread->pass_fd; -#else /* HAVE_MSGHDR_ACCRIGHTS */ - msghdr.msg_control = &cmsg; - msghdr.msg_controllen = sizeof(cmsg); - cmsg.fd = thread->pass_fd; -#endif /* HAVE_MSGHDR_ACCRIGHTS */ + assert (thread->pass_fd == -1); - myiovec.iov_base = (void *)header; - myiovec.iov_len = 1; - - ret = sendmsg( thread->obj.fd, &msghdr, 0 ); - close( thread->pass_fd ); - thread->pass_fd = -1; - } + ret = write( thread->reply_fd, header, 1 ); if (ret > 0) { set_select_events( &thread->obj, POLLIN ); @@ -255,6 +254,40 @@ int write_request( struct thread *thread ) return -1; } +/* send an fd to a client */ +int send_client_fd( struct thread *thread, int fd, int handle ) +{ + int ret; + +#ifdef HAVE_MSGHDR_ACCRIGHTS + msghdr.msg_accrightslen = sizeof(fd); + msghdr.msg_accrights = (void *)&fd; +#else /* HAVE_MSGHDR_ACCRIGHTS */ + msghdr.msg_control = &cmsg; + msghdr.msg_controllen = sizeof(cmsg); + cmsg.fd = fd; +#endif /* HAVE_MSGHDR_ACCRIGHTS */ + + myiovec.iov_base = (void *)&handle; + myiovec.iov_len = sizeof(handle); + + ret = sendmsg( thread->obj.fd, &msghdr, 0 ); + close( fd ); + + if (ret > 0) return 0; + if (errno == EPIPE) + { + kill_thread( thread, 0 ); /* normal death */ + } + else + { + perror("sendmsg"); + thread->exit_code = 1; + kill_thread( thread, 1 ); + } + return -1; +} + static void master_socket_dump( struct object *obj, int verbose ) { struct master_socket *sock = (struct master_socket *)obj; @@ -297,6 +330,61 @@ static void master_socket_destroy( struct object *obj ) socket_cleanup(); } +static void request_socket_dump( struct object *obj, int verbose ) +{ + struct request_socket *sock = (struct request_socket *)obj; + assert( obj->ops == &request_socket_ops ); + fprintf( stderr, "Request socket fd=%d thread=%p\n", sock->obj.fd, sock->thread ); +} + +/* handle a request socket event */ +static void request_socket_poll_event( struct object *obj, int event ) +{ + struct request_socket *sock = (struct request_socket *)obj; + assert( obj->ops == &request_socket_ops ); + + if (event & (POLLERR | POLLHUP)) kill_thread( sock->thread, 0 ); + else if (event & POLLIN) + { + struct thread *thread = sock->thread; + int ret; + char dummy[1]; + + ret = read( sock->obj.fd, &dummy, 1 ); + if (ret > 0) + { + call_req_handler( thread ); + return; + } + if (!ret) /* closed pipe */ + { + kill_thread( thread, 0 ); + return; + } + perror("read"); + thread->exit_code = 1; + kill_thread( thread, 1 ); + } +} + +/* create a request socket and send the fd to the client thread */ +struct object *create_request_socket( struct thread *thread ) +{ + struct request_socket *sock; + int fd[2]; + + if (pipe( fd )) return NULL; + if (!(sock = alloc_object( &request_socket_ops, fd[0] ))) + { + close( fd[1] ); + return NULL; + } + sock->thread = thread; + send_client_fd( thread, fd[1], -1 ); + set_select_events( &sock->obj, POLLIN ); + return &sock->obj; +} + /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */ const char *get_config_dir(void) { diff --git a/server/request.h b/server/request.h index ef856f31d6d..c58d5fbccb2 100644 --- a/server/request.h +++ b/server/request.h @@ -33,11 +33,12 @@ extern void fatal_perror( const char *err, ... ) WINE_NORETURN; extern const char *get_config_dir(void); extern void read_request( struct thread *thread ); extern int write_request( struct thread *thread ); -extern void set_reply_fd( struct thread *thread, int pass_fd ); +extern int send_client_fd( struct thread *thread, int fd, int handle ); extern void send_reply( struct thread *thread ); extern void open_master_socket(void); extern void close_master_socket(void); extern void lock_master_socket( int locked ); +extern struct object *create_request_socket( struct thread *thread ); extern void trace_request( enum request req ); extern void trace_reply( struct thread *thread ); @@ -90,7 +91,6 @@ DECL_HANDLER(unload_dll); DECL_HANDLER(queue_apc); DECL_HANDLER(get_apc); DECL_HANDLER(close_handle); -DECL_HANDLER(get_handle_info); DECL_HANDLER(set_handle_info); DECL_HANDLER(dup_handle); DECL_HANDLER(open_process); @@ -205,7 +205,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_queue_apc, (req_handler)req_get_apc, (req_handler)req_close_handle, - (req_handler)req_get_handle_info, (req_handler)req_set_handle_info, (req_handler)req_dup_handle, (req_handler)req_open_process, diff --git a/server/thread.c b/server/thread.c index 7cfacdc2dad..12e937716e1 100644 --- a/server/thread.c +++ b/server/thread.c @@ -89,26 +89,33 @@ static struct thread *booting_thread; static int alloc_client_buffer( struct thread *thread ) { struct get_thread_buffer_request *req; - int fd; + int fd, fd_pipe[2]; - if ((fd = create_anonymous_file()) == -1) return -1; + if (pipe( fd_pipe ) == -1) return -1; + if ((fd = create_anonymous_file()) == -1) goto error; if (ftruncate( fd, MAX_REQUEST_LENGTH ) == -1) goto error; if ((thread->buffer = mmap( 0, MAX_REQUEST_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 )) == (void*)-1) goto error; thread->buffer_info = (struct server_buffer_info *)((char *)thread->buffer + MAX_REQUEST_LENGTH) - 1; + if (!(thread->request_fd = create_request_socket( thread ))) goto error; + thread->reply_fd = fd_pipe[1]; /* build the first request into the buffer and send it */ req = thread->buffer; req->pid = get_process_id( thread->process ); req->tid = get_thread_id( thread ); req->boot = (thread == booting_thread); req->version = SERVER_PROTOCOL_VERSION; - set_reply_fd( thread, fd ); + + send_client_fd( thread, fd_pipe[0], -1 ); + send_client_fd( thread, fd, -1 ); send_reply( thread ); return 1; error: file_set_error(); if (fd != -1) close( fd ); + close( fd_pipe[0] ); + close( fd_pipe[1] ); return 0; } @@ -135,6 +142,8 @@ struct thread *create_thread( int fd, struct process *process ) thread->apc_tail = NULL; thread->error = 0; thread->pass_fd = -1; + thread->request_fd = NULL; + thread->reply_fd = -1; thread->state = RUNNING; thread->attached = 0; thread->exit_code = 0; @@ -197,7 +206,9 @@ static void destroy_thread( struct object *obj ) if (thread->info) release_object( thread->info ); if (thread->queue) release_object( thread->queue ); if (thread->buffer != (void *)-1) munmap( thread->buffer, MAX_REQUEST_LENGTH ); + if (thread->reply_fd != -1) close( thread->reply_fd ); if (thread->pass_fd != -1) close( thread->pass_fd ); + if (thread->request_fd) release_object( thread->request_fd ); } /* dump a thread on stdout for debugging purposes */ @@ -618,7 +629,11 @@ void kill_thread( struct thread *thread, int violent_death ) wake_up( &thread->obj, 0 ); detach_thread( thread, violent_death ? SIGTERM : 0 ); remove_select_user( &thread->obj ); + release_object( thread->request_fd ); + close( thread->reply_fd ); munmap( thread->buffer, MAX_REQUEST_LENGTH ); + thread->request_fd = NULL; + thread->reply_fd = -1; thread->buffer = (void *)-1; release_object( thread ); } @@ -675,7 +690,7 @@ DECL_HANDLER(new_thread) if ((req->handle = alloc_handle( current->process, thread, THREAD_ALL_ACCESS, req->inherit )) != -1) { - set_reply_fd( current, sock[1] ); + send_client_fd( current, sock[1], req->handle ); /* thread object will be released when the thread gets killed */ add_process_thread( current->process, thread ); return; diff --git a/server/thread.h b/server/thread.h index c0db4819b46..8e365692ca8 100644 --- a/server/thread.h +++ b/server/thread.h @@ -48,7 +48,9 @@ struct thread struct thread_apc *apc_head; /* queue of async procedure calls */ struct thread_apc *apc_tail; /* queue of async procedure calls */ unsigned int error; /* current error code */ - int pass_fd; /* fd to pass to the client */ + struct object *request_fd; /* fd for receiving client requests */ + int pass_fd; /* fd to pass to the client */ + int reply_fd; /* fd to use to wake a client waiting on a reply */ enum run_state state; /* running state */ int attached; /* is thread attached with ptrace? */ int exit_code; /* thread exit code */ diff --git a/server/trace.c b/server/trace.c index bad07e832f8..534f4d43e24 100644 --- a/server/trace.c +++ b/server/trace.c @@ -471,21 +471,23 @@ static void dump_close_handle_request( const struct close_handle_request *req ) fprintf( stderr, " handle=%d", req->handle ); } -static void dump_get_handle_info_request( const struct get_handle_info_request *req ) +static void dump_close_handle_reply( const struct close_handle_request *req ) { - fprintf( stderr, " handle=%d", req->handle ); -} - -static void dump_get_handle_info_reply( const struct get_handle_info_request *req ) -{ - fprintf( stderr, " flags=%d", req->flags ); + fprintf( stderr, " fd=%d", req->fd ); } static void dump_set_handle_info_request( const struct set_handle_info_request *req ) { fprintf( stderr, " handle=%d,", req->handle ); fprintf( stderr, " flags=%d,", req->flags ); - fprintf( stderr, " mask=%d", req->mask ); + fprintf( stderr, " mask=%d,", req->mask ); + fprintf( stderr, " fd=%d", req->fd ); +} + +static void dump_set_handle_info_reply( const struct set_handle_info_request *req ) +{ + fprintf( stderr, " old_flags=%d,", req->old_flags ); + fprintf( stderr, " cur_fd=%d", req->cur_fd ); } static void dump_dup_handle_request( const struct dup_handle_request *req ) @@ -500,7 +502,8 @@ static void dump_dup_handle_request( const struct dup_handle_request *req ) static void dump_dup_handle_reply( const struct dup_handle_request *req ) { - fprintf( stderr, " handle=%d", req->handle ); + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " fd=%d", req->fd ); } static void dump_open_process_request( const struct open_process_request *req ) @@ -957,7 +960,8 @@ static void dump_get_mapping_info_reply( const struct get_mapping_info_request * fprintf( stderr, " header_size=%d,", req->header_size ); fprintf( stderr, " base=%p,", req->base ); fprintf( stderr, " shared_file=%d,", req->shared_file ); - fprintf( stderr, " shared_size=%d", req->shared_size ); + fprintf( stderr, " shared_size=%d,", req->shared_size ); + fprintf( stderr, " anonymous=%d", req->anonymous ); } static void dump_create_device_request( const struct create_device_request *req ) @@ -1471,7 +1475,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_queue_apc_request, (dump_func)dump_get_apc_request, (dump_func)dump_close_handle_request, - (dump_func)dump_get_handle_info_request, (dump_func)dump_set_handle_info_request, (dump_func)dump_dup_handle_request, (dump_func)dump_open_process_request, @@ -1582,9 +1585,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)0, (dump_func)0, (dump_func)dump_get_apc_reply, - (dump_func)0, - (dump_func)dump_get_handle_info_reply, - (dump_func)0, + (dump_func)dump_close_handle_reply, + (dump_func)dump_set_handle_info_reply, (dump_func)dump_dup_handle_reply, (dump_func)dump_open_process_reply, (dump_func)dump_select_reply, @@ -1695,7 +1697,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "queue_apc", "get_apc", "close_handle", - "get_handle_info", "set_handle_info", "dup_handle", "open_process",