diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 4c2aa2ef53e..5b039caf6cb 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -68,52 +68,6 @@ typedef struct LpcMessage BYTE MessageData[MAX_MESSAGE_DATA]; } 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 */ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 5919aafddc1..b54ba82f750 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -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 diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index e0950f1487f..392956db1df 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1,8 +1,10 @@ /* * 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 * diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index e8365bcda56..ad3104c0de6 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -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 */ diff --git a/include/winternl.h b/include/winternl.h index 1f01f185612..831398d1a0a 100644 --- a/include/winternl.h +++ b/include/winternl.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); diff --git a/scheduler/timer.c b/scheduler/timer.c index 6ed81a0c3ca..a2d52ddd736 100644 --- a/scheduler/timer.c +++ b/scheduler/timer.c @@ -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; + SetLastError( RtlNtStatusToDosError(status) ); + return NULL; } - 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; - } - 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) + 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) { - SetLastError( ERROR_FILENAME_EXCED_RANGE ); - return 0; + SetLastError( RtlNtStatusToDosError(status) ); + return NULL; } - SERVER_START_REQ( open_timer ) - { - req->access = access; - req->inherit = inherit; - wine_server_add_data( req, name, len * sizeof(WCHAR) ); - wine_server_call_err( req ); - ret = reply->handle; - } - 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); diff --git a/server/protocol.def b/server/protocol.def index 75438fd8a8a..446f781372b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -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 diff --git a/server/timer.c b/server/timer.c index 2db86067af2..bc7eb4598b6 100644 --- a/server/timer.c +++ b/server/timer.c @@ -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 ); } } diff --git a/server/trace.c b/server/trace.c index d45dc53f63a..de191dc7ab4 100644 --- a/server/trace.c +++ b/server/trace.c @@ -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,