From 088bcf9ca5a00ffb6adfe6a1a0da6a3b3be5e9dc Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 4 Apr 2003 22:26:34 +0000 Subject: [PATCH] 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. --- dlls/ntdll/Makefile.in | 1 + dlls/ntdll/nt.c | 42 -------- dlls/ntdll/ntdll.spec | 18 ++-- dlls/ntdll/signal_i386.c | 4 +- dlls/ntdll/sync.c | 27 +++--- dlls/ntdll/thread.c | 171 +++++++++++++++++++++++++++++++++ include/wine/server_protocol.h | 10 +- include/winternl.h | 16 ++- scheduler/thread.c | 77 ++++++--------- server/async.c | 3 +- server/named_pipe.c | 6 +- server/protocol.def | 8 +- server/thread.c | 40 ++++---- server/thread.h | 2 +- server/timer.c | 2 +- server/trace.c | 24 ++--- 16 files changed, 286 insertions(+), 165 deletions(-) create mode 100644 dlls/ntdll/thread.c diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 3f60cc2b53..5353280e49 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -93,6 +93,7 @@ C_SRCS = \ signal_powerpc.c \ signal_sparc.c \ sync.c \ + thread.c \ virtual.c \ time.c \ wcstring.c diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 0e22ed294f..a633330d06 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -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.@] diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 8fc7164113..71532927ee 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -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 diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 1ddf6f755f..4823673486 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -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); } } diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 1662d738e7..e0950f1487 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -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 ); diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c new file mode 100644 index 0000000000..0978cd3a02 --- /dev/null +++ b/dlls/ntdll/thread.c @@ -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; +} diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 0a5ef3427c..36accfb8d6 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -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 */ diff --git a/include/winternl.h b/include/winternl.h index a399e481cf..e0ae837359 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -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); diff --git a/scheduler/thread.c b/scheduler/thread.c index 7cdd8df554..6d5ad887ba 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -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; } diff --git a/server/async.c b/server/async.c index 039833e1b2..338f0d1e4f 100644 --- a/server/async.c +++ b/server/async.c @@ -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 ) diff --git a/server/named_pipe.c b/server/named_pipe.c index 05cdda78de..984c575d0b 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -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 diff --git a/server/protocol.def b/server/protocol.def index b27788b4f4..90565f8714 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -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 }; diff --git a/server/thread.c b/server/thread.c index ad310c9dc5..c6ef4acec4 100644 --- a/server/thread.c +++ b/server/thread.c @@ -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 ); } diff --git a/server/thread.h b/server/thread.h index f30ef4c86c..b0fa9c3a81 100644 --- a/server/thread.h +++ b/server/thread.h @@ -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 ); diff --git a/server/timer.c b/server/timer.c index 85cf0801d8..2db86067af 100644 --- a/server/timer.c +++ b/server/timer.c @@ -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 ); diff --git a/server/trace.c b/server/trace.c index 9f466158cc..93b3de829f 100644 --- a/server/trace.c +++ b/server/trace.c @@ -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 ) -- 2.32.0.93.g670b81a890