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:
parent
c7bebba198
commit
088bcf9ca5
|
@ -93,6 +93,7 @@ C_SRCS = \
|
|||
signal_powerpc.c \
|
||||
signal_sparc.c \
|
||||
sync.c \
|
||||
thread.c \
|
||||
virtual.c \
|
||||
time.c \
|
||||
wcstring.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.@]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue