From: Piotr Caban <piotr(a)codeweavers.com> --- dlls/msvcr120/tests/msvcr120.c | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index 11a8594e749..d21e73244c2 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -183,6 +183,10 @@ typedef struct _UnrealizedChore void *unk[6]; } _UnrealizedChore; +typedef struct { + MSVCRT_bool *cancelling; +} _Cancellation_beacon; + static char* (CDECL *p_setlocale)(int category, const char* locale); static struct MSVCRT_lconv* (CDECL *p_localeconv)(void); static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max); @@ -255,6 +259,9 @@ static int (__stdcall *p__StructuredTaskCollection__RunAndWait)(_StructuredTaskC static void (__thiscall *p__StructuredTaskCollection__Cancel)(_StructuredTaskCollection*); static MSVCRT_bool (__thiscall *p__StructuredTaskCollection__IsCanceling)(_StructuredTaskCollection*); +static _Cancellation_beacon* (__thiscall *p__Cancellation_beacon_ctor)(_Cancellation_beacon*); +static void (__thiscall *p__Cancellation_beacon_dtor)(_Cancellation_beacon*); + #define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) @@ -355,6 +362,10 @@ static BOOL init(void) "?notify_all(a)_Condition_variable@details(a)Concurrency@@QEAAXXZ"); SET(p_Context_CurrentContext, "?CurrentContext(a)Context@Concurrency@@SAPEAV12(a)XZ"); + SET(p__Cancellation_beacon_ctor, + "??0_Cancellation_beacon(a)details@Concurrency@@QEAA(a)XZ"); + SET(p__Cancellation_beacon_dtor, + "??1_Cancellation_beacon(a)details@Concurrency@@QEAA(a)XZ"); } else { #ifdef __arm__ SET(p__StructuredTaskCollection_ctor, @@ -399,6 +410,10 @@ static BOOL init(void) "?notify_one(a)_Condition_variable@details(a)Concurrency@@QAAXXZ"); SET(p__Condition_variable_notify_all, "?notify_all(a)_Condition_variable@details(a)Concurrency@@QAAXXZ"); + SET(p__Cancellation_beacon_ctor, + "??0_Cancellation_beacon(a)details@Concurrency@@QAA(a)XZ"); + SET(p__Cancellation_beacon_dtor, + "??1_Cancellation_beacon(a)details@Concurrency@@QAA(a)XZ"); #else SET(p__StructuredTaskCollection_ctor, "??0_StructuredTaskCollection(a)details@Concurrency@@QAE(a)PAV_CancellationTokenState@12@@Z"); @@ -442,6 +457,10 @@ static BOOL init(void) "?notify_one(a)_Condition_variable@details(a)Concurrency@@QAEXXZ"); SET(p__Condition_variable_notify_all, "?notify_all(a)_Condition_variable@details(a)Concurrency@@QAEXXZ"); + SET(p__Cancellation_beacon_ctor, + "??0_Cancellation_beacon(a)details@Concurrency@@QAE(a)XZ"); + SET(p__Cancellation_beacon_dtor, + "??1_Cancellation_beacon(a)details@Concurrency@@QAE(a)XZ"); #endif SET(p_Context_CurrentContext, "?CurrentContext(a)Context@Concurrency@@SAPAV12(a)XZ"); @@ -1366,6 +1385,7 @@ struct chore static void __cdecl chore_proc(_UnrealizedChore *_this) { struct chore *chore = CONTAINING_RECORD(_this, struct chore, chore); + _Cancellation_beacon beacon, beacon2; if (chore->start_event) { @@ -1388,6 +1408,13 @@ static void __cdecl chore_proc(_UnrealizedChore *_this) p__StructuredTaskCollection__IsCanceling, chore->chore.task_collection); ok(!canceling, "Task is already canceling\n"); + + call_func1(p__Cancellation_beacon_ctor, &beacon); + ok(!*beacon.cancelling, "beacon signalled %x\n", *beacon.cancelling); + + call_func1(p__Cancellation_beacon_ctor, &beacon2); + ok(beacon.cancelling != beacon2.cancelling, "beacons point to the same data\n"); + ok(!*beacon.cancelling, "beacon signalled %x\n", *beacon.cancelling); } if (!chore->wait_event) @@ -1412,6 +1439,15 @@ static void __cdecl chore_proc(_UnrealizedChore *_this) p__StructuredTaskCollection__IsCanceling, chore->chore.task_collection); ok(canceling, "Task is not canceling\n"); + + ok(*beacon.cancelling == 1, "beacon not signalled (%x)\n", *beacon.cancelling); + call_func1(p__Cancellation_beacon_dtor, &beacon); + ok(*beacon2.cancelling == 1, "beacon not signalled (%x)\n", *beacon2.cancelling); + call_func1(p__Cancellation_beacon_dtor, &beacon2); + + call_func1(p__Cancellation_beacon_ctor, &beacon); + ok(*beacon.cancelling == 1, "beacon not signalled (%x)\n", *beacon.cancelling); + call_func1(p__Cancellation_beacon_dtor, &beacon); } } @@ -1426,6 +1462,7 @@ static void test_StructuredTaskCollection(void) HANDLE chore_start_evt, chore_evt1, chore_evt2; _StructuredTaskCollection task_coll; struct chore chore1, chore2; + _Cancellation_beacon beacon; DWORD main_thread_id; Context *context; int status; @@ -1585,13 +1622,20 @@ static void test_StructuredTaskCollection(void) ret = WaitForSingleObject(chore_evt1, 5000); ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", ret); + call_func1(p__Cancellation_beacon_ctor, &beacon); + ok(!*beacon.cancelling, "beacon signalled\n"); + call_func1(p__StructuredTaskCollection__Cancel, &task_coll); + ok(!*beacon.cancelling, "beacon signalled\n"); b = SetEvent(chore_evt2); ok(b, "SetEvent failed\n"); + ok(!*beacon.cancelling, "beacon signalled\n"); status = p__StructuredTaskCollection__RunAndWait(&task_coll, NULL); ok(status == 2, "_StructuredTaskCollection::_RunAndWait failed: %d\n", status); + ok(!*beacon.cancelling, "beacon signalled\n"); + call_func1(p__Cancellation_beacon_dtor, &beacon); call_func1(p__StructuredTaskCollection_dtor, &task_coll); /* cancel task collection without scheduled tasks */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/3664