ntdll: Implement RtlRegisterWait, RtlDeregisterWait and RtlDeregisterWaitEx.
This commit is contained in:
parent
39aa3beaf2
commit
25bc7023ba
|
@ -521,8 +521,8 @@
|
|||
# @ stub RtlDeleteTimer
|
||||
# @ stub RtlDeleteTimerQueue
|
||||
# @ stub RtlDeleteTimerQueueEx
|
||||
# @ stub RtlDeregisterWait
|
||||
# @ stub RtlDeregisterWaitEx
|
||||
@ stdcall RtlDeregisterWait(ptr)
|
||||
@ stdcall RtlDeregisterWaitEx(ptr ptr)
|
||||
@ stdcall RtlDestroyAtomTable(ptr)
|
||||
@ stdcall RtlDestroyEnvironment(ptr)
|
||||
@ stdcall RtlDestroyHandleTable(ptr)
|
||||
|
@ -793,7 +793,7 @@
|
|||
@ stub RtlRealPredecessor
|
||||
@ stub RtlRealSuccessor
|
||||
@ stub RtlRegisterSecureMemoryCacheCallback
|
||||
@ stub RtlRegisterWait
|
||||
@ stdcall RtlRegisterWait(ptr ptr ptr ptr long long)
|
||||
@ stdcall RtlReleaseActivationContext(ptr)
|
||||
@ stub RtlReleaseMemoryStream
|
||||
@ stdcall RtlReleasePebLock()
|
||||
|
|
|
@ -311,3 +311,220 @@ NTSTATUS WINAPI RtlSetIoCompletionCallback(HANDLE FileHandle, PRTL_OVERLAPPED_CO
|
|||
|
||||
return NtSetInformationFile( FileHandle, &iosb, &info, sizeof(info), FileCompletionInformation );
|
||||
}
|
||||
|
||||
static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, ULONG timeout )
|
||||
{
|
||||
if (timeout == INFINITE) return NULL;
|
||||
pTime->QuadPart = (ULONGLONG)timeout * -10000;
|
||||
return pTime;
|
||||
}
|
||||
|
||||
struct wait_work_item
|
||||
{
|
||||
HANDLE Object;
|
||||
HANDLE CancelEvent;
|
||||
WAITORTIMERCALLBACK Callback;
|
||||
PVOID Context;
|
||||
ULONG Milliseconds;
|
||||
ULONG Flags;
|
||||
HANDLE CompletionEvent;
|
||||
LONG DeleteCount;
|
||||
BOOLEAN CallbackInProgress;
|
||||
};
|
||||
|
||||
static void delete_wait_work_item(struct wait_work_item *wait_work_item)
|
||||
{
|
||||
NtClose( wait_work_item->CancelEvent );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, wait_work_item );
|
||||
}
|
||||
|
||||
static DWORD CALLBACK wait_thread_proc(LPVOID Arg)
|
||||
{
|
||||
struct wait_work_item *wait_work_item = Arg;
|
||||
NTSTATUS status;
|
||||
BOOLEAN alertable = (wait_work_item->Flags & WT_EXECUTEINIOTHREAD) ? TRUE : FALSE;
|
||||
HANDLE handles[2] = { wait_work_item->Object, wait_work_item->CancelEvent };
|
||||
LARGE_INTEGER timeout;
|
||||
HANDLE completion_event;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
status = NtWaitForMultipleObjects( 2, handles, FALSE, alertable,
|
||||
get_nt_timeout( &timeout, wait_work_item->Milliseconds ) );
|
||||
if (status == STATUS_WAIT_0 || status == STATUS_TIMEOUT)
|
||||
{
|
||||
BOOLEAN TimerOrWaitFired;
|
||||
|
||||
if (status == STATUS_WAIT_0)
|
||||
{
|
||||
TRACE( "object %p signaled, calling callback %p with context %p\n",
|
||||
wait_work_item->Object, wait_work_item->Callback,
|
||||
wait_work_item->Context );
|
||||
TimerOrWaitFired = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE( "wait for object %p timed out, calling callback %p with context %p\n",
|
||||
wait_work_item->Object, wait_work_item->Callback,
|
||||
wait_work_item->Context );
|
||||
TimerOrWaitFired = TRUE;
|
||||
}
|
||||
wait_work_item->CallbackInProgress = TRUE;
|
||||
wait_work_item->Callback( wait_work_item->Context, TimerOrWaitFired );
|
||||
wait_work_item->CallbackInProgress = FALSE;
|
||||
|
||||
if (wait_work_item->Flags & WT_EXECUTEONLYONCE)
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
completion_event = wait_work_item->CompletionEvent;
|
||||
if (completion_event) NtSetEvent( completion_event, NULL );
|
||||
|
||||
if (interlocked_inc( &wait_work_item->DeleteCount ) == 2 )
|
||||
delete_wait_work_item( wait_work_item );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlRegisterWait (NTDLL.@)
|
||||
*
|
||||
* Registers a wait for a handle to become signaled.
|
||||
*
|
||||
* PARAMS
|
||||
* NewWaitObject [I] Handle to the new wait object. Use RtlDeregisterWait() to free it.
|
||||
* Object [I] Object to wait to become signaled.
|
||||
* Callback [I] Callback function to execute when the wait times out or the handle is signaled.
|
||||
* Context [I] Context to pass to the callback function when it is executed.
|
||||
* Milliseconds [I] Number of milliseconds to wait before timing out.
|
||||
* Flags [I] Flags. See notes.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: STATUS_SUCCESS.
|
||||
* Failure: Any NTSTATUS code.
|
||||
*
|
||||
* NOTES
|
||||
* Flags can be one or more of the following:
|
||||
*|WT_EXECUTEDEFAULT - Executes the work item in a non-I/O worker thread.
|
||||
*|WT_EXECUTEINIOTHREAD - Executes the work item in an I/O worker thread.
|
||||
*|WT_EXECUTEINPERSISTENTTHREAD - Executes the work item in a thread that is persistent.
|
||||
*|WT_EXECUTELONGFUNCTION - Hints that the execution can take a long time.
|
||||
*|WT_TRANSFER_IMPERSONATION - Executes the function with the current access token.
|
||||
*/
|
||||
NTSTATUS WINAPI RtlRegisterWait(PHANDLE NewWaitObject, HANDLE Object,
|
||||
RTL_WAITORTIMERCALLBACKFUNC Callback,
|
||||
PVOID Context, ULONG Milliseconds, ULONG Flags)
|
||||
{
|
||||
struct wait_work_item *wait_work_item;
|
||||
NTSTATUS status;
|
||||
|
||||
TRACE( "(%p, %p, %p, %p, %d, 0x%x)\n", NewWaitObject, Object, Callback, Context, Milliseconds, Flags );
|
||||
|
||||
wait_work_item = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wait_work_item) );
|
||||
if (!wait_work_item)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
wait_work_item->Object = Object;
|
||||
wait_work_item->Callback = Callback;
|
||||
wait_work_item->Context = Context;
|
||||
wait_work_item->Milliseconds = Milliseconds;
|
||||
wait_work_item->Flags = Flags;
|
||||
wait_work_item->CallbackInProgress = FALSE;
|
||||
wait_work_item->DeleteCount = 0;
|
||||
wait_work_item->CompletionEvent = NULL;
|
||||
|
||||
status = NtCreateEvent( &wait_work_item->CancelEvent, EVENT_ALL_ACCESS, NULL, TRUE, FALSE );
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, wait_work_item );
|
||||
return status;
|
||||
}
|
||||
|
||||
status = RtlQueueWorkItem( wait_thread_proc, wait_work_item, Flags & ~WT_EXECUTEONLYONCE );
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
delete_wait_work_item( wait_work_item );
|
||||
return status;
|
||||
}
|
||||
|
||||
*NewWaitObject = wait_work_item;
|
||||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlDeregisterWaitEx (NTDLL.@)
|
||||
*
|
||||
* Cancels a wait operation and frees the resources associated with calling
|
||||
* RtlRegisterWait().
|
||||
*
|
||||
* PARAMS
|
||||
* WaitObject [I] Handle to the wait object to free.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: STATUS_SUCCESS.
|
||||
* Failure: Any NTSTATUS code.
|
||||
*/
|
||||
NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE WaitHandle, HANDLE CompletionEvent)
|
||||
{
|
||||
struct wait_work_item *wait_work_item = WaitHandle;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
TRACE( "(%p)\n", WaitHandle );
|
||||
|
||||
NtSetEvent( wait_work_item->CancelEvent, NULL );
|
||||
if (wait_work_item->CallbackInProgress)
|
||||
{
|
||||
if (CompletionEvent != NULL)
|
||||
{
|
||||
if (CompletionEvent == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
status = NtCreateEvent( &CompletionEvent, EVENT_ALL_ACCESS, NULL, TRUE, FALSE );
|
||||
if (status != STATUS_SUCCESS)
|
||||
return status;
|
||||
interlocked_xchg_ptr( (PVOID *)&wait_work_item->CompletionEvent, CompletionEvent );
|
||||
if (wait_work_item->CallbackInProgress)
|
||||
NtWaitForSingleObject( CompletionEvent, FALSE, NULL );
|
||||
NtClose( CompletionEvent );
|
||||
}
|
||||
else
|
||||
{
|
||||
interlocked_xchg_ptr( (PVOID *)&wait_work_item->CompletionEvent, CompletionEvent );
|
||||
if (wait_work_item->CallbackInProgress)
|
||||
status = STATUS_PENDING;
|
||||
}
|
||||
}
|
||||
else
|
||||
status = STATUS_PENDING;
|
||||
}
|
||||
|
||||
if (interlocked_inc( &wait_work_item->DeleteCount ) == 2 )
|
||||
{
|
||||
status = STATUS_SUCCESS;
|
||||
delete_wait_work_item( wait_work_item );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlDeregisterWait (NTDLL.@)
|
||||
*
|
||||
* Cancels a wait operation and frees the resources associated with calling
|
||||
* RtlRegisterWait().
|
||||
*
|
||||
* PARAMS
|
||||
* WaitObject [I] Handle to the wait object to free.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: STATUS_SUCCESS.
|
||||
* Failure: Any NTSTATUS code.
|
||||
*/
|
||||
NTSTATUS WINAPI RtlDeregisterWait(HANDLE WaitHandle)
|
||||
{
|
||||
return RtlDeregisterWaitEx(WaitHandle, NULL);
|
||||
}
|
||||
|
|
|
@ -1479,6 +1479,7 @@ typedef struct _RTL_HANDLE_TABLE
|
|||
typedef void (CALLBACK *PNTAPCFUNC)(ULONG_PTR,ULONG_PTR,ULONG_PTR); /* FIXME: not the right name */
|
||||
typedef void (CALLBACK *PRTL_THREAD_START_ROUTINE)(LPVOID); /* FIXME: not the right name */
|
||||
typedef DWORD (CALLBACK *PRTL_WORK_ITEM_ROUTINE)(LPVOID); /* FIXME: not the right name */
|
||||
typedef void (NTAPI *RTL_WAITORTIMERCALLBACKFUNC)(PVOID,BOOLEAN); /* FIXME: not the right name */
|
||||
|
||||
|
||||
/* DbgPrintEx default levels */
|
||||
|
@ -2109,6 +2110,8 @@ NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR);
|
|||
NTSYSAPI void WINAPI RtlDeleteResource(LPRTL_RWLOCK);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDeleteSecurityObject(PSECURITY_DESCRIPTOR*);
|
||||
NTSYSAPI PRTL_USER_PROCESS_PARAMETERS WINAPI RtlDeNormalizeProcessParams(RTL_USER_PROCESS_PARAMETERS*);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDeregisterWait(HANDLE);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE,HANDLE);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDestroyAtomTable(RTL_ATOM_TABLE);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDestroyEnvironment(PWSTR);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDestroyHandleTable(RTL_HANDLE_TABLE *);
|
||||
|
@ -2257,6 +2260,7 @@ NTSYSAPI void WINAPI RtlRaiseException(PEXCEPTION_RECORD);
|
|||
NTSYSAPI void WINAPI RtlRaiseStatus(NTSTATUS);
|
||||
NTSYSAPI ULONG WINAPI RtlRandom(PULONG);
|
||||
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE,ULONG,PVOID,SIZE_T);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlRegisterWait(PHANDLE,HANDLE,RTL_WAITORTIMERCALLBACKFUNC,PVOID,ULONG,ULONG);
|
||||
NTSYSAPI void WINAPI RtlReleaseActivationContext(HANDLE);
|
||||
NTSYSAPI void WINAPI RtlReleasePebLock(void);
|
||||
NTSYSAPI void WINAPI RtlReleaseResource(LPRTL_RWLOCK);
|
||||
|
|
Loading…
Reference in New Issue