Implemented NtQueueApcThread, and changed the server APC interface to

always take 3 parameters.
Implemented a number of other ntdll thread functions, and use them
from the kernel ones.
This commit is contained in:
Alexandre Julliard 2003-04-04 22:26:34 +00:00
parent c7bebba198
commit 088bcf9ca5
16 changed files with 286 additions and 165 deletions

View File

@ -93,6 +93,7 @@ C_SRCS = \
signal_powerpc.c \
signal_sparc.c \
sync.c \
thread.c \
virtual.c \
time.c \
wcstring.c

View File

@ -200,48 +200,6 @@ NTSTATUS WINAPI NtSetInformationProcess(
* Thread
*/
/******************************************************************************
* NtResumeThread [NTDLL.@]
* ZwResumeThread [NTDLL.@]
*/
NTSTATUS WINAPI NtResumeThread(
IN HANDLE ThreadHandle,
IN PULONG SuspendCount)
{
FIXME("(%p,%p),stub!\n",
ThreadHandle,SuspendCount);
return 0;
}
/******************************************************************************
* NtTerminateThread [NTDLL.@]
* ZwTerminateThread [NTDLL.@]
*/
NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code )
{
NTSTATUS ret;
BOOL self, last;
SERVER_START_REQ( terminate_thread )
{
req->handle = handle;
req->exit_code = exit_code;
ret = wine_server_call( req );
self = !ret && reply->self;
last = reply->last;
}
SERVER_END_REQ;
if (self)
{
if (last) exit( exit_code );
else SYSDEPS_ExitThread( exit_code );
}
return ret;
}
/******************************************************************************
* NtQueryInformationThread [NTDLL.@]
* ZwQueryInformationThread [NTDLL.@]

View File

@ -114,7 +114,7 @@
@ stub NtFlushWriteBuffer
@ stdcall NtFreeVirtualMemory(long ptr ptr long)
@ stdcall NtFsControlFile(long long long long long long long long long long)
@ stub NtGetContextThread
@ stdcall NtGetContextThread(long ptr)
@ stub NtGetPlugPlayEvent
@ stub NtGetTickCount
@ stub NtImpersonateClientOfPort
@ -142,7 +142,7 @@
@ stdcall NtOpenSection(ptr long ptr)
@ stdcall NtOpenSemaphore(long long ptr)
@ stdcall NtOpenSymbolicLinkObject (long long long)
@ stub NtOpenThread
@ stdcall NtOpenThread(ptr long ptr ptr)
@ stdcall NtOpenThreadToken(long long long long)
@ stub NtOpenTimer
@ stub NtPlugPlayControl
@ -181,6 +181,7 @@
@ stdcall NtQueryValueKey(long long long long long long)
@ stdcall NtQueryVirtualMemory(long ptr long ptr long ptr)
@ stdcall NtQueryVolumeInformationFile(long ptr ptr long long)
@ stdcall NtQueueApcThread(long ptr long long long)
@ stdcall NtRaiseException(ptr ptr long)
@ stub NtRaiseHardError
@ stdcall NtReadFile(long long long long long long long long long)
@ -204,7 +205,7 @@
@ stdcall NtResumeThread(long long)
@ stdcall NtSaveKey(long long)
@ stub NtSecureConnectPort
@ stub NtSetContextThread
@ stdcall NtSetContextThread(long ptr)
@ stub NtSetDefaultHardErrorPort
@ stub NtSetDefaultLocale
@ stub NtSetEaFile
@ -236,7 +237,7 @@
@ stub NtShutdownSystem
@ stub NtStartProfile
@ stub NtStopProfile
@ stub NtSuspendThread
@ stdcall NtSuspendThread(long ptr)
@ stub NtSystemDebugControl
@ stdcall NtTerminateProcess(long long)
@ stdcall NtTerminateThread(long long)
@ -640,7 +641,7 @@
@ stub ZwFlushWriteBuffer
@ stdcall ZwFreeVirtualMemory(long ptr ptr long) NtFreeVirtualMemory
@ stdcall ZwFsControlFile(long long long long long long long long long long) NtFsControlFile
@ stub ZwGetContextThread
@ stdcall ZwGetContextThread(long ptr) NtGetContextThread
@ stub ZwGetPlugPlayEvent
@ stub ZwGetTickCount
@ stub ZwImpersonateClientOfPort
@ -668,7 +669,7 @@
@ stdcall ZwOpenSection(ptr long ptr) NtOpenSection
@ stdcall ZwOpenSemaphore(long long ptr) NtOpenSemaphore
@ stdcall ZwOpenSymbolicLinkObject (long long long) NtOpenSymbolicLinkObject
@ stub ZwOpenThread
@ stdcall ZwOpenThread(ptr long ptr ptr) NtOpenThread
@ stdcall ZwOpenThreadToken(long long long long) NtOpenThreadToken
@ stub ZwOpenTimer
@ stub ZwPlugPlayControl
@ -728,7 +729,7 @@
@ stdcall ZwRestoreKey(long long long) NtRestoreKey
@ stdcall ZwResumeThread(long long) NtResumeThread
@ stdcall ZwSaveKey(long long) NtSaveKey
@ stub ZwSetContextThread
@ stdcall ZwSetContextThread(long ptr) NtSetContextThread
@ stub ZwSetDefaultHardErrorPort
@ stub ZwSetDefaultLocale
@ stub ZwSetEaFile
@ -760,7 +761,7 @@
@ stub ZwShutdownSystem
@ stub ZwStartProfile
@ stub ZwStopProfile
@ stub ZwSuspendThread
@ stdcall ZwSuspendThread(long ptr) NtSuspendThread
@ stub ZwSystemDebugControl
@ stdcall ZwTerminateProcess(long long) NtTerminateProcess
@ stdcall ZwTerminateThread(long long) NtTerminateThread
@ -1009,7 +1010,6 @@
@ stub NtDeleteAtom
@ stub NtFindAtom
@ stub NtQueryFullAttributesFile
@ stub NtQueueApcThread
@ stub NtReadFileScatter
@ stub NtSignalAndWaitForSingleObject
@ stub NtWriteFileGather

View File

@ -855,7 +855,7 @@ static void do_trap( CONTEXT *context, int trap_code )
else /* hardware breakpoint, fetch the debug registers */
{
context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(GetCurrentThread(), context);
NtGetContextThread(GetCurrentThread(), context);
}
break;
case T_BPTFLT: /* Breakpoint exception */
@ -879,7 +879,7 @@ static void do_trap( CONTEXT *context, int trap_code )
{
/* the debug registers have changed, set the new values */
context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
SetThreadContext(GetCurrentThread(), context);
NtSetContextThread(GetCurrentThread(), context);
}
}

View File

@ -357,9 +357,9 @@ static int wait_reply( void *cookie )
*/
static void call_apcs( BOOL alertable )
{
FARPROC proc = NULL;
FARPROC proc;
LARGE_INTEGER time;
void *args[4];
void *arg1, *arg2, *arg3;
for (;;)
{
@ -367,12 +367,11 @@ static void call_apcs( BOOL alertable )
SERVER_START_REQ( get_apc )
{
req->alertable = alertable;
wine_server_set_reply( req, args, sizeof(args) );
if (!wine_server_call( req ))
{
type = reply->type;
proc = reply->func;
}
if (!wine_server_call( req )) type = reply->type;
proc = reply->func;
arg1 = reply->arg1;
arg2 = reply->arg2;
arg3 = reply->arg3;
}
SERVER_END_REQ;
@ -381,19 +380,19 @@ static void call_apcs( BOOL alertable )
case APC_NONE:
return; /* no more APCs */
case APC_ASYNC:
proc( args[0], args[1]);
proc( arg1, arg2 );
break;
case APC_USER:
proc( args[0] );
proc( arg1, arg2, arg3 );
break;
case APC_TIMER:
/* convert sec/usec to NT time */
RtlSecondsSince1970ToTime( (time_t)args[0], &time );
time.QuadPart += (DWORD)args[1] * 10;
proc( args[2], time.s.LowPart, time.s.HighPart );
RtlSecondsSince1970ToTime( (time_t)arg1, &time );
time.QuadPart += (DWORD)arg2 * 10;
proc( arg3, time.s.LowPart, time.s.HighPart );
break;
case APC_ASYNC_IO:
check_async_list ( args[0], (DWORD) args[1]);
check_async_list( arg1, (DWORD) arg2 );
break;
default:
server_protocol_error( "get_apc_request: bad type %d\n", type );

171
dlls/ntdll/thread.c Normal file
View File

@ -0,0 +1,171 @@
/*
* NT threads support
*
* Copyright 1996, 2003 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "winternl.h"
#include "wine/server.h"
/***********************************************************************
* NtOpenThread (NTDLL.@)
* ZwOpenThread (NTDLL.@)
*/
NTSTATUS WINAPI NtOpenThread( HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, const CLIENT_ID *id )
{
NTSTATUS ret;
SERVER_START_REQ( open_thread )
{
req->tid = (thread_id_t)id->UniqueThread;
req->access = access;
req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
ret = wine_server_call( req );
*handle = reply->handle;
}
SERVER_END_REQ;
return ret;
}
/******************************************************************************
* NtSuspendThread (NTDLL.@)
* ZwSuspendThread (NTDLL.@)
*/
NTSTATUS WINAPI NtSuspendThread( HANDLE handle, PULONG count )
{
NTSTATUS ret;
SERVER_START_REQ( suspend_thread )
{
req->handle = handle;
if (!(ret = wine_server_call( req ))) *count = reply->count;
}
SERVER_END_REQ;
return ret;
}
/******************************************************************************
* NtResumeThread (NTDLL.@)
* ZwResumeThread (NTDLL.@)
*/
NTSTATUS WINAPI NtResumeThread( HANDLE handle, PULONG count )
{
NTSTATUS ret;
SERVER_START_REQ( resume_thread )
{
req->handle = handle;
if (!(ret = wine_server_call( req ))) *count = reply->count;
}
SERVER_END_REQ;
return ret;
}
/******************************************************************************
* NtTerminateThread (NTDLL.@)
* ZwTerminateThread (NTDLL.@)
*/
NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code )
{
NTSTATUS ret;
BOOL self, last;
SERVER_START_REQ( terminate_thread )
{
req->handle = handle;
req->exit_code = exit_code;
ret = wine_server_call( req );
self = !ret && reply->self;
last = reply->last;
}
SERVER_END_REQ;
if (self)
{
if (last) exit( exit_code );
else SYSDEPS_ExitThread( exit_code );
}
return ret;
}
/******************************************************************************
* NtQueueApcThread (NTDLL.@)
*/
NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1,
ULONG_PTR arg2, ULONG_PTR arg3 )
{
NTSTATUS ret;
SERVER_START_REQ( queue_apc )
{
req->handle = handle;
req->user = 1;
req->func = func;
req->arg1 = (void *)arg1;
req->arg2 = (void *)arg2;
req->arg3 = (void *)arg3;
ret = wine_server_call( req );
}
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* NtSetContextThread (NTDLL.@)
* ZwSetContextThread (NTDLL.@)
*/
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
{
NTSTATUS ret;
SERVER_START_REQ( set_thread_context )
{
req->handle = handle;
req->flags = context->ContextFlags;
wine_server_add_data( req, context, sizeof(*context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* NtGetContextThread (NTDLL.@)
* ZwGetContextThread (NTDLL.@)
*/
NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
{
NTSTATUS ret;
SERVER_START_REQ( get_thread_context )
{
req->handle = handle;
req->flags = context->ContextFlags;
wine_server_add_data( req, context, sizeof(*context) );
wine_server_set_reply( req, context, sizeof(*context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
return ret;
}

View File

@ -503,7 +503,9 @@ struct queue_apc_request
obj_handle_t handle;
int user;
void* func;
void* param;
void* arg1;
void* arg2;
void* arg3;
};
struct queue_apc_reply
{
@ -522,7 +524,9 @@ struct get_apc_reply
struct reply_header __header;
void* func;
int type;
/* VARARG(args,ptrs); */
void* arg1;
void* arg2;
void* arg3;
};
enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC, APC_ASYNC_IO };
@ -3577,6 +3581,6 @@ union generic_reply
struct get_next_hook_reply get_next_hook_reply;
};
#define SERVER_PROTOCOL_VERSION 104
#define SERVER_PROTOCOL_VERSION 105
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -89,6 +89,12 @@ typedef struct _UNICODE_STRING {
typedef const UNICODE_STRING *PCUNICODE_STRING;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
/***********************************************************************
* Enums
*/
@ -797,6 +803,8 @@ typedef BOOLEAN (WINAPI * PWINSTATIONQUERYINFORMATIONW)(HANDLE,ULONG,WINSTATIONI
#define SERVERNAME_CURRENT ((HANDLE)NULL)
typedef void (CALLBACK *PNTAPCFUNC)(ULONG_PTR,ULONG_PTR,ULONG_PTR); /* FIXME: not the right name */
/***********************************************************************
* Function declarations
*/
@ -832,6 +840,7 @@ NTSTATUS WINAPI NtEnumerateValueKey(HKEY,ULONG,KEY_VALUE_INFORMATION_CLASS,PVOI
NTSTATUS WINAPI NtFlushKey(HKEY);
NTSTATUS WINAPI NtFlushVirtualMemory(HANDLE,LPCVOID*,ULONG*,ULONG);
NTSTATUS WINAPI NtFreeVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
NTSTATUS WINAPI NtGetContextThread(HANDLE,CONTEXT*);
NTSTATUS WINAPI NtLoadKey(const OBJECT_ATTRIBUTES *,const OBJECT_ATTRIBUTES *);
NTSTATUS WINAPI NtLockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
NTSTATUS WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,ULONG,const LARGE_INTEGER*,ULONG*,SECTION_INHERIT,ULONG,ULONG);
@ -841,9 +850,11 @@ NTSTATUS WINAPI NtOpenFile(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BL
NTSTATUS WINAPI NtOpenKey(PHKEY,ACCESS_MASK,const OBJECT_ATTRIBUTES *);
NTSTATUS WINAPI NtOpenProcessToken(HANDLE,DWORD,HANDLE *);
NTSTATUS WINAPI NtOpenSection(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*);
NTSTATUS WINAPI NtOpenThread(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const CLIENT_ID*);
NTSTATUS WINAPI NtOpenThreadToken(HANDLE,DWORD,BOOLEAN,HANDLE *);
NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG,ULONG*);
NTSTATUS WINAPI NtPulseEvent(HANDLE,PULONG);
NTSTATUS WINAPI NtQueueApcThread(HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR);
NTSTATUS WINAPI NtQueryInformationProcess(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
NTSTATUS WINAPI NtQueryInformationThread(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
NTSTATUS WINAPI NtQueryInformationToken(HANDLE,DWORD,LPVOID,DWORD,LPDWORD);
@ -857,15 +868,18 @@ NTSTATUS WINAPI NtQueryVirtualMemory(HANDLE,LPCVOID,MEMORY_INFORMATION_CLASS,PV
void WINAPI NtRaiseException(PEXCEPTION_RECORD,PCONTEXT,BOOL);
NTSTATUS WINAPI NtReadFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,PLARGE_INTEGER,PULONG);
NTSTATUS WINAPI NtReleaseSemaphore(HANDLE,ULONG,PULONG);
NTSTATUS WINAPI NtReplaceKey(POBJECT_ATTRIBUTES,HKEY,POBJECT_ATTRIBUTES);
NTSTATUS WINAPI NtResetEvent(HANDLE,PULONG);
NTSTATUS WINAPI NtRestoreKey(HKEY,HANDLE,ULONG);
NTSTATUS WINAPI NtReplaceKey(POBJECT_ATTRIBUTES,HKEY,POBJECT_ATTRIBUTES);
NTSTATUS WINAPI NtResumeThread(HANDLE,PULONG);
NTSTATUS WINAPI NtSaveKey(HKEY,HANDLE);
NTSTATUS WINAPI NtSetContextThread(HANDLE,const CONTEXT*);
NTSTATUS WINAPI NtSetEvent(HANDLE,PULONG);
NTSTATUS WINAPI NtSetInformationKey(HKEY,const int,PVOID,ULONG);
NTSTATUS WINAPI NtSetSecurityObject(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR);
NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER*,LARGE_INTEGER*);
NTSTATUS WINAPI NtSetValueKey(HKEY,const UNICODE_STRING *,ULONG,ULONG,const void *,ULONG);
NTSTATUS WINAPI NtSuspendThread(HANDLE,PULONG);
NTSTATUS WINAPI NtTerminateProcess(HANDLE,LONG);
NTSTATUS WINAPI NtTerminateThread(HANDLE,LONG);
NTSTATUS WINAPI NtUnloadKey(HKEY);

View File

@ -371,16 +371,9 @@ HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwTh
BOOL WINAPI SetThreadContext( HANDLE handle, /* [in] Handle to thread with context */
const CONTEXT *context ) /* [in] Address of context structure */
{
BOOL ret;
SERVER_START_REQ( set_thread_context )
{
req->handle = handle;
req->flags = context->ContextFlags;
wine_server_add_data( req, context, sizeof(*context) );
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
NTSTATUS status = NtSetContextThread( handle, context );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
@ -394,17 +387,9 @@ BOOL WINAPI SetThreadContext( HANDLE handle, /* [in] Handle to thread
BOOL WINAPI GetThreadContext( HANDLE handle, /* [in] Handle to thread with context */
CONTEXT *context ) /* [out] Address of context structure */
{
BOOL ret;
SERVER_START_REQ( get_thread_context )
{
req->handle = handle;
req->flags = context->ContextFlags;
wine_server_add_data( req, context, sizeof(*context) );
wine_server_set_reply( req, context, sizeof(*context) );
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
NTSTATUS status = NtGetContextThread( handle, context );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
@ -577,16 +562,16 @@ BOOL WINAPI GetExitCodeThread(
* Failure: 0xFFFFFFFF
* Already running: 0
*/
DWORD WINAPI ResumeThread(
HANDLE hthread) /* [in] Identifies thread to restart */
DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
{
DWORD ret = 0xffffffff;
SERVER_START_REQ( resume_thread )
DWORD ret;
NTSTATUS status = NtResumeThread( hthread, &ret );
if (status)
{
req->handle = hthread;
if (!wine_server_call_err( req )) ret = reply->count;
ret = ~0U;
SetLastError( RtlNtStatusToDosError(status) );
}
SERVER_END_REQ;
return ret;
}
@ -598,36 +583,36 @@ DWORD WINAPI ResumeThread(
* Success: Previous suspend count
* Failure: 0xFFFFFFFF
*/
DWORD WINAPI SuspendThread(
HANDLE hthread) /* [in] Handle to the thread */
DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
{
DWORD ret = 0xffffffff;
SERVER_START_REQ( suspend_thread )
DWORD ret;
NTSTATUS status = NtSuspendThread( hthread, &ret );
if (status)
{
req->handle = hthread;
if (!wine_server_call_err( req )) ret = reply->count;
ret = ~0U;
SetLastError( RtlNtStatusToDosError(status) );
}
SERVER_END_REQ;
return ret;
}
/* callback for QueueUserAPC */
static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
{
PAPCFUNC func = (PAPCFUNC)arg1;
func( arg2 );
}
/***********************************************************************
* QueueUserAPC (KERNEL32.@)
*/
DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
{
DWORD ret;
SERVER_START_REQ( queue_apc )
{
req->handle = hthread;
req->user = 1;
req->func = func;
req->param = (void *)data;
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}

View File

@ -65,7 +65,8 @@ void async_notify(struct async *async, int status)
{
/* fprintf(stderr,"notifying %p!\n",async->overlapped); */
async->status = status;
thread_queue_apc(async->thread, NULL, NULL, APC_ASYNC_IO, 1, 2, async->overlapped, status);
thread_queue_apc(async->thread, NULL, NULL, APC_ASYNC_IO, 1,
async->overlapped, (void *)status, NULL );
}
void destroy_async_queue( struct async_queue *q )

View File

@ -151,8 +151,8 @@ static void notify_waiter( struct pipe_user *user, unsigned int status)
if(user->thread && user->func && user->overlapped)
{
/* queue a system APC, to notify a waiting thread */
thread_queue_apc(user->thread,NULL,user->func,
APC_ASYNC,1,2,user->overlapped,status);
thread_queue_apc(user->thread, NULL, user->func, APC_ASYNC, 1,
user->overlapped, (void *)status, NULL);
}
if (user->thread) release_object(user->thread);
user->thread = NULL;
@ -426,7 +426,7 @@ DECL_HANDLER(wait_named_pipe)
/* this should use notify_waiter,
but no pipe_user object exists now... */
thread_queue_apc(current,NULL,req->func,
APC_ASYNC,1,2,req->overlapped,STATUS_SUCCESS);
APC_ASYNC, 1, req->overlapped, STATUS_SUCCESS, NULL);
release_object(partner);
}
else

View File

@ -417,7 +417,9 @@ typedef struct
obj_handle_t handle; /* thread handle */
int user; /* user or system apc? */
void* func; /* function to call */
void* param; /* param for function to call */
void* arg1; /* params for function to call */
void* arg2;
void* arg3;
@END
@ -427,7 +429,9 @@ typedef struct
@REPLY
void* func; /* function to call */
int type; /* function type */
VARARG(args,ptrs); /* function arguments */
void* arg1; /* function arguments */
void* arg2;
void* arg3;
@END
enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC, APC_ASYNC_IO };

View File

@ -67,7 +67,9 @@ struct thread_apc
void *func; /* function to call in client */
enum apc_type type; /* type of apc function */
int nb_args; /* number of arguments */
void *args[1]; /* function arguments */
void *arg1; /* function arguments */
void *arg2;
void *arg3;
};
@ -580,7 +582,7 @@ void wake_up( struct object *obj, int max )
/* queue an async procedure call */
int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
enum apc_type type, int system, int nb_args, ... )
enum apc_type type, int system, void *arg1, void *arg2, void *arg3 )
{
struct thread_apc *apc;
struct apc_queue *queue = system ? &thread->system_apc : &thread->user_apc;
@ -589,21 +591,15 @@ int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
if (owner) thread_cancel_apc( thread, owner, system );
if (thread->state == TERMINATED) return 0;
if (!(apc = mem_alloc( sizeof(*apc) + (nb_args-1)*sizeof(apc->args[0]) ))) return 0;
apc->prev = queue->tail;
apc->next = NULL;
apc->owner = owner;
apc->func = func;
apc->type = type;
apc->nb_args = nb_args;
if (nb_args)
{
int i;
va_list args;
va_start( args, nb_args );
for (i = 0; i < nb_args; i++) apc->args[i] = va_arg( args, void * );
va_end( args );
}
if (!(apc = mem_alloc( sizeof(*apc) ))) return 0;
apc->prev = queue->tail;
apc->next = NULL;
apc->owner = owner;
apc->func = func;
apc->type = type;
apc->arg1 = arg1;
apc->arg2 = arg2;
apc->arg3 = arg3;
queue->tail = apc;
if (!apc->prev) /* first one */
{
@ -972,7 +968,8 @@ DECL_HANDLER(queue_apc)
struct thread *thread;
if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
{
thread_queue_apc( thread, NULL, req->func, APC_USER, !req->user, 1, req->param );
thread_queue_apc( thread, NULL, req->func, APC_USER, !req->user,
req->arg1, req->arg2, req->arg3 );
release_object( thread );
}
}
@ -981,7 +978,6 @@ DECL_HANDLER(queue_apc)
DECL_HANDLER(get_apc)
{
struct thread_apc *apc;
size_t size;
for (;;)
{
@ -999,11 +995,11 @@ DECL_HANDLER(get_apc)
if (apc->func || apc->type == APC_ASYNC_IO) break;
free( apc );
}
size = apc->nb_args * sizeof(apc->args[0]);
if (size > get_reply_max_size()) size = get_reply_max_size();
reply->func = apc->func;
reply->type = apc->type;
set_reply_data( apc->args, size );
reply->arg1 = apc->arg1;
reply->arg2 = apc->arg2;
reply->arg3 = apc->arg3;
free( apc );
}

View File

@ -118,7 +118,7 @@ extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
extern void kill_thread( struct thread *thread, int violent_death );
extern void wake_up( struct object *obj, int max );
extern int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
enum apc_type type, int system, int nb_args, ... );
enum apc_type type, int system, void *arg1, void *arg2, void *arg3 );
extern void thread_cancel_apc( struct thread *thread, struct object *owner, int system );
extern int thread_add_inflight_fd( struct thread *thread, int client, int server );
extern int thread_get_inflight_fd( struct thread *thread, int client );

View File

@ -94,7 +94,7 @@ static void timer_callback( void *private )
/* queue an APC */
if (timer->thread)
{
if (!thread_queue_apc( timer->thread, &timer->obj, timer->callback, APC_TIMER, 0, 3,
if (!thread_queue_apc( timer->thread, &timer->obj, timer->callback, APC_TIMER, 0,
(void *)timer->when.tv_sec, (void *)timer->when.tv_usec, timer->arg))
{
release_object( timer->thread );

View File

@ -157,21 +157,6 @@ static void dump_varargs_handles( size_t size )
remove_data( size );
}
static void dump_varargs_ptrs( size_t size )
{
void * const *data = cur_data;
size_t len = size / sizeof(*data);
fputc( '{', stderr );
while (len > 0)
{
fprintf( stderr, "%p", *data++ );
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
remove_data( size );
}
static void dump_varargs_user_handles( size_t size )
{
const user_handle_t *data = cur_data;
@ -623,7 +608,9 @@ static void dump_queue_apc_request( const struct queue_apc_request *req )
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " user=%d,", req->user );
fprintf( stderr, " func=%p,", req->func );
fprintf( stderr, " param=%p", req->param );
fprintf( stderr, " arg1=%p,", req->arg1 );
fprintf( stderr, " arg2=%p,", req->arg2 );
fprintf( stderr, " arg3=%p", req->arg3 );
}
static void dump_get_apc_request( const struct get_apc_request *req )
@ -635,8 +622,9 @@ static void dump_get_apc_reply( const struct get_apc_reply *req )
{
fprintf( stderr, " func=%p,", req->func );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " args=" );
dump_varargs_ptrs( cur_size );
fprintf( stderr, " arg1=%p,", req->arg1 );
fprintf( stderr, " arg2=%p,", req->arg2 );
fprintf( stderr, " arg3=%p", req->arg3 );
}
static void dump_close_handle_request( const struct close_handle_request *req )