Commit 4c591d4e authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

Implemented timer related functions in ntdll and make the kernel32

functions use them.
parent 11c15966
......@@ -69,52 +69,6 @@ typedef struct LpcMessage
} LPCMESSAGE, *PLPCMESSAGE;
/*
* Timer object
*/
/**************************************************************************
* NtCreateTimer [NTDLL.@]
* ZwCreateTimer [NTDLL.@]
*/
NTSTATUS WINAPI NtCreateTimer(
OUT PHANDLE TimerHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN TIMER_TYPE TimerType)
{
FIXME("(%p,0x%08lx,%p,0x%08x) stub\n",
TimerHandle,DesiredAccess,ObjectAttributes, TimerType);
dump_ObjectAttributes(ObjectAttributes);
return 0;
}
/**************************************************************************
* NtSetTimer [NTDLL.@]
* ZwSetTimer [NTDLL.@]
*/
NTSTATUS WINAPI NtSetTimer(
IN HANDLE TimerHandle,
IN PLARGE_INTEGER DueTime,
IN PTIMERAPCROUTINE TimerApcRoutine,
IN PVOID TimerContext,
IN BOOLEAN WakeTimer,
IN ULONG Period OPTIONAL,
OUT PBOOLEAN PreviousState OPTIONAL)
{
FIXME("(%p,%p,%p,%p,%08x,0x%08lx,%p) stub\n",
TimerHandle,DueTime,TimerApcRoutine,TimerContext,WakeTimer,Period,PreviousState);
return 0;
}
/******************************************************************************
* NtQueryTimerResolution [NTDLL.@]
*/
NTSTATUS WINAPI NtQueryTimerResolution(DWORD x1,DWORD x2,DWORD x3)
{
FIXME("(0x%08lx,0x%08lx,0x%08lx), stub!\n",x1,x2,x3);
return 1;
}
/*
* Process object
*/
......
......@@ -68,7 +68,7 @@
@ stdcall NtAllocateVirtualMemory(long ptr ptr ptr long long)
@ stub NtCallbackReturn
@ stub NtCancelIoFile
@ stub NtCancelTimer
@ stdcall NtCancelTimer(long ptr)
@ stdcall NtClearEvent(long)
@ stdcall NtClose(long)
@ stub NtCloseObjectAuditAlarm
......@@ -144,7 +144,7 @@
@ stdcall NtOpenSymbolicLinkObject (long long long)
@ stdcall NtOpenThread(ptr long ptr ptr)
@ stdcall NtOpenThreadToken(long long long long)
@ stub NtOpenTimer
@ stdcall NtOpenTimer(ptr long ptr)
@ stub NtPlugPlayControl
@ stub NtPrivilegeCheck
@ stub NtPrivilegeObjectAuditAlarm
......@@ -231,7 +231,7 @@
@ stub NtSetSystemPowerState
@ stdcall NtSetSystemTime(ptr ptr)
@ stdcall NtSetTimer(long ptr ptr ptr long long ptr)
@ stub NtSetTimerResolution
@ stdcall NtSetTimerResolution(long long ptr)
@ stdcall NtSetValueKey(long long long long long long)
@ stdcall NtSetVolumeInformationFile(long ptr ptr long long)
@ stub NtShutdownSystem
......@@ -599,7 +599,7 @@
@ stdcall ZwAllocateVirtualMemory(long ptr ptr ptr long long) NtAllocateVirtualMemory
@ stub ZwCallbackReturn
@ stub ZwCancelIoFile
@ stub ZwCancelTimer
@ stdcall ZwCancelTimer(long ptr) NtCancelTimer
@ stdcall ZwClearEvent(long) NtClearEvent
@ stdcall ZwClose(long) NtClose
@ stub ZwCloseObjectAuditAlarm
......@@ -674,7 +674,7 @@
@ stdcall ZwOpenSymbolicLinkObject (long long long) NtOpenSymbolicLinkObject
@ stdcall ZwOpenThread(ptr long ptr ptr) NtOpenThread
@ stdcall ZwOpenThreadToken(long long long long) NtOpenThreadToken
@ stub ZwOpenTimer
@ stdcall ZwOpenTimer(ptr long ptr) NtOpenTimer
@ stub ZwPlugPlayControl
@ stub ZwPrivilegeCheck
@ stub ZwPrivilegeObjectAuditAlarm
......@@ -758,7 +758,7 @@
@ stub ZwSetSystemPowerState
@ stdcall ZwSetSystemTime(ptr ptr) NtSetSystemTime
@ stdcall ZwSetTimer(long ptr ptr ptr long long ptr) NtSetTimer
@ stub ZwSetTimerResolution
@ stdcall ZwSetTimerResolution(long long) NtSetTimerResolution
@ stdcall ZwSetValueKey(long long long long long long) NtSetValueKey
@ stdcall ZwSetVolumeInformationFile(long ptr ptr long long) NtSetVolumeInformationFile
@ stub ZwShutdownSystem
......
/*
* Process synchronisation
*
* Copyright 1997 Alexandre Julliard
* Copyright 1996, 1997, 1998 Marcus Meissner
* Copyright 1997, 1999 Alexandre Julliard
* Copyright 1999, 2000 Juergen Schmied
* Copyright 2003 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -282,6 +284,150 @@ NTSTATUS WINAPI NtQueryEvent (
}
/*
* Timers
*/
/**************************************************************************
* NtCreateTimer [NTDLL.@]
* ZwCreateTimer [NTDLL.@]
*/
NTSTATUS WINAPI NtCreateTimer(OUT HANDLE *handle,
IN ACCESS_MASK access,
IN const OBJECT_ATTRIBUTES *oa OPTIONAL,
IN TIMER_TYPE timer_type)
{
NTSTATUS status;
if (timer_type != NotificationTimer && timer_type != SynchronizationTimer)
return STATUS_INVALID_PARAMETER;
SERVER_START_REQ( create_timer )
{
req->manual = (timer_type == NotificationTimer) ? TRUE : FALSE;
req->inherit = oa && (oa->Attributes & OBJ_INHERIT);
if (oa && oa->ObjectName->Length)
wine_server_add_data( req, oa->ObjectName->Buffer, oa->ObjectName->Length );
status = wine_server_call( req );
*handle = reply->handle;
}
SERVER_END_REQ;
return status;
}
/**************************************************************************
* NtOpenTimer [NTDLL.@]
* ZwOpenTimer [NTDLL.@]
*/
NTSTATUS WINAPI NtOpenTimer(OUT PHANDLE handle,
IN ACCESS_MASK access,
IN const OBJECT_ATTRIBUTES* oa )
{
NTSTATUS status;
if (oa && oa->Length >= MAX_PATH * sizeof(WCHAR))
return STATUS_NAME_TOO_LONG;
SERVER_START_REQ( open_timer )
{
req->access = access;
req->inherit = oa && (oa->Attributes & OBJ_INHERIT);
if (oa && oa->ObjectName->Length)
wine_server_add_data( req, oa->ObjectName->Buffer, oa->ObjectName->Length );
status = wine_server_call( req );
*handle = reply->handle;
}
SERVER_END_REQ;
return status;
}
/**************************************************************************
* NtSetTimer [NTDLL.@]
* ZwSetTimer [NTDLL.@]
*/
NTSTATUS WINAPI NtSetTimer(IN HANDLE handle,
IN const LARGE_INTEGER* when,
IN PTIMERAPCROUTINE callback,
IN PVOID callback_arg,
IN BOOLEAN resume,
IN ULONG period OPTIONAL,
OUT PBOOLEAN state OPTIONAL)
{
NTSTATUS status = STATUS_SUCCESS;
TRACE("(%p,%p,%p,%p,%08x,0x%08lx,%p) stub\n",
handle, when, callback, callback_arg, resume, period, state);
SERVER_START_REQ( set_timer )
{
if (!when->s.LowPart && !when->s.HighPart)
{
/* special case to start timeout on now+period without too many calculations */
req->expire.sec = 0;
req->expire.usec = 0;
}
else NTDLL_get_server_timeout( &req->expire, when );
req->handle = handle;
req->period = period;
req->callback = callback;
req->arg = callback_arg;
status = wine_server_call( req );
if (state) *state = reply->signaled;
}
SERVER_END_REQ;
/* set error but can still succeed */
if (resume && status == STATUS_SUCCESS) return STATUS_TIMER_RESUME_IGNORED;
return status;
}
/**************************************************************************
* NtCancelTimer [NTDLL.@]
* ZwCancelTimer [NTDLL.@]
*/
NTSTATUS WINAPI NtCancelTimer(IN HANDLE handle, OUT BOOLEAN* state)
{
NTSTATUS status;
SERVER_START_REQ( cancel_timer )
{
req->handle = handle;
status = wine_server_call( req );
if (state) *state = reply->signaled;
}
SERVER_END_REQ;
return status;
}
/******************************************************************************
* NtQueryTimerResolution [NTDLL.@]
*/
NTSTATUS WINAPI NtQueryTimerResolution(OUT ULONG* min_resolution,
OUT ULONG* max_resolution,
OUT ULONG* current_resolution)
{
FIXME("(%p,%p,%p), stub!\n",
min_resolution, max_resolution, current_resolution);
return STATUS_NOT_IMPLEMENTED;
}
/******************************************************************************
* NtSetTimerResolution [NTDLL.@]
*/
NTSTATUS WINAPI NtSetTimerResolution(IN ULONG resolution,
IN BOOLEAN set_resolution,
OUT ULONG* current_resolution )
{
FIXME("(%lu,%u,%p), stub!\n",
resolution, set_resolution, current_resolution);
return STATUS_NOT_IMPLEMENTED;
}
/***********************************************************************
* check_async_list
*
......
......@@ -2013,6 +2013,7 @@ struct set_timer_request
struct set_timer_reply
{
struct reply_header __header;
int signaled;
};
......@@ -2024,6 +2025,7 @@ struct cancel_timer_request
struct cancel_timer_reply
{
struct reply_header __header;
int signaled;
};
......@@ -3583,6 +3585,6 @@ union generic_reply
struct get_next_hook_reply get_next_hook_reply;
};
#define SERVER_PROTOCOL_VERSION 106
#define SERVER_PROTOCOL_VERSION 107
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -855,6 +855,7 @@ void WINAPI LdrShutdownThread(void);
NTSTATUS WINAPI NtAccessCheck(PSECURITY_DESCRIPTOR,HANDLE,ACCESS_MASK,PGENERIC_MAPPING,PPRIVILEGE_SET,PULONG,PULONG,PBOOLEAN);
NTSTATUS WINAPI NtAdjustPrivilegesToken(HANDLE,BOOLEAN,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,PVOID,ULONG*,ULONG,ULONG);
NTSTATUS WINAPI NtCancelTimer(HANDLE, BOOLEAN*);
NTSTATUS WINAPI NtClearEvent(HANDLE);
NTSTATUS WINAPI NtClose(HANDLE);
NTSTATUS WINAPI NtCreateEvent(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES *,BOOLEAN,BOOLEAN);
......@@ -862,6 +863,7 @@ NTSTATUS WINAPI NtCreateFile(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_
NTSTATUS WINAPI NtCreateKey(PHKEY,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,const UNICODE_STRING*,ULONG,PULONG);
NTSTATUS WINAPI NtCreateSection(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE);
NTSTATUS WINAPI NtCreateSemaphore(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,ULONG);
NTSTATUS WINAPI NtCreateTimer(HANDLE*, ACCESS_MASK, const OBJECT_ATTRIBUTES*, TIMER_TYPE);
NTSTATUS WINAPI NtDeleteKey(HKEY);
NTSTATUS WINAPI NtDeleteValueKey(HKEY,const UNICODE_STRING *);
NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,PVOID,ULONG,PVOID,ULONG);
......@@ -884,6 +886,7 @@ 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 NtOpenTimer(HANDLE*, ACCESS_MASK, const OBJECT_ATTRIBUTES*);
NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG,ULONG*);
NTSTATUS WINAPI NtPulseEvent(HANDLE,PULONG);
NTSTATUS WINAPI NtQueueApcThread(HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR);
......@@ -912,6 +915,7 @@ 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 NtSetTimer(HANDLE, const LARGE_INTEGER*, PTIMERAPCROUTINE, PVOID, BOOLEAN, ULONG, BOOLEAN*);
NTSTATUS WINAPI NtSetValueKey(HKEY,const UNICODE_STRING *,ULONG,ULONG,const void *,ULONG);
NTSTATUS WINAPI NtSuspendThread(HANDLE,PULONG);
NTSTATUS WINAPI NtTerminateProcess(HANDLE,LONG);
......
......@@ -59,24 +59,26 @@ HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR
*/
HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
{
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
if (len >= MAX_PATH)
HANDLE handle;
NTSTATUS status;
UNICODE_STRING us;
DWORD attr = 0;
OBJECT_ATTRIBUTES oa;
if (name) RtlInitUnicodeString(&us, name);
if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
attr |= OBJ_INHERIT;
InitializeObjectAttributes(&oa, name ? &us : NULL, attr,
NULL /* FIXME */, NULL /* FIXME */);
status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &oa,
manual ? NotificationTimer : SynchronizationTimer);
if (status != STATUS_SUCCESS)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_REQ( create_timer )
{
req->manual = manual;
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
wine_server_add_data( req, name, len * sizeof(WCHAR) );
SetLastError(0);
wine_server_call_err( req );
ret = reply->handle;
SetLastError( RtlNtStatusToDosError(status) );
return NULL;
}
SERVER_END_REQ;
return ret;
return handle;
}
......@@ -103,23 +105,23 @@ HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
*/
HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
{
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_REQ( open_timer )
NTSTATUS status;
ULONG attr = 0;
UNICODE_STRING us;
HANDLE handle;
OBJECT_ATTRIBUTES oa;
if (inherit) attr |= OBJ_INHERIT;
if (name) RtlInitUnicodeString(&us, name);
InitializeObjectAttributes(&oa, name ? &us : NULL, attr, NULL /* FIXME */, NULL /* FIXME */);
status = NtOpenTimer(&handle, access, &oa);
if (status != STATUS_SUCCESS)
{
req->access = access;
req->inherit = inherit;
wine_server_add_data( req, name, len * sizeof(WCHAR) );
wine_server_call_err( req );
ret = reply->handle;
SetLastError( RtlNtStatusToDosError(status) );
return NULL;
}
SERVER_END_REQ;
return ret;
return handle;
}
......@@ -129,27 +131,15 @@ HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
{
BOOL ret;
SERVER_START_REQ( set_timer )
NTSTATUS status;
status = NtSetTimer(handle, when, callback, arg, resume, period, NULL);
if (status != STATUS_SUCCESS)
{
if (!when->s.LowPart && !when->s.HighPart)
{
/* special case to start timeout on now+period without too many calculations */
req->expire.sec = 0;
req->expire.usec = 0;
}
else NTDLL_get_server_timeout( &req->expire, when );
req->handle = handle;
req->period = period;
req->callback = callback;
req->arg = arg;
if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
ret = !wine_server_call_err( req );
SetLastError( RtlNtStatusToDosError(status) );
if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
}
SERVER_END_REQ;
return ret;
return TRUE;
}
......@@ -158,21 +148,22 @@ BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG per
*/
BOOL WINAPI CancelWaitableTimer( HANDLE handle )
{
BOOL ret;
SERVER_START_REQ( cancel_timer )
NTSTATUS status;
status = NtCancelTimer(handle, NULL);
if (status != STATUS_SUCCESS)
{
req->handle = handle;
ret = !wine_server_call_err( req );
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
SERVER_END_REQ;
return ret;
return TRUE;
}
/***********************************************************************
* CreateTimerQueue (KERNEL32.@)
*/
HANDLE WINAPI CreateTimerQueue()
HANDLE WINAPI CreateTimerQueue(void)
{
FIXME("stub\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
......
......@@ -1442,11 +1442,15 @@ enum char_info_mode
int period; /* timer period in ms */
void* callback; /* callback function */
void* arg; /* callback argument */
@REPLY
int signaled; /* was the timer signaled before this call ? */
@END
/* Cancel a waitable timer */
@REQ(cancel_timer)
obj_handle_t handle; /* handle to the timer */
@REPLY
int signaled; /* was the timer signaled before this calltime ? */
@END
......
......@@ -115,8 +115,10 @@ static void timer_callback( void *private )
}
/* cancel a running timer */
static void cancel_timer( struct timer *timer )
static int cancel_timer( struct timer *timer )
{
int signaled = timer->signaled;
if (timer->timeout)
{
remove_timeout_user( timer->timeout );
......@@ -128,13 +130,14 @@ static void cancel_timer( struct timer *timer )
release_object( timer->thread );
timer->thread = NULL;
}
return signaled;
}
/* set the timer expiration and period */
static void set_timer( struct timer *timer, const abs_time_t *expire, int period,
void *callback, void *arg )
static int set_timer( struct timer *timer, const abs_time_t *expire, int period,
void *callback, void *arg )
{
cancel_timer( timer );
int signaled = cancel_timer( timer );
if (timer->manual)
{
period = 0; /* period doesn't make any sense for a manual timer */
......@@ -156,6 +159,7 @@ static void set_timer( struct timer *timer, const abs_time_t *expire, int period
timer->arg = arg;
if (callback) timer->thread = (struct thread *)grab_object( current );
timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
return signaled;
}
static void timer_dump( struct object *obj, int verbose )
......@@ -220,7 +224,7 @@ DECL_HANDLER(set_timer)
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
TIMER_MODIFY_STATE, &timer_ops )))
{
set_timer( timer, &req->expire, req->period, req->callback, req->arg );
reply->signaled = set_timer( timer, &req->expire, req->period, req->callback, req->arg );
release_object( timer );
}
}
......@@ -233,7 +237,7 @@ DECL_HANDLER(cancel_timer)
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
TIMER_MODIFY_STATE, &timer_ops )))
{
cancel_timer( timer );
reply->signaled = cancel_timer( timer );
release_object( timer );
}
}
......@@ -1687,11 +1687,21 @@ static void dump_set_timer_request( const struct set_timer_request *req )
fprintf( stderr, " arg=%p", req->arg );
}
static void dump_set_timer_reply( const struct set_timer_reply *req )
{
fprintf( stderr, " signaled=%d", req->signaled );
}
static void dump_cancel_timer_request( const struct cancel_timer_request *req )
{
fprintf( stderr, " handle=%p", req->handle );
}
static void dump_cancel_timer_reply( const struct cancel_timer_reply *req )
{
fprintf( stderr, " signaled=%d", req->signaled );
}
static void dump_get_thread_context_request( const struct get_thread_context_request *req )
{
fprintf( stderr, " handle=%p,", req->handle );
......@@ -2737,8 +2747,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0,
(dump_func)dump_create_timer_reply,
(dump_func)dump_open_timer_reply,
(dump_func)0,
(dump_func)0,
(dump_func)dump_set_timer_reply,
(dump_func)dump_cancel_timer_reply,
(dump_func)dump_get_thread_context_reply,
(dump_func)0,
(dump_func)dump_get_selector_entry_reply,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment