Framework for remote operations
Alexander Yaworsky
yaworsky at migusoft.ru
Wed Aug 25 02:15:27 CDT 2004
Hello
ChangeLog:
Basic framework for thread creation and memory
management functions in context of arbitrarily process.
Index: dlls/kernel/kernel_private.h
===================================================================
RCS file: /home/wine/wine/dlls/kernel/kernel_private.h,v
retrieving revision 1.20
diff -u -r1.20 kernel_private.h
--- dlls/kernel/kernel_private.h 14 May 2004 21:43:18 -0000 1.20
+++ dlls/kernel/kernel_private.h 25 Aug 2004 06:38:24 -0000
@@ -91,4 +91,6 @@
} INSTANCEDATA;
#include "poppack.h"
+extern void CALLBACK THREAD_Start( void *ptr );
+
#endif
Index: dlls/kernel/process.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/process.c,v
retrieving revision 1.72
diff -u -r1.72 process.c
--- dlls/kernel/process.c 24 Aug 2004 18:46:05 -0000 1.72
+++ dlls/kernel/process.c 25 Aug 2004 06:38:37 -0000
@@ -894,6 +894,7 @@
{
req->peb = peb;
req->ldt_copy = &wine_ldt_copy;
+ req->kernel_thread_start = THREAD_Start;
if ((ret = !wine_server_call_err( req )))
{
main_exe_file = reply->exe_file;
Index: dlls/kernel/thread.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/thread.c,v
retrieving revision 1.19
diff -u -r1.19 thread.c
--- dlls/kernel/thread.c 7 Jul 2004 00:49:34 -0000 1.19
+++ dlls/kernel/thread.c 25 Aug 2004 06:38:40 -0000
@@ -90,13 +90,13 @@
*
* Start execution of a newly created thread. Does not return.
*/
-static void CALLBACK THREAD_Start( void *ptr )
+void CALLBACK THREAD_Start( void *ptr )
{
struct new_thread_info *info = ptr;
LPTHREAD_START_ROUTINE func = info->func;
void *arg = info->arg;
- RtlFreeHeap( GetProcessHeap(), 0, info );
+ VirtualFree( info, 0, MEM_RELEASE );
if (TRACE_ON(relay))
DPRINTF("%04lx:Starting thread (entryproc=%p)\n", GetCurrentThreadId(), func );
@@ -121,39 +121,8 @@
LPTHREAD_START_ROUTINE start, LPVOID param,
DWORD flags, LPDWORD id )
{
- HANDLE handle;
- CLIENT_ID client_id;
- NTSTATUS status;
- SIZE_T stack_reserve = 0, stack_commit = 0;
- struct new_thread_info *info;
-
- if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*info) )))
- {
- SetLastError( ERROR_NOT_ENOUGH_MEMORY );
- return 0;
- }
- info->func = start;
- info->arg = param;
-
- if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
- else stack_commit = stack;
-
- status = RtlCreateUserThread( GetCurrentProcess(), NULL, (flags & CREATE_SUSPENDED) != 0,
- NULL, stack_reserve, stack_commit,
- THREAD_Start, info, &handle, &client_id );
- if (status == STATUS_SUCCESS)
- {
- if (id) *id = (DWORD)client_id.UniqueThread;
- if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
- SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
- }
- else
- {
- RtlFreeHeap( GetProcessHeap(), 0, info );
- SetLastError( RtlNtStatusToDosError(status) );
- handle = 0;
- }
- return handle;
+ return CreateRemoteThread( GetCurrentProcess(),
+ sa, stack, start, param, flags, id );
}
@@ -168,16 +137,66 @@
* Success: Handle to the new thread.
* Failure: NULL. Use GetLastError() to find the error cause.
*
- * BUGS
- * Unimplemented
*/
HANDLE WINAPI CreateRemoteThread( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
LPTHREAD_START_ROUTINE start, LPVOID param,
DWORD flags, LPDWORD id )
{
- FIXME("(): stub, Write Me.\n");
+ HANDLE handle;
+ CLIENT_ID client_id;
+ NTSTATUS status;
+ SIZE_T stack_reserve = 0, stack_commit = 0;
+ struct new_thread_info *info;
+ PRTL_THREAD_START_ROUTINE start_addr;
+
+ if (!(info = VirtualAllocEx( hProcess, NULL, sizeof(*info),
+ MEM_COMMIT, PAGE_READWRITE )))
+ return 0;
+
+ if( GetProcessId( hProcess ) == GetCurrentProcessId() )
+ {
+ info->func = start;
+ info->arg = param;
+ start_addr = (void*) THREAD_Start;
+ }
+ else
+ {
+ struct new_thread_info local_info;
+ DWORD written;
+
+ local_info.func = start;
+ local_info.arg = param;
+ if( ! WriteProcessMemory( hProcess, info, &local_info,
+ sizeof(struct new_thread_info), &written ) )
+ return NULL;
+ SERVER_START_REQ( get_kernel_thread_start )
+ {
+ req->handle = hProcess;
+ if (!(status = wine_server_call( req )))
+ start_addr = (PRTL_THREAD_START_ROUTINE) reply->address;
+ }
+ SERVER_END_REQ;
+ if (status)
+ goto error;
+ }
+
+ if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
+ else stack_commit = stack;
+
+ status = RtlCreateUserThread( hProcess, NULL, (flags & CREATE_SUSPENDED) != 0,
+ NULL, stack_reserve, stack_commit,
+ start_addr, info, &handle, &client_id );
+ if (status)
+ goto error;
+
+ if (id) *id = (DWORD)client_id.UniqueThread;
+ if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
+ SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
+ return handle;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+error:
+ VirtualFreeEx( hProcess, info, 0, MEM_RELEASE );
+ SetLastError( RtlNtStatusToDosError(status) );
return NULL;
}
Index: dlls/ntdll/ntdll_misc.h
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/ntdll_misc.h,v
retrieving revision 1.48
diff -u -r1.48 ntdll_misc.h
--- dlls/ntdll/ntdll_misc.h 15 Jul 2004 22:07:21 -0000 1.48
+++ dlls/ntdll/ntdll_misc.h 25 Aug 2004 06:38:43 -0000
@@ -98,4 +98,9 @@
extern int ntdll_wcstoumbs(DWORD flags, const WCHAR* src, int srclen, char* dst, int dstlen,
const char* defchar, int *used );
+/* remote operations */
+extern BOOL is_current_process( HANDLE handle );
+extern NTSTATUS remote_op( HANDLE process, int type,
+ void* params, int params_size, void* result, int* result_size );
+
#endif
Index: dlls/ntdll/thread.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/thread.c,v
retrieving revision 1.21
diff -u -r1.21 thread.c
--- dlls/ntdll/thread.c 23 Aug 2004 18:52:54 -0000 1.21
+++ dlls/ntdll/thread.c 25 Aug 2004 06:38:46 -0000
@@ -215,6 +215,29 @@
ULONG size;
int request_pipe[2];
NTSTATUS status;
+
+ if( ! is_current_process( process ) )
+ {
+ struct remote_op_params_new_thread op_params;
+ struct remote_op_result_new_thread op_result;
+ int result_size = sizeof(struct remote_op_result_new_thread);
+
+ op_params.suspend = suspended;
+ op_params.stack_addr = stack_addr;
+ op_params.stack_reserve = stack_reserve;
+ op_params.stack_commit = stack_commit;
+ op_params.start = start;
+ op_params.param = param;
+ status = remote_op( process, REMOTE_OP_NEW_THREAD,
+ &op_params, sizeof(op_params),
+ &op_result, &result_size );
+ if (status)
+ return status;
+
+ handle = op_result.handle;
+ tid = op_result.tid;
+ goto success;
+ }
if (pipe( request_pipe ) == -1) return STATUS_TOO_MANY_OPENED_FILES;
fcntl( request_pipe[1], F_SETFD, 1 ); /* set close on exec flag */
@@ -284,6 +307,7 @@
goto error;
}
+success:
if (id) id->UniqueThread = (HANDLE)tid;
if (handle_ptr) *handle_ptr = handle;
else NtClose( handle );
Index: dlls/ntdll/virtual.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/virtual.c,v
retrieving revision 1.38
diff -u -r1.38 virtual.c
--- dlls/ntdll/virtual.c 18 Aug 2004 00:04:58 -0000 1.38
+++ dlls/ntdll/virtual.c 25 Aug 2004 06:38:55 -0000
@@ -1028,7 +1028,7 @@
*
* Check whether a process handle is for the current process.
*/
-static BOOL is_current_process( HANDLE handle )
+BOOL is_current_process( HANDLE handle )
{
BOOL ret = FALSE;
@@ -1045,6 +1045,53 @@
/***********************************************************************
+ * remote_op
+ *
+ */
+NTSTATUS remote_op( HANDLE process, int type,
+ 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->type = type;
+ 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 */
+ status = NtWaitForMultipleObjects( 1, &event, FALSE, FALSE, NULL );
+ NtClose( event );
+ if (HIWORD(status))
+ return status;
+
+ /* get result */
+ 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 );
+ }
+ }
+ SERVER_END_REQ;
+
+ return status? status : remote_status;
+}
+
+
+/***********************************************************************
* virtual_init
*/
void virtual_init(void)
@@ -1158,20 +1205,39 @@
{
void *base;
BYTE vprot;
- DWORD size = *size_ptr;
+ DWORD size;
NTSTATUS status = STATUS_SUCCESS;
struct file_view *view;
+ TRACE("%p %p %p %p %lx %08lx\n", process, ret, addr, size_ptr, type, protect );
+
+ /* sanity check */
+ if (NULL == ret || NULL == size_ptr) return STATUS_INVALID_PARAMETER;
+
+ TRACE("size=%08lx\n", *size_ptr );
+ if (!(size = *size_ptr)) return STATUS_INVALID_PARAMETER;
+
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;
}
- TRACE("%p %08lx %lx %08lx\n", addr, size, type, protect );
-
- if (!size) return STATUS_INVALID_PARAMETER;
-
/* Round parameters to a page boundary */
if (size > 0x7fc00000) return STATUS_WORKING_SET_LIMIT_RANGE; /* 2Gb - 4Mb */
@@ -1265,17 +1331,38 @@
FILE_VIEW *view;
char *base;
NTSTATUS status = STATUS_SUCCESS;
- LPVOID addr = *addr_ptr;
- DWORD size = *size_ptr;
+ LPVOID addr;
+ DWORD size;
+
+ TRACE("%p %p %p %lx\n", process, addr_ptr, size_ptr, type );
+
+ /* sanity check */
+ if (NULL == addr_ptr || NULL == size_ptr) return ERROR_INVALID_PARAMETER;
+
+ addr = *addr_ptr;
+ size = *size_ptr;
+ TRACE("addr=%p size=%08lx\n", addr, size );
if (!is_current_process( process ))
{
- ERR("Unsupported on other process\n");
- return STATUS_ACCESS_DENIED;
+ struct remote_op_params_vm_free free_params;
+ struct remote_op_result_vm_free free_result;
+ int result_size = sizeof(struct remote_op_result_vm_free);
+
+ free_params.addr = addr;
+ free_params.size = size;
+ free_params.type = type;
+ status = remote_op( process, REMOTE_OP_VM_FREE,
+ &free_params, sizeof(free_params),
+ &free_result, &result_size );
+ if (!status)
+ {
+ *addr_ptr = free_result.base;
+ *size_ptr = free_result.size;
+ }
+ return status;
}
- TRACE("%p %08lx %lx\n", addr, size, type );
-
/* Fix the parameters */
size = ROUND_SIZE( addr, size );
@@ -1341,17 +1428,39 @@
char *base;
UINT i;
BYTE vprot, *p;
- DWORD prot, size = *size_ptr;
- LPVOID addr = *addr_ptr;
+ DWORD prot, size;
+ LPVOID addr;
+
+ TRACE("%p %p %p %08lx %p\n", process, addr_ptr, size_ptr, new_prot, old_prot );
+
+ /* sanity check */
+ if (NULL == addr_ptr || NULL == size_ptr) return ERROR_INVALID_PARAMETER;
+
+ addr = *addr_ptr;
+ size = *size_ptr;
+ TRACE("addr=%p size=%08lx\n", addr, size );
if (!is_current_process( process ))
{
- ERR("Unsupported on other process\n");
- return STATUS_ACCESS_DENIED;
+ struct remote_op_params_vm_protect protect_params;
+ struct remote_op_result_vm_protect protect_result;
+ int result_size = sizeof(struct remote_op_result_vm_protect);
+
+ protect_params.addr = addr;
+ protect_params.size = size;
+ protect_params.new_prot = new_prot;
+ status = remote_op( process, REMOTE_OP_VM_PROTECT,
+ &protect_params, sizeof(protect_params),
+ &protect_result, &result_size );
+ if (!status)
+ {
+ *addr_ptr = protect_result.base;
+ *size_ptr = protect_result.size;
+ if (old_prot) *old_prot = protect_result.old_prot;
+ }
+ return status;
}
- TRACE("%p %08lx %08lx\n", addr, size, new_prot );
-
/* Fix the parameters */
size = ROUND_SIZE( addr, size );
@@ -1409,16 +1518,41 @@
UINT size = 0;
MEMORY_BASIC_INFORMATION *info = buffer;
- if (info_class != MemoryBasicInformation) return STATUS_INVALID_INFO_CLASS;
- if (ADDRESS_SPACE_LIMIT && addr >= ADDRESS_SPACE_LIMIT)
- return STATUS_WORKING_SET_LIMIT_RANGE;
+ TRACE("%p %p %d %p %lu %p\n", process, addr, info_class, buffer, len, res_len );
+
+ /* sanity check */
+ if (NULL == buffer) return ERROR_INVALID_PARAMETER;
if (!is_current_process( process ))
{
- ERR("Unsupported on other process\n");
- return STATUS_ACCESS_DENIED;
+ struct remote_op_params_vm_query *query_params;
+ int result_size = len;
+ NTSTATUS status;
+
+ query_params = (struct remote_op_params_vm_query*)
+ RtlAllocateHeap( GetProcessHeap(), 0, sizeof(struct remote_op_params_vm_query) + len );
+ if (!query_params)
+ return STATUS_NO_MEMORY;
+
+ query_params->addr = (void*) addr;
+ query_params->info_class = info_class;
+ if (len) memcpy( query_params + 1, buffer, len );
+ status = remote_op( process, REMOTE_OP_VM_QUERY,
+ query_params, sizeof(struct remote_op_params_vm_query) + len,
+ buffer, &result_size );
+ RtlFreeHeap( GetProcessHeap(), 0, query_params );
+ if (!status)
+ if (res_len) *res_len = result_size;
+ return status;
}
+ if (info_class != MemoryBasicInformation) return STATUS_INVALID_INFO_CLASS;
+ if (ADDRESS_SPACE_LIMIT && addr >= ADDRESS_SPACE_LIMIT)
+ return STATUS_WORKING_SET_LIMIT_RANGE;
+
+ /* sanity check */
+ if (len < sizeof(MEMORY_BASIC_INFORMATION)) return ERROR_INVALID_PARAMETER;
+
base = ROUND_ADDR( addr, page_mask );
/* Find the view containing the address */
@@ -1497,10 +1631,10 @@
*/
NTSTATUS WINAPI NtLockVirtualMemory( HANDLE process, PVOID *addr, ULONG *size, ULONG unknown )
{
+ /* FIXME */
if (!is_current_process( process ))
{
- ERR("Unsupported on other process\n");
- return STATUS_ACCESS_DENIED;
+ return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
}
@@ -1512,10 +1646,10 @@
*/
NTSTATUS WINAPI NtUnlockVirtualMemory( HANDLE process, PVOID *addr, ULONG *size, ULONG unknown )
{
+ /* FIXME */
if (!is_current_process( process ))
{
- ERR("Unsupported on other process\n");
- return STATUS_ACCESS_DENIED;
+ return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
}
@@ -1608,15 +1742,40 @@
HANDLE shared_file;
BOOL removable = FALSE;
+ TRACE("%p %p %p %lu %lu %p %p %d %lu %lx\n", handle, process, addr_ptr, zero_bits,
+ commit_size, offset, size_ptr, inherit, alloc_type, protect );
+
+ /* sanity check */
+ if (NULL == addr_ptr || NULL == size_ptr || NULL == offset) return ERROR_INVALID_PARAMETER;
+
+ TRACE("addr=%p off=%lx%08lx\n", *addr_ptr, offset->u.HighPart, offset->u.LowPart );
+
if (!is_current_process( process ))
{
- ERR("Unsupported on other process\n");
- return STATUS_ACCESS_DENIED;
+ struct remote_op_params_vm_map map_params;
+ struct remote_op_result_vm_map map_result;
+ int result_size = sizeof(struct remote_op_result_vm_map);
+
+ map_params.addr = *addr_ptr;
+ map_params.zero_bits = zero_bits;
+ map_params.commit_size = commit_size;
+ map_params.offset_low = offset->u.LowPart;
+ map_params.offset_high = offset->u.HighPart;
+ map_params.size = *size_ptr;
+ map_params.inherit = inherit;
+ map_params.alloc_type = alloc_type;
+ map_params.protect = protect;
+ res = remote_op( process, REMOTE_OP_VM_MAP,
+ &map_params, sizeof(map_params),
+ &map_result, &result_size );
+ if (!res)
+ {
+ *addr_ptr = map_result.base;
+ *size_ptr = map_result.size;
+ }
+ return res;
}
- TRACE("handle=%p addr=%p off=%lx%08lx size=%x access=%lx\n",
- handle, *addr_ptr, offset->u.HighPart, offset->u.LowPart, size, protect );
-
/* Check parameters */
if ((offset->u.LowPart & granularity_mask) ||
@@ -1764,11 +1923,14 @@
NTSTATUS status = STATUS_INVALID_PARAMETER;
void *base = ROUND_ADDR( addr, page_mask );
+ TRACE("%p %p base=%p\n", process, addr, base );
+
if (!is_current_process( process ))
{
- ERR("Unsupported on other process\n");
- return STATUS_ACCESS_DENIED;
+ return remote_op( process, REMOTE_OP_VM_UNMAP,
+ &addr, sizeof(addr), NULL, NULL );
}
+
RtlEnterCriticalSection( &csVirtual );
if ((view = VIRTUAL_FindView( base )) && (base == view->base))
{
@@ -1789,13 +1951,38 @@
{
FILE_VIEW *view;
NTSTATUS status = STATUS_SUCCESS;
- void *addr = ROUND_ADDR( *addr_ptr, page_mask );
+ void *addr;
+ ULONG size;
+
+ TRACE("%p %p %p %lx\n", process, addr_ptr, size_ptr, unknown );
+
+ /* sanity check */
+ if (NULL == addr_ptr || NULL == size_ptr) return ERROR_INVALID_PARAMETER;
+
+ size = *size_ptr;
+ TRACE("addr=%p size=%08lx\n", *addr_ptr, size );
if (!is_current_process( process ))
{
- ERR("Unsupported on other process\n");
- return STATUS_ACCESS_DENIED;
+ struct remote_op_params_vm_flush flush_params;
+ struct remote_op_result_vm_flush flush_result;
+ int result_size = sizeof(struct remote_op_result_vm_flush);
+
+ flush_params.addr = (void*) *addr_ptr;
+ flush_params.size = size;
+ flush_params.unknown = unknown;
+ status = remote_op( process, REMOTE_OP_VM_FLUSH,
+ &flush_params, sizeof(flush_params),
+ &flush_result, &result_size );
+ if (!status)
+ {
+ *addr_ptr = flush_result.base;
+ if (!*size_ptr) *size_ptr = flush_result.size;
+ }
+ return status;
}
+
+ addr = ROUND_ADDR( *addr_ptr, page_mask );
RtlEnterCriticalSection( &csVirtual );
if (!(view = VIRTUAL_FindView( addr ))) status = STATUS_INVALID_PARAMETER;
else
Index: include/wine/server_protocol.h
===================================================================
RCS file: /home/wine/wine/include/wine/server_protocol.h,v
retrieving revision 1.111
diff -u -r1.111 server_protocol.h
--- include/wine/server_protocol.h 18 Aug 2004 00:04:58 -0000 1.111
+++ include/wine/server_protocol.h 25 Aug 2004 06:39:12 -0000
@@ -239,6 +239,7 @@
struct request_header __header;
void* peb;
void* ldt_copy;
+ void* kernel_thread_start;
};
struct init_process_reply
{
@@ -3095,6 +3096,157 @@
#define SET_GLOBAL_TASKMAN_WINDOW 0x04
+struct get_kernel_thread_start_request
+{
+ struct request_header __header;
+ obj_handle_t handle;
+};
+struct get_kernel_thread_start_reply
+{
+ struct reply_header __header;
+ void* address;
+};
+
+
+struct remote_operation_request
+{
+ struct request_header __header;
+ obj_handle_t handle;
+ int type;
+ /* VARARG(data,bytes); */
+};
+struct remote_operation_reply
+{
+ struct reply_header __header;
+ obj_handle_t event;
+};
+enum remote_op_type
+{
+ 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
+};
+
+
+struct remote_operation_complete_request
+{
+ struct request_header __header;
+ thread_id_t originator;
+ unsigned int status;
+ /* VARARG(data,bytes); */
+};
+struct remote_operation_complete_reply
+{
+ struct reply_header __header;
+};
+
+
+struct remote_operation_result_request
+{
+ struct request_header __header;
+};
+struct remote_operation_result_reply
+{
+ struct reply_header __header;
+ unsigned int status;
+ /* VARARG(data,bytes); */
+};
+
+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;
+};
+
+
enum request
{
REQ_new_process,
@@ -3274,6 +3426,10 @@
REQ_set_clipboard_info,
REQ_open_token,
REQ_set_global_windows,
+ REQ_get_kernel_thread_start,
+ REQ_remote_operation,
+ REQ_remote_operation_complete,
+ REQ_remote_operation_result,
REQ_NB_REQUESTS
};
@@ -3458,6 +3614,10 @@
struct set_clipboard_info_request set_clipboard_info_request;
struct open_token_request open_token_request;
struct set_global_windows_request set_global_windows_request;
+ struct get_kernel_thread_start_request get_kernel_thread_start_request;
+ struct remote_operation_request remote_operation_request;
+ struct remote_operation_complete_request remote_operation_complete_request;
+ struct remote_operation_result_request remote_operation_result_request;
};
union generic_reply
{
@@ -3640,6 +3800,10 @@
struct set_clipboard_info_reply set_clipboard_info_reply;
struct open_token_reply open_token_reply;
struct set_global_windows_reply set_global_windows_reply;
+ struct get_kernel_thread_start_reply get_kernel_thread_start_reply;
+ struct remote_operation_reply remote_operation_reply;
+ struct remote_operation_complete_reply remote_operation_complete_reply;
+ struct remote_operation_result_reply remote_operation_result_reply;
};
#define SERVER_PROTOCOL_VERSION 149
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 25 Aug 2004 06:39:20 -0000
@@ -45,6 +45,7 @@
#include "request.h"
#include "console.h"
#include "user.h"
+#include "object.h"
/* process structure */
@@ -972,6 +973,7 @@
reply->info_size = 0;
current->process->peb = req->peb;
current->process->ldt_copy = req->ldt_copy;
+ current->process->kernel_thread_start = req->kernel_thread_start;
current->process->startup_info = init_process( reply );
}
@@ -1188,5 +1190,136 @@
reply->event = alloc_handle( current->process, process->idle_event,
EVENT_ALL_ACCESS, 0 );
release_object( process );
+ }
+}
+
+/* return address of internal thread start function in kernel32 */
+DECL_HANDLER(get_kernel_thread_start)
+{
+ struct process *process;
+
+ /* because this is used for CreateRemoteThread,
+ required access rights must be the same
+ */
+ if ((process = get_process_from_handle( req->handle,
+ PROCESS_CREATE_THREAD
+ | PROCESS_QUERY_INFORMATION
+ | PROCESS_VM_OPERATION
+ | PROCESS_VM_READ | PROCESS_VM_WRITE )))
+ {
+ reply->address = process->kernel_thread_start;
+ release_object( process );
+ }
+}
+
+/* Accept parameters for remote operation and start it */
+DECL_HANDLER(remote_operation)
+{
+ int access;
+ struct process *process;
+ struct event *event;
+
+ /* define required access rights */
+ switch( req->type )
+ {
+ 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;
+
+ /* FIXME: pass somehow operation type, params and originator thread id
+ for some thread in the process and force execution of operation */
+ set_error( STATUS_NOT_IMPLEMENTED );
+
+ /* save event object in thread structure for future set operation;
+ we do not release it here */
+ current->result_event = 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 );
+
+ if (!thread) return;
+
+ /* save status */
+ thread->remote_status = 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 */
+ 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;
+
+ if (current->result_data)
+ {
+ void *result = current->result_data;
+ current->result_data = NULL;
+ set_reply_data_ptr( result, current->result_size );
}
}
Index: server/process.h
===================================================================
RCS file: /home/wine/wine/server/process.h,v
retrieving revision 1.42
diff -u -r1.42 process.h
--- server/process.h 10 Dec 2003 04:08:06 -0000 1.42
+++ server/process.h 25 Aug 2004 06:39:21 -0000
@@ -79,6 +79,8 @@
struct process_dll exe; /* main exe file */
void *peb; /* PEB address in client address space */
void *ldt_copy; /* pointer to LDT copy in client addr space */
+ void *kernel_thread_start; /* addr of internal kernel32 thread routine */
+ /* (in client address space) */
};
struct process_snapshot
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 25 Aug 2004 06:39:30 -0000
@@ -232,6 +232,7 @@
@REQ(init_process)
void* peb; /* addr of PEB */
void* ldt_copy; /* addr of LDT copy */
+ void* kernel_thread_start; /* addr of internal kernel32 thread routine */
@REPLY
int create_flags; /* creation flags */
unsigned int server_start; /* server start time (GetTickCount) */
@@ -2166,3 +2167,133 @@
#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
+
+/* Get address of kernel32 internal THREAD_Start function */
+ at REQ(get_kernel_thread_start)
+ obj_handle_t handle; /* process handle */
+ at REPLY
+ void* address;
+ at END
+
+/* Accept parameters for remote operation and start it */
+ at REQ(remote_operation)
+ obj_handle_t handle; /* process handle */
+ int type; /* operation type (see below) */
+ VARARG(data,bytes); /* operation parameters (see below) */
+ at REPLY
+ obj_handle_t event; /* originator waits for it */
+ at END
+enum remote_op_type
+{
+ 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 */
+ at REQ(remote_operation_complete)
+ thread_id_t originator; /* originator thread id */
+ unsigned int status; /* operation status */
+ VARARG(data,bytes); /* operation result data (see below) */
+ at END
+
+/* Get result of remote opertaion */
+ at REQ(remote_operation_result)
+ at REPLY
+ unsigned int status; /* operation status */
+ VARARG(data,bytes); /* operation result data (see below) */
+ at 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;
+};
Index: server/request.h
===================================================================
RCS file: /home/wine/wine/server/request.h,v
retrieving revision 1.102
diff -u -r1.102 request.h
--- server/request.h 20 Jul 2004 22:17:39 -0000 1.102
+++ server/request.h 25 Aug 2004 06:39:32 -0000
@@ -280,6 +280,10 @@
DECL_HANDLER(set_clipboard_info);
DECL_HANDLER(open_token);
DECL_HANDLER(set_global_windows);
+DECL_HANDLER(get_kernel_thread_start);
+DECL_HANDLER(remote_operation);
+DECL_HANDLER(remote_operation_complete);
+DECL_HANDLER(remote_operation_result);
#ifdef WANT_REQUEST_HANDLERS
@@ -463,6 +467,10 @@
(req_handler)req_set_clipboard_info,
(req_handler)req_open_token,
(req_handler)req_set_global_windows,
+ (req_handler)req_get_kernel_thread_start,
+ (req_handler)req_remote_operation,
+ (req_handler)req_remote_operation_complete,
+ (req_handler)req_remote_operation_result,
};
#endif /* WANT_REQUEST_HANDLERS */
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 25 Aug 2004 06:39:36 -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 */
{
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 25 Aug 2004 06:39:37 -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 for it */
};
struct thread_snapshot
Index: server/trace.c
===================================================================
RCS file: /home/wine/wine/server/trace.c,v
retrieving revision 1.212
diff -u -r1.212 trace.c
--- server/trace.c 18 Aug 2004 00:04:58 -0000 1.212
+++ server/trace.c 25 Aug 2004 06:39:49 -0000
@@ -471,6 +471,7 @@
{
fprintf( stderr, " peb=%p,", req->peb );
fprintf( stderr, " ldt_copy=%p", req->ldt_copy );
+ fprintf( stderr, " kernel_thread_start=%p", req->kernel_thread_start );
}
static void dump_init_process_reply( const struct init_process_reply *req )
@@ -2548,6 +2549,48 @@
fprintf( stderr, " old_taskman_window=%p", req->old_taskman_window );
}
+static void dump_get_kernel_thread_start_request( const struct get_kernel_thread_start_request *req )
+{
+ fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_get_kernel_thread_start_reply( const struct get_kernel_thread_start_reply *req )
+{
+ fprintf( stderr, " address=%p", req->address );
+}
+
+static void dump_remote_operation_request( const struct remote_operation_request *req )
+{
+ fprintf( stderr, " handle=%p,", req->handle );
+ fprintf( stderr, " type=%d,", req->type );
+ fprintf( stderr, " data=" );
+ dump_varargs_bytes( cur_size );
+}
+
+static void dump_remote_operation_reply( const struct remote_operation_reply *req )
+{
+ fprintf( stderr, " event=%p", req->event );
+}
+
+static void dump_remote_operation_complete_request( const struct remote_operation_complete_request *req )
+{
+ fprintf( stderr, " originator=%04x,", req->originator );
+ fprintf( stderr, " status=%08x,", req->status );
+ fprintf( stderr, " data=" );
+ dump_varargs_bytes( cur_size );
+}
+
+static void dump_remote_operation_result_request( const struct remote_operation_result_request *req )
+{
+}
+
+static void dump_remote_operation_result_reply( const struct remote_operation_result_reply *req )
+{
+ fprintf( stderr, " status=%08x,", req->status );
+ fprintf( stderr, " data=" );
+ dump_varargs_bytes( cur_size );
+}
+
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_get_new_process_info_request,
@@ -2726,6 +2769,10 @@
(dump_func)dump_set_clipboard_info_request,
(dump_func)dump_open_token_request,
(dump_func)dump_set_global_windows_request,
+ (dump_func)dump_get_kernel_thread_start_request,
+ (dump_func)dump_remote_operation_request,
+ (dump_func)dump_remote_operation_complete_request,
+ (dump_func)dump_remote_operation_result_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -2906,6 +2953,10 @@
(dump_func)dump_set_clipboard_info_reply,
(dump_func)dump_open_token_reply,
(dump_func)dump_set_global_windows_reply,
+ (dump_func)dump_get_kernel_thread_start_reply,
+ (dump_func)dump_remote_operation_reply,
+ (dump_func)0,
+ (dump_func)dump_remote_operation_result_reply,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -3086,6 +3137,10 @@
"set_clipboard_info",
"open_token",
"set_global_windows",
+ "get_kernel_thread_start",
+ "remote_operation",
+ "remote_operation_complete",
+ "remote_operation_result",
};
/* ### make_requests end ### */
More information about the wine-patches
mailing list