Index: dlls/ntdll/ntdll_misc.h =================================================================== RCS file: /home/wine/wine/dlls/ntdll/ntdll_misc.h,v retrieving revision 1.49 diff -u -r1.49 ntdll_misc.h --- dlls/ntdll/ntdll_misc.h 21 Sep 2004 00:23:50 -0000 1.49 +++ dlls/ntdll/ntdll_misc.h 23 Sep 2004 09:22:44 -0000 @@ -95,6 +95,8 @@ extern BOOL is_current_process( HANDLE handle ); +extern void remote_op_handler(void); + /* code pages */ extern int ntdll_umbstowcs(DWORD flags, const char* src, int srclen, WCHAR* dst, int dstlen); extern int ntdll_wcstoumbs(DWORD flags, const WCHAR* src, int srclen, char* dst, int dstlen, Index: dlls/ntdll/sync.c =================================================================== RCS file: /home/wine/wine/dlls/ntdll/sync.c,v retrieving revision 1.35 diff -u -r1.35 sync.c --- dlls/ntdll/sync.c 1 Apr 2004 21:01:53 -0000 1.35 +++ dlls/ntdll/sync.c 23 Sep 2004 09:22:46 -0000 @@ -480,6 +480,15 @@ if (ret == sizeof(reply)) { if (!reply.cookie) break; /* thread got killed */ +#define REMOTE_OPERATION_APPROACH_WAIT +#ifdef REMOTE_OPERATION_APPROACH_WAIT + if (reply.cookie == (void*) 1 ) + { + TRACE("CATCH\n"); + remote_op_handler(); + continue; + } +#endif if (reply.cookie == cookie) return reply.signaled; /* we stole another reply, wait for the real one */ signaled = wait_reply( cookie ); @@ -627,6 +636,10 @@ if (alertable) flags |= SELECT_ALERTABLE; return NTDLL_wait_for_multiple_objects( 0, NULL, flags, timeout ); } + +#ifdef REMOTE_OPERATION_APPROACH_WAIT + return NTDLL_wait_for_multiple_objects( 0, NULL, 0, timeout ); +#endif if (!timeout) /* sleep forever */ { Index: dlls/ntdll/virtual.c =================================================================== RCS file: /home/wine/wine/dlls/ntdll/virtual.c,v retrieving revision 1.40 diff -u -r1.40 virtual.c --- dlls/ntdll/virtual.c 22 Sep 2004 04:03:10 -0000 1.40 +++ dlls/ntdll/virtual.c 23 Sep 2004 09:22:53 -0000 @@ -140,6 +140,220 @@ static void *user_space_limit = USER_SPACE_LIMIT; +#define REMOTE_OPERATION_ALLOWED 0 +#define SUSPEND_REMOTE_OPERATION 1 +#define PENDING_REMOTE_OPERATION 2 + +/*********************************************************************** + * execute_remote_operation + * + */ +static void execute_remote_operation() +{ + TEB *teb = NtCurrentTeb(); + NTSTATUS status; + void *result_buf = NULL; + DWORD size; + + switch( teb->remote_op_code ) + { + case REMOTE_OP_NEW_THREAD: + status = STATUS_NOT_IMPLEMENTED; + break; + case REMOTE_OP_VM_ALLOC: + { + struct remote_op_params_vm_alloc *params = teb->remote_op_params; + struct remote_op_result_vm_alloc *result; + + size = sizeof(struct remote_op_result_vm_alloc); + result_buf = RtlAllocateHeap( GetProcessHeap(), 0, size ); + if( NULL == result_buf ) + { + ERR("cannot allocate memory\n"); + break; + } + result = result_buf; + status = NtAllocateVirtualMemory( GetCurrentProcess(), &result->base, params->addr, + ¶ms->size, params->type, params->protect ); + TRACE("status=%08X\n",status); + result->size = params->size; + break; + } + case REMOTE_OP_VM_FREE: + case REMOTE_OP_VM_PROTECT: + case REMOTE_OP_VM_QUERY: + case REMOTE_OP_VM_MAP: + case REMOTE_OP_VM_UNMAP: + case REMOTE_OP_VM_FLUSH: + status = STATUS_NOT_IMPLEMENTED; + break; + default: + ERR("invalid operation code %d\n", teb->remote_op_code); + status = STATUS_INVALID_PARAMETER; /* ??? */ + break; + } + + TRACE("sending remote_operation_complete\n"); + SERVER_START_REQ( remote_operation_complete ) + { + req->originator = teb->remote_op_originator; + req->status = status; + if (result_buf) wine_server_add_data( req, result_buf, size ); + wine_server_call( req ); + } + SERVER_END_REQ; + + TRACE("done\n"); + if( result_buf ) RtlFreeHeap( GetProcessHeap(), 0, result_buf ); + RtlFreeHeap( GetProcessHeap(), 0, teb->remote_op_params ); + teb->remote_op_params = NULL; +} + + +/*********************************************************************** + * Workaround for remote operations. + * Thread may be interrupted inside critical section so deadlock + * will occur because of nested RtlEnterCriticalSection. + */ + +/*********************************************************************** + * enter_critical_section + * + * Indicate that remote operation for this thread must be suspended + * and enter csVirtual critical section. + */ +static void enter_critical_section(void) +{ + NtCurrentTeb()->remote_op_flag = SUSPEND_REMOTE_OPERATION; + RtlEnterCriticalSection(&csVirtual); +} + + +/*********************************************************************** + * leave_critical_section + * + * Leave csVirtual critical section and check remote operation flag + * in TEB. Also set this flag to allow immediate execution of + * remote operation. + * If there is a pending operation at this point, execute it. + */ +static void leave_critical_section(void) +{ + RtlLeaveCriticalSection(&csVirtual); + if (interlocked_xchg( &NtCurrentTeb()->remote_op_flag, + REMOTE_OPERATION_ALLOWED ) == PENDING_REMOTE_OPERATION) + execute_remote_operation(); +} + + +/*********************************************************************** + * remote_op_handler + * + */ +void remote_op_handler(void) +{ + TEB *teb = NtCurrentTeb(); + struct remote_op_request request; + + /* sanity check*/ + if( PENDING_REMOTE_OPERATION == teb->remote_op_flag ) + ERR("nested remote operations"); + if( teb->remote_op_params ) + ERR("params not null"); + + /* get request & params */ +#define REMOTE_OPERATION_APPROACH_WAIT +#ifdef REMOTE_OPERATION_APPROACH_WAIT + for (;;) + { + int ret; + TRACE("reading request\n"); + ret = read( teb->wait_fd[0], &request, sizeof(struct remote_op_request) ); + if (ret == sizeof(struct remote_op_request)) + break; + if (ret >= 0) server_protocol_error( "partial remote operation opcode read %d\n", ret ); + if (errno == EINTR) continue; + server_protocol_perror("remote operation opcode read"); + } + TRACE("params size=%d\n", request.params_size); + teb->remote_op_params = RtlAllocateHeap( GetProcessHeap(), 0, request.params_size ); + if( NULL == teb->remote_op_params ) + return; + for (;;) + { + int ret; + ret = read( teb->wait_fd[0], teb->remote_op_params, request.params_size ); + if (ret == request.params_size) + break; + if (ret >= 0) server_protocol_error( "partial remote operation request read %d\n", ret ); + if (errno == EINTR) continue; + server_protocol_perror("remote operation request read"); + } + teb->remote_op_originator = request.originator; + teb->remote_op_code = request.op_code; +#endif + + /* Check remote_operation_flag in TEB and either execute operation + * immediately or suspend. */ + if (SUSPEND_REMOTE_OPERATION == teb->remote_op_flag) + teb->remote_op_flag = PENDING_REMOTE_OPERATION; + else + execute_remote_operation(); +} + + +/*********************************************************************** + * remote_op + * + * helper function + */ +NTSTATUS remote_op( HANDLE process, int opcode, + void* params, int params_size, void* result, int* result_size ) +{ + HANDLE event; + NTSTATUS status, remote_status; + + /* send params */ + SERVER_START_REQ( remote_operation ) + { + req->handle = process; + req->code = opcode; + if (params) wine_server_add_data( req, params, params_size ); + if (!(status = wine_server_call( req ))) + event = reply->event; + } + SERVER_END_REQ; + if (status) + return status; + + /* wait for completion */ + TRACE("waiting for completion on %p\n", event); + status = NtWaitForMultipleObjects( 1, &event, FALSE, FALSE, NULL ); + NtClose( event ); + /* FIXME: check abandoned status */ + if (HIWORD(status)) + return status; + + /* get result */ + TRACE("getting result\n"); + remote_status = 0; /* make compiler happy */ + SERVER_START_REQ( remote_operation_result ) + { + wine_server_set_reply( req, result, *result_size ); + if (!(status = wine_server_call( req ))) + { + remote_status = reply->status; + if (result) + *result_size = wine_server_reply_size( reply ); + TRACE("result_size=%d\n", *result_size ); + } + } + SERVER_END_REQ; + + return status? status : remote_status; +} + + /*********************************************************************** * VIRTUAL_GetProtStr */ @@ -198,7 +412,7 @@ struct list *ptr; DPRINTF( "\nDump of all virtual memory views:\n\n" ); - RtlEnterCriticalSection(&csVirtual); + enter_critical_section(); LIST_FOR_EACH( ptr, &views_list ) { VIRTUAL_DumpView( LIST_ENTRY( ptr, struct file_view, entry ) ); @@ -832,7 +1046,7 @@ /* zero-map the whole range */ - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); if (base >= (char *)0x110000) /* make sure the DOS area remains free */ status = map_view( &view, base, total_size, @@ -1011,14 +1225,14 @@ if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC; VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot ); } - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); *addr_ptr = ptr; return STATUS_SUCCESS; error: if (view) delete_view( view ); - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); return status; } @@ -1068,14 +1282,14 @@ FILE_VIEW *view; BOOL ret = FALSE; - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); if ((view = VIRTUAL_FindView( addr ))) { view->handlerProc = proc; view->handlerArg = arg; ret = TRUE; } - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); return ret; } @@ -1087,14 +1301,14 @@ FILE_VIEW *view; DWORD ret = EXCEPTION_ACCESS_VIOLATION; - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); if ((view = VIRTUAL_FindView( addr ))) { if (view->handlerProc) { HANDLERPROC proc = view->handlerProc; void *arg = view->handlerArg; - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); if (proc( arg, addr )) ret = 0; /* handled */ return ret; } @@ -1113,7 +1327,7 @@ ret = STATUS_STACK_OVERFLOW; } } - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); return ret; } @@ -1127,9 +1341,9 @@ FILE_VIEW *view; BOOL ret = FALSE; - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); if ((view = VIRTUAL_FindView( addr ))) ret = (view->mapping != 0); - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); return ret; } @@ -1142,10 +1356,10 @@ void VIRTUAL_UseLargeAddressSpace(void) { if (user_space_limit >= ADDRESS_SPACE_LIMIT) return; - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); remove_reserved_area( user_space_limit, (char *)ADDRESS_SPACE_LIMIT - (char *)user_space_limit ); user_space_limit = ADDRESS_SPACE_LIMIT; - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); } @@ -1168,8 +1382,23 @@ if (!is_current_process( process )) { - ERR("Unsupported on other process\n"); - return STATUS_ACCESS_DENIED; + struct remote_op_params_vm_alloc alloc_params; + struct remote_op_result_vm_alloc alloc_result; + int result_size = sizeof(struct remote_op_result_vm_alloc); + + alloc_params.addr = addr; + alloc_params.size = size; + alloc_params.type = type; + alloc_params.protect = protect; + status = remote_op( process, REMOTE_OP_VM_ALLOC, + &alloc_params, sizeof(alloc_params), + &alloc_result, &result_size ); + if (!status) + { + *ret = alloc_result.base; + *size_ptr = alloc_result.size; + } + return status; } /* Round parameters to a page boundary */ @@ -1217,7 +1446,7 @@ /* Reserve the memory */ - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); if (type & MEM_SYSTEM) { @@ -1245,7 +1474,7 @@ else if (!VIRTUAL_SetProt( view, base, size, vprot )) status = STATUS_ACCESS_DENIED; } - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); if (status == STATUS_SUCCESS) { @@ -1281,7 +1510,7 @@ size = ROUND_SIZE( addr, size ); base = ROUND_ADDR( addr, page_mask ); - RtlEnterCriticalSection(&csVirtual); + enter_critical_section(); if (!(view = VIRTUAL_FindView( base )) || (base + size > (char *)view->base + view->size) || @@ -1324,7 +1553,7 @@ status = STATUS_INVALID_PARAMETER; } - RtlLeaveCriticalSection(&csVirtual); + leave_critical_section(); return status; } @@ -1357,7 +1586,7 @@ size = ROUND_SIZE( addr, size ); base = ROUND_ADDR( addr, page_mask ); - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); if (!(view = VIRTUAL_FindView( base )) || (base + size > (char *)view->base + view->size)) { @@ -1384,7 +1613,7 @@ if (!VIRTUAL_SetProt( view, base, size, vprot )) status = STATUS_ACCESS_DENIED; } } - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); if (status == STATUS_SUCCESS) { @@ -1423,7 +1652,7 @@ /* Find the view containing the address */ - RtlEnterCriticalSection(&csVirtual); + enter_critical_section(); ptr = list_head( &views_list ); for (;;) { @@ -1435,7 +1664,7 @@ { if (user_space_limit && base >= (char *)user_space_limit) { - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); return STATUS_WORKING_SET_LIMIT_RANGE; } size = (char *)user_space_limit - alloc_base; @@ -1481,7 +1710,7 @@ else if (view->flags & VFLAG_VALLOC) info->Type = MEM_PRIVATE; else info->Type = MEM_MAPPED; } - RtlLeaveCriticalSection(&csVirtual); + leave_critical_section(); info->BaseAddress = (LPVOID)base; info->AllocationBase = (LPVOID)alloc_base; @@ -1714,12 +1943,12 @@ /* Reserve a properly aligned area */ - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); res = map_view( &view, *addr_ptr, size, prot ); if (res) { - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); goto done; } @@ -1746,7 +1975,7 @@ delete_view( view ); } - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); done: wine_server_release_fd( handle, unix_handle ); @@ -1769,13 +1998,13 @@ ERR("Unsupported on other process\n"); return STATUS_ACCESS_DENIED; } - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); if ((view = VIRTUAL_FindView( base )) && (base == view->base)) { delete_view( view ); status = STATUS_SUCCESS; } - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); return status; } @@ -1796,7 +2025,7 @@ ERR("Unsupported on other process\n"); return STATUS_ACCESS_DENIED; } - RtlEnterCriticalSection( &csVirtual ); + enter_critical_section(); if (!(view = VIRTUAL_FindView( addr ))) status = STATUS_INVALID_PARAMETER; else { @@ -1804,7 +2033,7 @@ *addr_ptr = addr; if (msync( addr, *size_ptr, MS_SYNC )) status = STATUS_NOT_MAPPED_DATA; } - RtlLeaveCriticalSection( &csVirtual ); + leave_critical_section(); return status; } Index: include/thread.h =================================================================== RCS file: /home/wine/wine/include/thread.h,v retrieving revision 1.96 diff -u -r1.96 thread.h --- include/thread.h 10 May 2004 19:58:48 -0000 1.96 +++ include/thread.h 23 Sep 2004 09:23:00 -0000 @@ -117,10 +117,14 @@ DWORD dpmi_vif; /* --3 22c Protected mode virtual interrupt flag */ DWORD vm86_pending; /* --3 230 Data for vm86 mode */ void *vm86_ptr; /* --3 234 Data for vm86 mode */ + void *remote_op_params; /* --3 238 */ + DWORD remote_op_originator; /* --3 23C thread id */ + int remote_op_code; /* --3 240 */ + LONG remote_op_flag; /* --3 244 */ /* here is plenty space for wine specific fields (don't forget to change pad6!!) */ /* the following are nt specific fields */ - DWORD pad6[624]; /* --n 238 */ + DWORD pad6[620]; /* --n 248 */ UNICODE_STRING StaticUnicodeString; /* -2- bf8 used by advapi32 */ WCHAR StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */ PVOID DeallocationStack; /* -2- e0c Base of the stack */ Index: server/process.c =================================================================== RCS file: /home/wine/wine/server/process.c,v retrieving revision 1.117 diff -u -r1.117 process.c --- server/process.c 14 Jun 2004 17:02:00 -0000 1.117 +++ server/process.c 23 Sep 2004 09:23:12 -0000 @@ -22,6 +22,7 @@ #include "wine/port.h" #include +#include #include #include #include @@ -1188,5 +1189,183 @@ reply->event = alloc_handle( current->process, process->idle_event, EVENT_ALL_ACCESS, 0 ); release_object( process ); + } +} + +/* Accept parameters for remote operation and start it */ +DECL_HANDLER(remote_operation) +{ + int access, ret; + struct process *process; + struct event *event; + struct thread *thread; + struct remote_op_request request; + + /* define required access rights */ + switch( req->code ) + { + case REMOTE_OP_NEW_THREAD: + access = PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION + | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE; + break; + case REMOTE_OP_VM_ALLOC: access = PROCESS_VM_OPERATION; break; + case REMOTE_OP_VM_FREE: access = PROCESS_VM_OPERATION; break; + case REMOTE_OP_VM_PROTECT: access = PROCESS_VM_OPERATION; break; + case REMOTE_OP_VM_QUERY: access = PROCESS_QUERY_INFORMATION; break; + case REMOTE_OP_VM_MAP: access = PROCESS_VM_OPERATION; break; + case REMOTE_OP_VM_UNMAP: access = PROCESS_VM_OPERATION; break; + case REMOTE_OP_VM_FLUSH: access = PROCESS_VM_OPERATION; break; /* FIXME: is access right? */ + default: + set_error( STATUS_INVALID_PARAMETER ); + return; + } + + /* get process object */ + if (!(process = get_process_from_handle( req->handle, access ))) return; + + /* dispose result data buffer if allocated */ + if (current->result_data) + { + free( current->result_data ); + current->result_data = NULL; + } + + /* create event object */ + reply->event = NULL; + if (current->result_event) + { + release_object( current->result_event ); + current->result_event = NULL; + } + if (!(event = create_event( NULL, 0, 1, 0 ))) + goto error; + + if (!(reply->event = alloc_handle( current->process, event, EVENT_ALL_ACCESS, FALSE ))) + goto error; + +#define REMOTE_OPERATION_APPROACH_WAIT +#ifdef REMOTE_OPERATION_APPROACH_WAIT + + /* find waithing thread */ + thread = process->thread_list; + if (!thread) + { + fprintf( stderr, "no threads\n" ); + /* FIXME: is status correct? */ + set_error( STATUS_ACCESS_DENIED ); + goto error; + } + while (!thread->wait) + { + fprintf( stderr, "thread %08X not waiting\n", thread->id ); + thread = thread->proc_next; + if (!thread) + { + fprintf( stderr, "no waiting threads\n" ); + set_error( STATUS_ACCESS_DENIED ); + goto error; + } + } + fprintf( stderr, "found waiting thread %08X\n", thread->id ); + + /* wakeup thread with magic cookie */ + if (send_thread_wakeup( thread, (void*) 1, 0 ) == -1) + goto error; + + /* send request */ + request.op_code = req->code; + request.originator = current->id; + request.params_size = get_req_data_size(); + fprintf(stderr,"opcode=%d, originator=%d, params size=%d\n",req->code,thread->id,request.params_size); + ret = write( get_unix_fd( thread->wait_fd ), &request, sizeof(request) ); + if(ret != sizeof(request)) + { + if (ret >= 0) + fatal_protocol_error( thread, "partial request write %d\n", ret ); + else if (errno == EPIPE) + kill_thread( thread, 0 ); /* normal death */ + else + fatal_protocol_perror( thread, "write" ); + } + /* send params */ + ret = write( get_unix_fd( thread->wait_fd ), get_req_data(), request.params_size ); + if(ret != request.params_size) + { + if (ret >= 0) + fatal_protocol_error( thread, "partial request write %d\n", ret ); + else if (errno == EPIPE) + kill_thread( thread, 0 ); /* normal death */ + else + fatal_protocol_perror( thread, "write" ); + } + +#else + /* FIXME: pass somehow operation code, params and originator thread id + for some thread in the process and force execution of operation */ + set_error( STATUS_NOT_IMPLEMENTED ); + close_handle( current->process, reply->event, NULL ); +#endif + + /* save event object in thread structure for future set operation; + we do not release it here */ + current->result_event = event; + fprintf( stderr, "thread %p, id=%d, event=%p\n", current, current->id, event ); + release_object( process ); + return; + +error: + if (reply->event) close_handle( current->process, reply->event, NULL ); + if (event) release_object( event ); + release_object( process ); +} + +/* save result of remote operation and wakeup originator */ +DECL_HANDLER(remote_operation_complete) +{ + struct thread *thread = get_thread_from_id( req->originator ); + + fprintf(stderr,"remote_operation_complete: originator=%d, thread=%p, id=%d\n",req->originator, thread, thread->id); + if (!thread) return; + + /* save status */ + thread->remote_status = req->status; + fprintf(stderr,"remote_operation_complete: status=%08X\n",req->status); + + /* allocate buffer for result data, if required */ + if (thread->result_data) + { + free( thread->result_data ); + thread->result_data = NULL; + } + if ((thread->result_size = get_req_data_size())) + { + if ((thread->result_data = mem_alloc( thread->result_size ))) + memcpy( thread->result_data, get_req_data(), thread->result_size ); + else + thread->remote_status = get_error(); + } + + /* set event */ + fprintf(stderr,"setting event %p\n", thread->result_event); + if (thread->result_event) + { + set_event( thread->result_event ); + release_object( thread->result_event ); + thread->result_event = NULL; + } + release_object( thread ); +} + +/* return status and result data from remote opertaion */ +DECL_HANDLER(remote_operation_result) +{ + reply->status = current->remote_status; + fprintf(stderr,"remote_operation_result: status=%08X\n",reply->status); + + if (current->result_data) + { + void *result = current->result_data; + current->result_data = NULL; + set_reply_data_ptr( result, current->result_size ); } } Index: server/protocol.def =================================================================== RCS file: /home/wine/wine/server/protocol.def,v retrieving revision 1.110 diff -u -r1.110 protocol.def --- server/protocol.def 18 Aug 2004 00:04:58 -0000 1.110 +++ server/protocol.def 23 Sep 2004 09:23:18 -0000 @@ -2166,3 +2166,134 @@ #define SET_GLOBAL_SHELL_WINDOWS 0x01 /* set both main shell and listview windows */ #define SET_GLOBAL_PROGMAN_WINDOW 0x02 #define SET_GLOBAL_TASKMAN_WINDOW 0x04 + +/* Accept parameters for remote operation and start it */ +@REQ(remote_operation) + obj_handle_t handle; /* process handle */ + int code; /* operation code (see below) */ + VARARG(data,bytes); /* operation parameters (see below) */ +@REPLY + obj_handle_t event; /* originator waits on it */ +@END +enum remote_op_code +{ + REMOTE_OP_NEW_THREAD, + REMOTE_OP_VM_ALLOC, + REMOTE_OP_VM_FREE, + REMOTE_OP_VM_PROTECT, + REMOTE_OP_VM_QUERY, + REMOTE_OP_VM_MAP, + REMOTE_OP_VM_UNMAP, + REMOTE_OP_VM_FLUSH +}; + +/* Notify that remote operation has been complete */ +@REQ(remote_operation_complete) + thread_id_t originator; /* originator thread id */ + unsigned int status; /* operation status */ + VARARG(data,bytes); /* operation result data (see below) */ +@END + +/* Get result of remote opertaion */ +@REQ(remote_operation_result) +@REPLY + unsigned int status; /* operation status */ + VARARG(data,bytes); /* operation result data (see below) */ +@END + +struct remote_op_params_new_thread +{ + int suspend; + void *stack_addr; + unsigned int stack_reserve; + unsigned int stack_commit; + void *start; + void *param; +}; +struct remote_op_result_new_thread +{ + obj_handle_t handle; + thread_id_t tid; +}; + +struct remote_op_params_vm_alloc +{ + void *addr; + unsigned long size; + unsigned long type; + unsigned long protect; +}; +struct remote_op_result_vm_alloc +{ + void *base; + unsigned long size; +}; + +struct remote_op_params_vm_free +{ + void *addr; + unsigned long size; + unsigned long type; +}; +struct remote_op_result_vm_free +{ + void *base; + unsigned long size; +}; + +struct remote_op_params_vm_protect +{ + void *addr; + unsigned long size; + unsigned long new_prot; +}; +struct remote_op_result_vm_protect +{ + void *base; + unsigned long size; + unsigned long old_prot; +}; + +struct remote_op_params_vm_query +{ + void *addr; + int info_class; +}; + +struct remote_op_params_vm_map +{ + void *addr; + unsigned long zero_bits; + unsigned long commit_size; + unsigned long offset_low; + long offset_high; + unsigned long size; + int inherit; + unsigned long alloc_type; + unsigned long protect; +}; +struct remote_op_result_vm_map +{ + void *base; + unsigned long size; +}; + +struct remote_op_params_vm_flush +{ + void *addr; + unsigned long size; + unsigned long unknown; +}; +struct remote_op_result_vm_flush +{ + void *base; + unsigned long size; +}; + +/* structure for marshalling remote operation requests */ +struct remote_op_request +{ + enum remote_op_code op_code; + thread_id_t originator; + int params_size; +}; Index: server/thread.c =================================================================== RCS file: /home/wine/wine/server/thread.c,v retrieving revision 1.103 diff -u -r1.103 thread.c --- server/thread.c 27 Oct 2003 22:10:22 -0000 1.103 +++ server/thread.c 23 Sep 2004 09:23:23 -0000 @@ -142,6 +142,8 @@ thread->suspend = 0; thread->creation_time = time(NULL); thread->exit_time = 0; + thread->result_data = NULL; + thread->result_event = NULL; for (i = 0; i < MAX_INFLIGHT_FDS; i++) thread->inflight[i].server = thread->inflight[i].client = -1; @@ -210,6 +212,8 @@ if (thread->request_fd) release_object( thread->request_fd ); if (thread->reply_fd) release_object( thread->reply_fd ); if (thread->wait_fd) release_object( thread->wait_fd ); + if (thread->result_data) free( thread->result_data ); + if (thread->result_event) release_object( thread->result_event ); free_msg_queue( thread ); cleanup_clipboard_thread(thread); destroy_thread_windows( thread ); @@ -226,6 +230,8 @@ thread->request_fd = NULL; thread->reply_fd = NULL; thread->wait_fd = NULL; + thread->result_data = NULL; + thread->result_event = NULL; if (thread == booting_thread) /* killing booting thread */ { @@ -462,7 +468,12 @@ } /* send the wakeup signal to a thread */ +#define REMOTE_OPERATION_APPROACH_WAIT +#ifdef REMOTE_OPERATION_APPROACH_WAIT +int send_thread_wakeup( struct thread *thread, void *cookie, int signaled ) +#else static int send_thread_wakeup( struct thread *thread, void *cookie, int signaled ) +#endif { struct wake_up_reply reply; int ret; Index: server/thread.h =================================================================== RCS file: /home/wine/wine/server/thread.h,v retrieving revision 1.56 diff -u -r1.56 thread.h --- server/thread.h 10 Dec 2003 01:12:18 -0000 1.56 +++ server/thread.h 23 Sep 2004 09:23:24 -0000 @@ -94,6 +94,10 @@ time_t creation_time; /* Thread creation time */ time_t exit_time; /* Thread exit time */ struct token *token; /* security token associated with this thread */ + unsigned int remote_status; /* error code from remote operation */ + void *result_data; /* result data from remote operation */ + int result_size; /* size of result data */ + struct event *result_event; /* originator of remote operation waits on it */ }; struct thread_snapshot @@ -112,6 +116,10 @@ extern struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access ); extern struct thread *get_thread_from_pid( int pid ); extern void stop_thread( struct thread *thread ); +#define REMOTE_OPERATION_APPROACH_WAIT +#ifdef REMOTE_OPERATION_APPROACH_WAIT +extern int send_thread_wakeup( struct thread *thread, void *cookie, int signaled ); +#endif extern int wake_thread( struct thread *thread ); extern int add_queue( struct object *obj, struct wait_queue_entry *entry ); extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );