ntdll: Implement [Rtl]Create/DeleteTimerQueue[Ex].
This commit is contained in:
parent
09f4ca64e2
commit
20a1ca2bbf
|
@ -1047,9 +1047,16 @@ BOOL WINAPI CancelWaitableTimer( HANDLE handle )
|
|||
*/
|
||||
HANDLE WINAPI CreateTimerQueue(void)
|
||||
{
|
||||
FIXME("stub\n");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return NULL;
|
||||
HANDLE q;
|
||||
NTSTATUS status = RtlCreateTimerQueue(&q);
|
||||
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
SetLastError( RtlNtStatusToDosError(status) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1058,9 +1065,15 @@ HANDLE WINAPI CreateTimerQueue(void)
|
|||
*/
|
||||
BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
|
||||
{
|
||||
FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
NTSTATUS status = RtlDeleteTimerQueueEx(TimerQueue, CompletionEvent);
|
||||
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
SetLastError( RtlNtStatusToDosError(status) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -605,18 +605,15 @@ static void test_timer_queue(void)
|
|||
|
||||
/* Test asynchronous deletion of the queue. */
|
||||
q = pCreateTimerQueue();
|
||||
todo_wine
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueEx(q, NULL);
|
||||
ok(!ret, "DeleteTimerQueueEx\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
|
||||
|
||||
/* Test synchronous deletion of the queue and running timers. */
|
||||
q = pCreateTimerQueue();
|
||||
todo_wine
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
/* Called once. */
|
||||
|
@ -668,9 +665,9 @@ static void test_timer_queue(void)
|
|||
Sleep(500);
|
||||
|
||||
ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueEx\n");
|
||||
todo_wine
|
||||
{
|
||||
ok(ret, "DeleteTimerQueueEx\n");
|
||||
ok(n1 == 1, "Timer callback 1\n");
|
||||
ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
|
||||
}
|
||||
|
@ -687,23 +684,18 @@ static void test_timer_queue(void)
|
|||
}
|
||||
|
||||
q = pCreateTimerQueue();
|
||||
todo_wine
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueEx(q, e);
|
||||
ok(!ret, "DeleteTimerQueueEx\n");
|
||||
todo_wine
|
||||
{
|
||||
ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
|
||||
ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
|
||||
"Timer destruction event not triggered\n");
|
||||
}
|
||||
CloseHandle(e);
|
||||
|
||||
/* Test deleting/changing a timer in execution. */
|
||||
q = pCreateTimerQueue();
|
||||
todo_wine
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
d2.t = t2 = NULL;
|
||||
|
@ -731,9 +723,9 @@ static void test_timer_queue(void)
|
|||
Sleep(200);
|
||||
|
||||
ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueEx\n");
|
||||
todo_wine
|
||||
{
|
||||
ok(ret, "DeleteTimerQueueEx\n");
|
||||
ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
|
||||
ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
|
||||
}
|
||||
|
|
|
@ -489,7 +489,7 @@
|
|||
# @ stub RtlCreateSystemVolumeInformationFolder
|
||||
@ stub RtlCreateTagHeap
|
||||
# @ stub RtlCreateTimer
|
||||
# @ stub RtlCreateTimerQueue
|
||||
@ stdcall RtlCreateTimerQueue(ptr)
|
||||
@ stdcall RtlCreateUnicodeString(ptr wstr)
|
||||
@ stdcall RtlCreateUnicodeStringFromAsciiz(ptr str)
|
||||
@ stub RtlCreateUserProcess
|
||||
|
@ -520,7 +520,7 @@
|
|||
@ stdcall RtlDeleteSecurityObject(ptr)
|
||||
# @ stub RtlDeleteTimer
|
||||
# @ stub RtlDeleteTimerQueue
|
||||
# @ stub RtlDeleteTimerQueueEx
|
||||
@ stdcall RtlDeleteTimerQueueEx(ptr ptr)
|
||||
@ stdcall RtlDeregisterWait(ptr)
|
||||
@ stdcall RtlDeregisterWaitEx(ptr ptr)
|
||||
@ stdcall RtlDestroyAtomTable(ptr)
|
||||
|
|
|
@ -528,3 +528,75 @@ NTSTATUS WINAPI RtlDeregisterWait(HANDLE WaitHandle)
|
|||
{
|
||||
return RtlDeregisterWaitEx(WaitHandle, NULL);
|
||||
}
|
||||
|
||||
|
||||
/************************** Timer Queue Impl **************************/
|
||||
|
||||
struct queue_timer
|
||||
{
|
||||
struct list entry;
|
||||
};
|
||||
|
||||
struct timer_queue
|
||||
{
|
||||
RTL_CRITICAL_SECTION cs;
|
||||
struct list timers;
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* RtlCreateTimerQueue (NTDLL.@)
|
||||
*
|
||||
* Creates a timer queue object and returns a handle to it.
|
||||
*
|
||||
* PARAMS
|
||||
* NewTimerQueue [O] The newly created queue.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: STATUS_SUCCESS.
|
||||
* Failure: Any NTSTATUS code.
|
||||
*/
|
||||
NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue)
|
||||
{
|
||||
struct timer_queue *q = RtlAllocateHeap(GetProcessHeap(), 0, sizeof *q);
|
||||
if (!q)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
RtlInitializeCriticalSection(&q->cs);
|
||||
list_init(&q->timers);
|
||||
|
||||
*NewTimerQueue = q;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlDeleteTimerQueueEx (NTDLL.@)
|
||||
*
|
||||
* Deletes a timer queue object.
|
||||
*
|
||||
* PARAMS
|
||||
* TimerQueue [I] The timer queue to destroy.
|
||||
* CompletionEvent [I] If NULL, return immediately. If INVALID_HANDLE_VALUE,
|
||||
* wait until all timers are finished firing before
|
||||
* returning. Otherwise, return immediately and set the
|
||||
* event when all timers are done.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: STATUS_SUCCESS if synchronous, STATUS_PENDING if not.
|
||||
* Failure: Any NTSTATUS code.
|
||||
*/
|
||||
NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
|
||||
{
|
||||
struct timer_queue *q = TimerQueue;
|
||||
|
||||
RtlDeleteCriticalSection(&q->cs);
|
||||
RtlFreeHeap(GetProcessHeap(), 0, q);
|
||||
|
||||
if (CompletionEvent == INVALID_HANDLE_VALUE)
|
||||
return STATUS_SUCCESS;
|
||||
else
|
||||
{
|
||||
if (CompletionEvent)
|
||||
NtSetEvent(CompletionEvent, NULL);
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2117,6 +2117,7 @@ NTSYSAPI NTSTATUS WINAPI RtlCreateEnvironment(BOOLEAN, PWSTR*);
|
|||
NTSYSAPI HANDLE WINAPI RtlCreateHeap(ULONG,PVOID,SIZE_T,SIZE_T,PVOID,PRTL_HEAP_DEFINITION);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlCreateProcessParameters(RTL_USER_PROCESS_PARAMETERS**,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,PWSTR,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR,DWORD);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE);
|
||||
NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR);
|
||||
NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlCreateUserThread(HANDLE,const SECURITY_DESCRIPTOR*,BOOLEAN,PVOID,SIZE_T,SIZE_T,PRTL_THREAD_START_ROUTINE,void*,HANDLE*,CLIENT_ID*);
|
||||
|
@ -2127,6 +2128,7 @@ NTSYSAPI NTSTATUS WINAPI RtlDeleteCriticalSection(RTL_CRITICAL_SECTION *);
|
|||
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR);
|
||||
NTSYSAPI void WINAPI RtlDeleteResource(LPRTL_RWLOCK);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDeleteSecurityObject(PSECURITY_DESCRIPTOR*);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE, HANDLE);
|
||||
NTSYSAPI PRTL_USER_PROCESS_PARAMETERS WINAPI RtlDeNormalizeProcessParams(RTL_USER_PROCESS_PARAMETERS*);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDeregisterWait(HANDLE);
|
||||
NTSYSAPI NTSTATUS WINAPI RtlDeregisterWaitEx(HANDLE,HANDLE);
|
||||
|
|
Loading…
Reference in New Issue