Alexander Yaworsky wrote:
Hello
This is a basic framework. Not finished, not really tested -- just stable point. It does no harm for applications I'm using. I would be glad to get some comments and suggestions.
Looks good so far, apart from a few comments below.
@@ -168,16 +137,68 @@
- 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");
- extern BOOL __wine_is_current_process( HANDLE hProcess );
- 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( __wine_is_current_process( hProcess ) )
There is no need to export __wine_is_current_process from ntdll and use it here when standard win32 apis will suffice.
- {
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,
This looks wrong. &info? Don't you mean just info?
/***********************************************************************
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;
+}
I don't really like the idea of a multiplexer like this, but I guess otherwise we would end up with duplicated code.
+/* 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 )))
I would argue that it is perfectly alright for the access rights to be just PROCESS_QUERY_INFORMATION here.
- {
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 );
+}
Is it really necessary to perform the action required for remote invocation of some operation asynchronously? It seems to add a lot of unneeded complexity.
+/* 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 );
}
Rob