Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186/* * PROJECT: ReactOS api tests * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) * PURPOSE: Tests for QueueUserAPC, SleepEx, WaitForSingleObjectEx etc. * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) */#include "precomp.h"
#define MAX_RECORD 30
static LONG s_record_count = 0;static DWORD s_record[MAX_RECORD + 1] = { 0 };static BOOL s_terminate_all = FALSE;
static const DWORD s_expected[] ={ 0, 1, 7, 8, 4, 2, 1, 9, 10, 5, 2, 1, 11, 12, 13, 6, 2, 3, 14, 15, 16};static const SIZE_T s_expected_count = _countof(s_expected);
static void AddValueToRecord(DWORD dwValue){ LONG next = InterlockedIncrement(&s_record_count) - 1; if (next < MAX_RECORD) s_record[next] = dwValue;}
static VOID CheckRecord(void){ SIZE_T i, count = min(s_record_count, s_expected_count);
for (i = 0; i < count; ++i) { ok(s_record[i] == s_expected[i], "s_record[%u]: got %lu vs expected %lu\n", (INT)i, s_record[i], s_expected[i]); }
count = abs((int)s_record_count - (int)s_expected_count); for (i = 0; i < count; ++i) { ok(s_record_count == s_expected_count, "s_record_count: got %u vs expected %u\n", (int)s_record_count, (int)s_expected_count); }}
static DWORD WINAPI ThreadFunc1(LPVOID arg){ AddValueToRecord(0); while (!s_terminate_all) { AddValueToRecord(1); ok_long(SleepEx(INFINITE, TRUE), WAIT_IO_COMPLETION); AddValueToRecord(2); } AddValueToRecord(3); return 0;}
static DWORD WINAPI ThreadFunc2(LPVOID arg){ AddValueToRecord(0); while (!s_terminate_all) { AddValueToRecord(1); ok_long(WaitForSingleObjectEx(GetCurrentThread(), INFINITE, TRUE), WAIT_IO_COMPLETION); AddValueToRecord(2); } AddValueToRecord(3); return 0;}
static VOID NTAPI DoUserAPC1(ULONG_PTR Parameter){ ok_int((int)Parameter, 1); AddValueToRecord(4);}
static VOID NTAPI DoUserAPC2(ULONG_PTR Parameter){ ok_int((int)Parameter, 2); AddValueToRecord(5);}
static VOID NTAPI DoUserAPC3(ULONG_PTR Parameter){ ok_int((int)Parameter, 3); AddValueToRecord(6); s_terminate_all = TRUE;}
static void JustDoIt(LPTHREAD_START_ROUTINE fn){ HANDLE hThread; DWORD dwThreadId;
s_terminate_all = FALSE; s_record_count = 0; ZeroMemory(s_record, sizeof(s_record));
hThread = CreateThread(NULL, 0, fn, NULL, 0, &dwThreadId); ok(hThread != NULL, "hThread was NULL\n");
Sleep(100);
AddValueToRecord(7); ok_long(QueueUserAPC(DoUserAPC1, hThread, 1), 1); AddValueToRecord(8);
Sleep(100);
AddValueToRecord(9); ok_long(QueueUserAPC(DoUserAPC2, hThread, 2), 1); AddValueToRecord(10);
Sleep(100);
AddValueToRecord(11); ok_long(QueueUserAPC(DoUserAPC3, hThread, 3), 1); AddValueToRecord(12);
AddValueToRecord(13); ok_long(WaitForSingleObject(hThread, 5 * 1000), WAIT_OBJECT_0); AddValueToRecord(14);
AddValueToRecord(15); ok_int(CloseHandle(hThread), TRUE); hThread = NULL; AddValueToRecord(16);
CheckRecord();}
static void TestForSleepEx(void){ JustDoIt(ThreadFunc1);}
static void TestForWaitForSingleObjectEx(void){ JustDoIt(ThreadFunc2);}
static DWORD WINAPI ThreadFunc3(LPVOID arg){ return 0;}
static void TestMultipleUserAPCs(void){ HANDLE hThread; DWORD dwThreadId;
s_record_count = 0;
hThread = CreateThread(NULL, 0, ThreadFunc3, NULL, CREATE_SUSPENDED, &dwThreadId); ok(hThread != NULL, "hThread was NULL\n");
ok_long(QueueUserAPC(DoUserAPC1, hThread, 1), 1); ok_long(QueueUserAPC(DoUserAPC2, hThread, 2), 1); ok_long(QueueUserAPC(DoUserAPC3, hThread, 3), 1);
ok_long(s_record_count, 0);
ResumeThread(hThread);
ok_long(WaitForSingleObject(hThread, 5 * 1000), WAIT_OBJECT_0); ok_int(CloseHandle(hThread), TRUE);
ok_long(s_record_count, 3); ok_long(s_record[0], 4); ok_long(s_record[1], 5); ok_long(s_record[2], 6);}
START_TEST(QueueUserAPC){ TestForSleepEx(); TestForWaitForSingleObjectEx(); TestMultipleUserAPCs();}