https://git.reactos.org/?p=reactos.git;a=commitdiff;h=88a63011ea30eb14d5249…
commit 88a63011ea30eb14d5249026d4505dc336c3b92f
Author: Justin Miller <justin.miller(a)reactos.org>
AuthorDate: Wed Jan 22 20:13:15 2025 -0800
Commit: Justin Miller <justinmiller100(a)gmail.com>
CommitDate: Sun Jan 26 23:30:59 2025 -0800
[ROSTESTS] Import winetest threadpool.c from wine-9.7
---
modules/rostests/winetests/ntdll/threadpool.c | 1229 +++++++++++++++++--------
1 file changed, 857 insertions(+), 372 deletions(-)
diff --git a/modules/rostests/winetests/ntdll/threadpool.c
b/modules/rostests/winetests/ntdll/threadpool.c
index af0b6673d39..1dd96bfd2f3 100644
--- a/modules/rostests/winetests/ntdll/threadpool.c
+++ b/modules/rostests/winetests/ntdll/threadpool.c
@@ -20,71 +20,91 @@
#include "ntdll_test.h"
-static HMODULE hntdll = 0;
static NTSTATUS (WINAPI *pTpAllocCleanupGroup)(TP_CLEANUP_GROUP **);
+static NTSTATUS (WINAPI *pTpAllocIoCompletion)(TP_IO **,HANDLE,PTP_IO_CALLBACK,void
*,TP_CALLBACK_ENVIRON *);
static NTSTATUS (WINAPI *pTpAllocPool)(TP_POOL **,PVOID);
static NTSTATUS (WINAPI *pTpAllocTimer)(TP_TIMER
**,PTP_TIMER_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
static NTSTATUS (WINAPI *pTpAllocWait)(TP_WAIT
**,PTP_WAIT_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
static NTSTATUS (WINAPI *pTpAllocWork)(TP_WORK
**,PTP_WORK_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);
static NTSTATUS (WINAPI *pTpCallbackMayRunLong)(TP_CALLBACK_INSTANCE *);
static VOID (WINAPI *pTpCallbackReleaseSemaphoreOnCompletion)(TP_CALLBACK_INSTANCE
*,HANDLE,DWORD);
+static void (WINAPI *pTpCancelAsyncIoOperation)(TP_IO *);
static VOID (WINAPI *pTpDisassociateCallback)(TP_CALLBACK_INSTANCE *);
static BOOL (WINAPI *pTpIsTimerSet)(TP_TIMER *);
-static VOID (WINAPI *pTpReleaseWait)(TP_WAIT *);
static VOID (WINAPI *pTpPostWork)(TP_WORK *);
+static NTSTATUS (WINAPI *pTpQueryPoolStackInformation)(TP_POOL
*,TP_POOL_STACK_INFORMATION *);
static VOID (WINAPI *pTpReleaseCleanupGroup)(TP_CLEANUP_GROUP *);
static VOID (WINAPI *pTpReleaseCleanupGroupMembers)(TP_CLEANUP_GROUP *,BOOL,PVOID);
+static void (WINAPI *pTpReleaseIoCompletion)(TP_IO *);
static VOID (WINAPI *pTpReleasePool)(TP_POOL *);
static VOID (WINAPI *pTpReleaseTimer)(TP_TIMER *);
+static VOID (WINAPI *pTpReleaseWait)(TP_WAIT *);
static VOID (WINAPI *pTpReleaseWork)(TP_WORK *);
static VOID (WINAPI *pTpSetPoolMaxThreads)(TP_POOL *,DWORD);
+static NTSTATUS (WINAPI *pTpSetPoolStackInformation)(TP_POOL *,TP_POOL_STACK_INFORMATION
*);
static VOID (WINAPI *pTpSetTimer)(TP_TIMER *,LARGE_INTEGER *,LONG,LONG);
static VOID (WINAPI *pTpSetWait)(TP_WAIT *,HANDLE,LARGE_INTEGER *);
static NTSTATUS (WINAPI *pTpSimpleTryPost)(PTP_SIMPLE_CALLBACK,PVOID,TP_CALLBACK_ENVIRON
*);
+static void (WINAPI *pTpStartAsyncIoOperation)(TP_IO *);
+static void (WINAPI *pTpWaitForIoCompletion)(TP_IO *,BOOL);
static VOID (WINAPI *pTpWaitForTimer)(TP_TIMER *,BOOL);
static VOID (WINAPI *pTpWaitForWait)(TP_WAIT *,BOOL);
static VOID (WINAPI *pTpWaitForWork)(TP_WORK *,BOOL);
-#define NTDLL_GET_PROC(func) \
+static void (WINAPI *pCancelThreadpoolIo)(TP_IO *);
+static void (WINAPI *pCloseThreadpoolIo)(TP_IO *);
+static TP_IO *(WINAPI *pCreateThreadpoolIo)(HANDLE, PTP_WIN32_IO_CALLBACK, void *,
TP_CALLBACK_ENVIRON *);
+static void (WINAPI *pStartThreadpoolIo)(TP_IO *);
+static void (WINAPI *pWaitForThreadpoolIoCallbacks)(TP_IO *, BOOL);
+
+#define GET_PROC(func) \
do \
{ \
- p ## func = (void *)GetProcAddress(hntdll, #func); \
+ p ## func = (void *)GetProcAddress(module, #func); \
if (!p ## func) trace("Failed to get address for %s\n", #func); \
} \
while (0)
static BOOL init_threadpool(void)
{
- hntdll = GetModuleHandleA("ntdll");
- if (!hntdll)
- {
- win_skip("Could not load ntdll\n");
- return FALSE;
- }
-
- NTDLL_GET_PROC(TpAllocCleanupGroup);
- NTDLL_GET_PROC(TpAllocPool);
- NTDLL_GET_PROC(TpAllocTimer);
- NTDLL_GET_PROC(TpAllocWait);
- NTDLL_GET_PROC(TpAllocWork);
- NTDLL_GET_PROC(TpCallbackMayRunLong);
- NTDLL_GET_PROC(TpCallbackReleaseSemaphoreOnCompletion);
- NTDLL_GET_PROC(TpDisassociateCallback);
- NTDLL_GET_PROC(TpIsTimerSet);
- NTDLL_GET_PROC(TpPostWork);
- NTDLL_GET_PROC(TpReleaseCleanupGroup);
- NTDLL_GET_PROC(TpReleaseCleanupGroupMembers);
- NTDLL_GET_PROC(TpReleasePool);
- NTDLL_GET_PROC(TpReleaseTimer);
- NTDLL_GET_PROC(TpReleaseWait);
- NTDLL_GET_PROC(TpReleaseWork);
- NTDLL_GET_PROC(TpSetPoolMaxThreads);
- NTDLL_GET_PROC(TpSetTimer);
- NTDLL_GET_PROC(TpSetWait);
- NTDLL_GET_PROC(TpSimpleTryPost);
- NTDLL_GET_PROC(TpWaitForTimer);
- NTDLL_GET_PROC(TpWaitForWait);
- NTDLL_GET_PROC(TpWaitForWork);
+ HMODULE module = GetModuleHandleA("ntdll");
+ GET_PROC(TpAllocCleanupGroup);
+ GET_PROC(TpAllocIoCompletion);
+ GET_PROC(TpAllocPool);
+ GET_PROC(TpAllocTimer);
+ GET_PROC(TpAllocWait);
+ GET_PROC(TpAllocWork);
+ GET_PROC(TpCallbackMayRunLong);
+ GET_PROC(TpCallbackReleaseSemaphoreOnCompletion);
+ GET_PROC(TpCancelAsyncIoOperation);
+ GET_PROC(TpDisassociateCallback);
+ GET_PROC(TpIsTimerSet);
+ GET_PROC(TpPostWork);
+ GET_PROC(TpQueryPoolStackInformation);
+ GET_PROC(TpReleaseCleanupGroup);
+ GET_PROC(TpReleaseCleanupGroupMembers);
+ GET_PROC(TpReleaseIoCompletion);
+ GET_PROC(TpReleasePool);
+ GET_PROC(TpReleaseTimer);
+ GET_PROC(TpReleaseWait);
+ GET_PROC(TpReleaseWork);
+ GET_PROC(TpSetPoolMaxThreads);
+ GET_PROC(TpSetPoolStackInformation);
+ GET_PROC(TpSetTimer);
+ GET_PROC(TpSetWait);
+ GET_PROC(TpSimpleTryPost);
+ GET_PROC(TpStartAsyncIoOperation);
+ GET_PROC(TpWaitForIoCompletion);
+ GET_PROC(TpWaitForTimer);
+ GET_PROC(TpWaitForWait);
+ GET_PROC(TpWaitForWork);
+
+ module = GetModuleHandleA("kernel32");
+ GET_PROC(CancelThreadpoolIo);
+ GET_PROC(CloseThreadpoolIo);
+ GET_PROC(CreateThreadpoolIo);
+ GET_PROC(StartThreadpoolIo);
+ GET_PROC(WaitForThreadpoolIoCallbacks);
if (!pTpAllocPool)
{
@@ -101,7 +121,6 @@ static BOOL init_threadpool(void)
static DWORD CALLBACK rtl_work_cb(void *userdata)
{
HANDLE semaphore = userdata;
- trace("Running rtl_work callback\n");
ReleaseSemaphore(semaphore, 1, NULL);
return 0;
}
@@ -113,32 +132,32 @@ static void test_RtlQueueWorkItem(void)
DWORD result;
semaphore = CreateSemaphoreA(NULL, 0, 1, NULL);
- ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
+ ok(semaphore != NULL, "CreateSemaphoreA failed %lu\n", GetLastError());
status = RtlQueueWorkItem(rtl_work_cb, semaphore, WT_EXECUTEDEFAULT);
- ok(!status, "RtlQueueWorkItem failed with status %x\n", status);
+ ok(!status, "RtlQueueWorkItem failed with status %lx\n", status);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
status = RtlQueueWorkItem(rtl_work_cb, semaphore, WT_EXECUTEINIOTHREAD);
- ok(!status, "RtlQueueWorkItem failed with status %x\n", status);
+ ok(!status, "RtlQueueWorkItem failed with status %lx\n", status);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
status = RtlQueueWorkItem(rtl_work_cb, semaphore, WT_EXECUTEINPERSISTENTTHREAD);
- ok(!status, "RtlQueueWorkItem failed with status %x\n", status);
+ ok(!status, "RtlQueueWorkItem failed with status %lx\n", status);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
status = RtlQueueWorkItem(rtl_work_cb, semaphore, WT_EXECUTELONGFUNCTION);
- ok(!status, "RtlQueueWorkItem failed with status %x\n", status);
+ ok(!status, "RtlQueueWorkItem failed with status %lx\n", status);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
status = RtlQueueWorkItem(rtl_work_cb, semaphore, WT_TRANSFER_IMPERSONATION);
- ok(!status, "RtlQueueWorkItem failed with status %x\n", status);
+ ok(!status, "RtlQueueWorkItem failed with status %lx\n", status);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
CloseHandle(semaphore);
}
@@ -157,8 +176,6 @@ static void CALLBACK rtl_wait_cb(void *userdata, BOOLEAN timeout)
struct rtl_wait_info *info = userdata;
DWORD result;
- trace("Running rtl_wait callback\n");
-
if (!timeout)
InterlockedIncrement(&info->userdata);
else
@@ -169,7 +186,7 @@ static void CALLBACK rtl_wait_cb(void *userdata, BOOLEAN timeout)
if (info->semaphore2)
{
result = WaitForSingleObject(info->semaphore2, 200);
- ok(result == info->wait_result, "expected %u, got %u\n",
info->wait_result, result);
+ ok(result == info->wait_result, "expected %lu, got %lu\n",
info->wait_result, result);
ReleaseSemaphore(info->semaphore1, 1, NULL);
}
}
@@ -178,7 +195,6 @@ static HANDLE rtl_wait_apc_semaphore;
static void CALLBACK rtl_wait_apc_cb(ULONG_PTR userdata)
{
- trace("Running rtl_wait_apc callback\n");
if (rtl_wait_apc_semaphore)
ReleaseSemaphore(rtl_wait_apc_semaphore, 1, NULL);
}
@@ -189,7 +205,7 @@ static void test_RtlRegisterWait(void)
struct rtl_wait_info info;
HANDLE semaphores[2];
NTSTATUS status;
- DWORD result;
+ DWORD result, threadid;
semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL);
ok(semaphores[0] != NULL, "failed to create semaphore\n");
@@ -205,196 +221,257 @@ static void test_RtlRegisterWait(void)
wait1 = NULL;
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEDEFAULT);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ok(wait1 != NULL, "expected wait1 != NULL\n");
status = RtlDeregisterWait(wait1);
- ok(!status, "RtlDeregisterWait failed with status %x\n", status);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
/* infinite timeout, signal the semaphore two times */
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEDEFAULT);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 2, "expected info.userdata = 2, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 2, "expected info.userdata = 2, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
Sleep(50);
status = RtlDeregisterWait(wait1);
- ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
/* repeat test with WT_EXECUTEONLYONCE */
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEONLYONCE);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
Sleep(50);
status = RtlDeregisterWait(wait1);
- ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
/* finite timeout, no event */
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 200,
WT_EXECUTEDEFAULT);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[0], 200);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
Sleep(50);
status = RtlDeregisterWait(wait1);
- ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
/* finite timeout, with event */
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 200,
WT_EXECUTEDEFAULT);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
+ result = WaitForSingleObject(semaphores[1], 0);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ Sleep(50);
+ status = RtlDeregisterWait(wait1);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
+
+ /* test RtlRegisterWait WT_EXECUTEINWAITTHREAD flag */
+ info.userdata = 0;
+ info.threadid = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 200,
WT_EXECUTEINWAITTHREAD|WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 200);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
+ ok(info.threadid && info.threadid != GetCurrentThreadId(), "unexpected
wait thread id %lx\n", info.threadid);
+ threadid = info.threadid;
+ result = WaitForSingleObject(semaphores[1], 0);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ Sleep(50);
+ status = RtlDeregisterWait(wait1);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
+
+ info.userdata = 0;
+ info.threadid = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 200,
WT_EXECUTEINWAITTHREAD|WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 200);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
+ ok(info.threadid == threadid, "unexpected different wait thread id %lx\n",
info.threadid);
+ result = WaitForSingleObject(semaphores[1], 0);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ Sleep(50);
+ status = RtlDeregisterWait(wait1);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
+
+ /* test RtlRegisterWait WT_EXECUTEINWAITTHREAD flag with 0 timeout */
+ info.userdata = 0;
+ info.threadid = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 0,
WT_EXECUTEINWAITTHREAD|WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
+ ok(info.threadid == threadid, "unexpected different wait thread id %lx\n",
info.threadid);
+ result = WaitForSingleObject(semaphores[1], 0);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ Sleep(50);
+ status = RtlDeregisterWait(wait1);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
+
+ /* test RtlRegisterWait WT_EXECUTEINWAITTHREAD flag with already signaled event */
+ info.userdata = 0;
+ info.threadid = 0;
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 200,
WT_EXECUTEINWAITTHREAD|WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
+ result = WaitForSingleObject(semaphores[0], 200);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
+ ok(info.threadid == threadid, "unexpected different wait thread id %lx\n",
info.threadid);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
Sleep(50);
status = RtlDeregisterWait(wait1);
- ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
/* test for IO threads */
info.userdata = 0;
info.threadid = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEINIOTHREAD);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
- ok(info.threadid != 0, "expected info.threadid != 0, got %u\n",
info.threadid);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
+ ok(info.threadid != 0, "expected info.threadid != 0, got %lu\n",
info.threadid);
thread = OpenThread(THREAD_SET_CONTEXT, FALSE, info.threadid);
- ok(thread != NULL, "OpenThread failed with %u\n", GetLastError());
+ ok(thread != NULL, "OpenThread failed with %lu\n", GetLastError());
rtl_wait_apc_semaphore = semaphores[0];
result = QueueUserAPC(rtl_wait_apc_cb, thread, 0);
- ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
+ ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
result = WaitForSingleObject(semaphores[0], 200);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
rtl_wait_apc_semaphore = 0;
CloseHandle(thread);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 2, "expected info.userdata = 2, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 2, "expected info.userdata = 2, got %lu\n",
info.userdata);
Sleep(50);
status = RtlDeregisterWait(wait1);
- ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
info.userdata = 0;
info.threadid = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEDEFAULT);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
- ok(info.threadid != 0, "expected info.threadid != 0, got %u\n",
info.threadid);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
+ ok(info.threadid != 0, "expected info.threadid != 0, got %lu\n",
info.threadid);
thread = OpenThread(THREAD_SET_CONTEXT, FALSE, info.threadid);
- ok(thread != NULL, "OpenThread failed with %u\n", GetLastError());
+ ok(thread != NULL, "OpenThread failed with %lu\n", GetLastError());
rtl_wait_apc_semaphore = semaphores[0];
result = QueueUserAPC(rtl_wait_apc_cb, thread, 0);
- ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
+ ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
result = WaitForSingleObject(semaphores[0], 200);
ok(result == WAIT_TIMEOUT || broken(result == WAIT_OBJECT_0) /* >= Win Vista */,
- "WaitForSingleObject returned %u\n", result);
+ "WaitForSingleObject returned %lu\n", result);
rtl_wait_apc_semaphore = 0;
CloseHandle(thread);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 2, "expected info.userdata = 2, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 2, "expected info.userdata = 2, got %lu\n",
info.userdata);
Sleep(50);
status = RtlDeregisterWait(wait1);
- ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+ ok(!status, "RtlDeregisterWait failed with status %lx\n", status);
/* test RtlDeregisterWaitEx before wait expired */
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEDEFAULT);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
status = RtlDeregisterWaitEx(wait1, NULL);
- ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(!status, "RtlDeregisterWaitEx failed with status %lx\n", status);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEDEFAULT);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
status = RtlDeregisterWaitEx(wait1, INVALID_HANDLE_VALUE);
- ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(!status, "RtlDeregisterWaitEx failed with status %lx\n", status);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEDEFAULT);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
status = RtlDeregisterWaitEx(wait1, event);
- ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(!status, "RtlDeregisterWaitEx failed with status %lx\n", status);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
result = WaitForSingleObject(event, 200);
- todo_wine
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* test RtlDeregisterWaitEx after wait expired */
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 0,
WT_EXECUTEONLYONCE);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
Sleep(50);
status = RtlDeregisterWaitEx(wait1, NULL);
- ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(!status, "RtlDeregisterWaitEx failed with status %lx\n", status);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 0,
WT_EXECUTEONLYONCE);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
Sleep(50);
status = RtlDeregisterWaitEx(wait1, INVALID_HANDLE_VALUE);
- ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(!status, "RtlDeregisterWaitEx failed with status %lx\n", status);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 0,
WT_EXECUTEONLYONCE);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
Sleep(50);
status = RtlDeregisterWaitEx(wait1, event);
- ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(!status, "RtlDeregisterWaitEx failed with status %lx\n", status);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
result = WaitForSingleObject(event, 200);
- todo_wine
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* test RtlDeregisterWaitEx while callback is running */
info.semaphore2 = semaphores[1];
@@ -402,58 +479,84 @@ static void test_RtlRegisterWait(void)
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEONLYONCE);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
status = RtlDeregisterWait(wait1);
- ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %x\n",
status);
+ ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %lx\n",
status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEINWAITTHREAD|WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
+ status = RtlDeregisterWait(wait1);
+ ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %lx\n",
status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEONLYONCE);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
status = RtlDeregisterWaitEx(wait1, NULL);
- ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %x\n",
status);
+ ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %lx\n",
status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
info.wait_result = WAIT_TIMEOUT;
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEONLYONCE);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
+ status = RtlDeregisterWaitEx(wait1, INVALID_HANDLE_VALUE);
+ ok(!status, "RtlDeregisterWaitEx failed with status %lx\n", status);
+ result = WaitForSingleObject(semaphores[0], 0);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+
+ info.wait_result = WAIT_TIMEOUT;
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEINWAITTHREAD|WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
status = RtlDeregisterWaitEx(wait1, INVALID_HANDLE_VALUE);
- ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
+ ok(!status, "RtlDeregisterWaitEx failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 0);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
info.wait_result = WAIT_OBJECT_0;
info.userdata = 0;
status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE,
WT_EXECUTEONLYONCE);
- ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(!status, "RtlRegisterWait failed with status %lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
status = RtlDeregisterWaitEx(wait1, event);
- ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %x\n",
status);
+ ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %lx\n",
status);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(event, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphores[0], 0);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
CloseHandle(semaphores[0]);
CloseHandle(semaphores[1]);
@@ -463,19 +566,19 @@ static void test_RtlRegisterWait(void)
static void CALLBACK simple_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
{
HANDLE semaphore = userdata;
- trace("Running simple callback\n");
ReleaseSemaphore(semaphore, 1, NULL);
}
static void CALLBACK simple2_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
{
- trace("Running simple2 callback\n");
Sleep(50);
InterlockedIncrement((LONG *)userdata);
}
static void test_tp_simple(void)
{
+ IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress
);
+ TP_POOL_STACK_INFORMATION stack_info;
TP_CALLBACK_ENVIRON environment;
TP_CALLBACK_ENVIRON_V3 environment3;
TP_CLEANUP_GROUP *group;
@@ -487,21 +590,21 @@ static void test_tp_simple(void)
int i;
semaphore = CreateSemaphoreA(NULL, 0, 1, NULL);
- ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
+ ok(semaphore != NULL, "CreateSemaphoreA failed %lu\n", GetLastError());
/* post the callback using the default threadpool */
memset(&environment, 0, sizeof(environment));
environment.Version = 1;
environment.Pool = NULL;
status = pTpSimpleTryPost(simple_cb, semaphore, &environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* allocate new threadpool */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
/* post the callback using the new threadpool */
@@ -509,20 +612,29 @@ static void test_tp_simple(void)
environment.Version = 1;
environment.Pool = pool;
status = pTpSimpleTryPost(simple_cb, semaphore, &environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* test with environment version 3 */
memset(&environment3, 0, sizeof(environment3));
environment3.Version = 3;
environment3.Pool = pool;
- environment3.CallbackPriority = TP_CALLBACK_PRIORITY_NORMAL;
environment3.Size = sizeof(environment3);
+
+ for (i = 0; i < 3; ++i)
+ {
+ environment3.CallbackPriority = TP_CALLBACK_PRIORITY_HIGH + i;
+ status = pTpSimpleTryPost(simple_cb, semaphore, (TP_CALLBACK_ENVIRON
*)&environment3);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
+ result = WaitForSingleObject(semaphore, 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ }
+
+ environment3.CallbackPriority = 10;
status = pTpSimpleTryPost(simple_cb, semaphore, (TP_CALLBACK_ENVIRON
*)&environment3);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
- result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(status == STATUS_INVALID_PARAMETER || broken(!status) /* Vista does not support
priorities */,
+ "TpSimpleTryPost failed with status %lx\n", status);
/* test with invalid version number */
memset(&environment, 0, sizeof(environment));
@@ -531,17 +643,17 @@ static void test_tp_simple(void)
status = pTpSimpleTryPost(simple_cb, semaphore, &environment);
todo_wine
ok(status == STATUS_INVALID_PARAMETER || broken(!status) /* Vista/2008 */,
- "TpSimpleTryPost unexpectedly returned status %x\n", status);
+ "TpSimpleTryPost unexpectedly returned status %lx\n", status);
if (!status)
{
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n",
result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
}
/* allocate a cleanup group for synchronization */
group = NULL;
status = pTpAllocCleanupGroup(&group);
- ok(!status, "TpAllocCleanupGroup failed with status %x\n", status);
+ ok(!status, "TpAllocCleanupGroup failed with status %lx\n", status);
ok(group != NULL, "expected pool != NULL\n");
/* use cleanup group to wait for a simple callback */
@@ -551,9 +663,9 @@ static void test_tp_simple(void)
environment.Pool = pool;
environment.CleanupGroup = group;
status = pTpSimpleTryPost(simple2_cb, &userdata, &environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
- ok(userdata == 1, "expected userdata = 1, got %u\n", userdata);
+ ok(userdata == 1, "expected userdata = 1, got %lu\n", userdata);
/* test cancellation of pending simple callbacks */
userdata = 0;
@@ -565,10 +677,26 @@ static void test_tp_simple(void)
for (i = 0; i < 100; i++)
{
status = pTpSimpleTryPost(simple2_cb, &userdata, &environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
}
pTpReleaseCleanupGroupMembers(group, TRUE, NULL);
- ok(userdata < 100, "expected userdata < 100, got %u\n", userdata);
+ ok(userdata < 100, "expected userdata < 100, got %lu\n", userdata);
+
+ /* test querying and setting the stack size */
+ status = pTpQueryPoolStackInformation(pool, &stack_info);
+ ok(!status, "TpQueryPoolStackInformation failed: %lx\n", status);
+ ok(stack_info.StackReserve == nt->OptionalHeader.SizeOfStackReserve,
"expected default StackReserve, got %Ix\n", stack_info.StackReserve);
+ ok(stack_info.StackCommit == nt->OptionalHeader.SizeOfStackCommit, "expected
default StackCommit, got %Ix\n", stack_info.StackCommit);
+
+ /* threadpool does not validate the stack size values */
+ stack_info.StackReserve = stack_info.StackCommit = 1;
+ status = pTpSetPoolStackInformation(pool, &stack_info);
+ ok(!status, "TpSetPoolStackInformation failed: %lx\n", status);
+
+ status = pTpQueryPoolStackInformation(pool, &stack_info);
+ ok(!status, "TpQueryPoolStackInformation failed: %lx\n", status);
+ ok(stack_info.StackReserve == 1, "expected 1 byte StackReserve, got %ld\n",
(ULONG)stack_info.StackReserve);
+ ok(stack_info.StackCommit == 1, "expected 1 byte StackCommit, got %ld\n",
(ULONG)stack_info.StackCommit);
/* cleanup */
pTpReleaseCleanupGroup(group);
@@ -578,14 +706,12 @@ static void test_tp_simple(void)
static void CALLBACK work_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_WORK
*work)
{
- trace("Running work callback\n");
Sleep(100);
InterlockedIncrement((LONG *)userdata);
}
static void CALLBACK work2_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_WORK
*work)
{
- trace("Running work2 callback\n");
Sleep(100);
InterlockedExchangeAdd((LONG *)userdata, 0x10000);
}
@@ -602,7 +728,7 @@ static void test_tp_work(void)
/* allocate new threadpool with only one thread */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
pTpSetPoolMaxThreads(pool, 1);
@@ -612,7 +738,7 @@ static void test_tp_work(void)
environment.Version = 1;
environment.Pool = pool;
status = pTpAllocWork(&work, work_cb, &userdata, &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
/* post 5 identical work items at once */
@@ -620,14 +746,14 @@ static void test_tp_work(void)
for (i = 0; i < 5; i++)
pTpPostWork(work);
pTpWaitForWork(work, FALSE);
- ok(userdata == 5, "expected userdata = 5, got %u\n", userdata);
+ ok(userdata == 5, "expected userdata = 5, got %lu\n", userdata);
/* add more tasks and cancel them immediately */
userdata = 0;
for (i = 0; i < 10; i++)
pTpPostWork(work);
pTpWaitForWork(work, TRUE);
- ok(userdata < 10, "expected userdata < 10, got %u\n", userdata);
+ ok(userdata < 10, "expected userdata < 10, got %lu\n", userdata);
/* cleanup */
pTpReleaseWork(work);
@@ -647,14 +773,14 @@ static void test_tp_work_scheduler(void)
/* allocate new threadpool with only one thread */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
pTpSetPoolMaxThreads(pool, 1);
/* create a cleanup group */
group = NULL;
status = pTpAllocCleanupGroup(&group);
- ok(!status, "TpAllocCleanupGroup failed with status %x\n", status);
+ ok(!status, "TpAllocCleanupGroup failed with status %lx\n", status);
ok(group != NULL, "expected pool != NULL\n");
/* the first work item has no cleanup group associated */
@@ -663,7 +789,7 @@ static void test_tp_work_scheduler(void)
environment.Version = 1;
environment.Pool = pool;
status = pTpAllocWork(&work, work_cb, &userdata, &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
/* allocate a second work item with a cleanup group */
@@ -673,7 +799,7 @@ static void test_tp_work_scheduler(void)
environment.Pool = pool;
environment.CleanupGroup = group;
status = pTpAllocWork(&work2, work2_cb, &userdata, &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work2 != NULL, "expected work2 != NULL\n");
/* the 'work' callbacks are not blocking execution of 'work2'
callbacks */
@@ -685,8 +811,8 @@ static void test_tp_work_scheduler(void)
Sleep(500);
pTpWaitForWork(work, TRUE);
pTpWaitForWork(work2, TRUE);
- ok(userdata & 0xffff, "expected userdata & 0xffff != 0, got %u\n",
userdata & 0xffff);
- ok(userdata >> 16, "expected userdata >> 16 != 0, got %u\n",
userdata >> 16);
+ ok(userdata & 0xffff, "expected userdata & 0xffff != 0, got %lu\n",
userdata & 0xffff);
+ ok(userdata >> 16, "expected userdata >> 16 != 0, got %lu\n",
userdata >> 16);
/* test TpReleaseCleanupGroupMembers on a work item */
userdata = 0;
@@ -696,8 +822,8 @@ static void test_tp_work_scheduler(void)
pTpPostWork(work2);
pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
pTpWaitForWork(work, TRUE);
- ok((userdata & 0xffff) < 10, "expected userdata & 0xffff < 10, got
%u\n", userdata & 0xffff);
- ok((userdata >> 16) == 3, "expected userdata >> 16 == 3, got
%u\n", userdata >> 16);
+ ok((userdata & 0xffff) < 10, "expected userdata & 0xffff < 10, got
%lu\n", userdata & 0xffff);
+ ok((userdata >> 16) == 3, "expected userdata >> 16 == 3, got
%lu\n", userdata >> 16);
/* cleanup */
pTpReleaseWork(work);
@@ -708,7 +834,6 @@ static void test_tp_work_scheduler(void)
static void CALLBACK simple_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
{
HANDLE *semaphores = userdata;
- trace("Running simple release callback\n");
ReleaseSemaphore(semaphores, 1, NULL);
Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */
}
@@ -716,7 +841,6 @@ static void CALLBACK simple_release_cb(TP_CALLBACK_INSTANCE *instance,
void *use
static void CALLBACK work_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata,
TP_WORK *work)
{
HANDLE semaphore = userdata;
- trace("Running work release callback\n");
ReleaseSemaphore(semaphore, 1, NULL);
Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */
pTpReleaseWork(work);
@@ -725,7 +849,6 @@ static void CALLBACK work_release_cb(TP_CALLBACK_INSTANCE *instance,
void *userd
static void CALLBACK timer_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata,
TP_TIMER *timer)
{
HANDLE semaphore = userdata;
- trace("Running timer release callback\n");
ReleaseSemaphore(semaphore, 1, NULL);
Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */
pTpReleaseTimer(timer);
@@ -735,7 +858,6 @@ static void CALLBACK wait_release_cb(TP_CALLBACK_INSTANCE *instance,
void *userd
TP_WAIT *wait, TP_WAIT_RESULT result)
{
HANDLE semaphore = userdata;
- trace("Running wait release callback\n");
ReleaseSemaphore(semaphore, 1, NULL);
Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */
pTpReleaseWait(wait);
@@ -755,18 +877,18 @@ static void test_tp_group_wait(void)
DWORD result;
semaphore = CreateSemaphoreA(NULL, 0, 1, NULL);
- ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
+ ok(semaphore != NULL, "CreateSemaphoreA failed %lu\n", GetLastError());
/* allocate new threadpool */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
/* allocate a cleanup group */
group = NULL;
status = pTpAllocCleanupGroup(&group);
- ok(!status, "TpAllocCleanupGroup failed with status %x\n", status);
+ ok(!status, "TpAllocCleanupGroup failed with status %lx\n", status);
ok(group != NULL, "expected pool != NULL\n");
/* release work object during TpReleaseCleanupGroupMembers */
@@ -776,11 +898,11 @@ static void test_tp_group_wait(void)
environment.Pool = pool;
environment.CleanupGroup = group;
status = pTpAllocWork(&work, work_release_cb, semaphore, &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
pTpPostWork(work);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
/* release timer object during TpReleaseCleanupGroupMembers */
@@ -790,12 +912,12 @@ static void test_tp_group_wait(void)
environment.Pool = pool;
environment.CleanupGroup = group;
status = pTpAllocTimer(&timer, timer_release_cb, semaphore, &environment);
- ok(!status, "TpAllocTimer failed with status %x\n", status);
+ ok(!status, "TpAllocTimer failed with status %lx\n", status);
ok(timer != NULL, "expected timer != NULL\n");
when.QuadPart = 0;
pTpSetTimer(timer, &when, 0, 0);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
/* release wait object during TpReleaseCleanupGroupMembers */
@@ -805,12 +927,12 @@ static void test_tp_group_wait(void)
environment.Pool = pool;
environment.CleanupGroup = group;
status = pTpAllocWait(&wait, wait_release_cb, semaphore, &environment);
- ok(!status, "TpAllocWait failed with status %x\n", status);
+ ok(!status, "TpAllocWait failed with status %lx\n", status);
ok(wait != NULL, "expected wait != NULL\n");
when.QuadPart = 0;
pTpSetWait(wait, INVALID_HANDLE_VALUE, &when);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
/* cleanup */
@@ -828,17 +950,15 @@ static void CALLBACK simple_group_cancel_cb(TP_CALLBACK_INSTANCE
*instance, void
DWORD result;
int i;
- trace("Running simple group cancel callback\n");
-
status = pTpCallbackMayRunLong(instance);
ok(status == STATUS_TOO_MANY_THREADS || broken(status == 1) /* Win Vista / 2008 */,
- "expected STATUS_TOO_MANY_THREADS, got %08x\n", status);
+ "expected STATUS_TOO_MANY_THREADS, got %08lx\n", status);
ReleaseSemaphore(semaphores[1], 1, NULL);
for (i = 0; i < 4; i++)
{
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n",
result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
}
ReleaseSemaphore(semaphores[1], 1, NULL);
}
@@ -848,17 +968,14 @@ static void CALLBACK work_group_cancel_cb(TP_CALLBACK_INSTANCE
*instance, void *
HANDLE *semaphores = userdata;
DWORD result;
- trace("Running work group cancel callback\n");
-
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 200);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
}
static void CALLBACK group_cancel_cleanup_release_cb(void *object, void *userdata)
{
HANDLE *semaphores = userdata;
- trace("Running group cancel cleanup release callback\n");
group_cancel_tid = GetCurrentThreadId();
ok(object == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n",
object);
ReleaseSemaphore(semaphores[0], 1, NULL);
@@ -867,7 +984,6 @@ static void CALLBACK group_cancel_cleanup_release_cb(void *object,
void *userdat
static void CALLBACK group_cancel_cleanup_release2_cb(void *object, void *userdata)
{
HANDLE *semaphores = userdata;
- trace("Running group cancel cleanup release2 callback\n");
group_cancel_tid = GetCurrentThreadId();
ok(object == userdata, "expected %p, got %p\n", userdata, object);
ReleaseSemaphore(semaphores[0], 1, NULL);
@@ -875,7 +991,6 @@ static void CALLBACK group_cancel_cleanup_release2_cb(void *object,
void *userda
static void CALLBACK group_cancel_cleanup_increment_cb(void *object, void *userdata)
{
- trace("Running group cancel cleanup increment callback\n");
group_cancel_tid = GetCurrentThreadId();
InterlockedIncrement((LONG *)userdata);
}
@@ -921,21 +1036,21 @@ static void test_tp_group_cancel(void)
int i;
semaphores[0] = CreateSemaphoreA(NULL, 0, 4, NULL);
- ok(semaphores[0] != NULL, "CreateSemaphoreA failed %u\n",
GetLastError());
+ ok(semaphores[0] != NULL, "CreateSemaphoreA failed %lu\n",
GetLastError());
semaphores[1] = CreateSemaphoreA(NULL, 0, 1, NULL);
- ok(semaphores[1] != NULL, "CreateSemaphoreA failed %u\n",
GetLastError());
+ ok(semaphores[1] != NULL, "CreateSemaphoreA failed %lu\n",
GetLastError());
/* allocate new threadpool with only one thread */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
pTpSetPoolMaxThreads(pool, 1);
/* allocate a cleanup group */
group = NULL;
status = pTpAllocCleanupGroup(&group);
- ok(!status, "TpAllocCleanupGroup failed with status %x\n", status);
+ ok(!status, "TpAllocCleanupGroup failed with status %lx\n", status);
ok(group != NULL, "expected pool != NULL\n");
/* test execution of cancellation callback */
@@ -943,9 +1058,9 @@ static void test_tp_group_cancel(void)
environment.Version = 1;
environment.Pool = pool;
status = pTpSimpleTryPost(simple_group_cancel_cb, semaphores, &environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
memset(&environment, 0, sizeof(environment));
environment.Version = 1;
@@ -953,28 +1068,28 @@ static void test_tp_group_cancel(void)
environment.CleanupGroup = group;
environment.CleanupGroupCancelCallback = group_cancel_cleanup_release_cb;
status = pTpSimpleTryPost(unexpected_simple_cb, (void *)0xdeadbeef,
&environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
work = NULL;
status = pTpAllocWork(&work, unexpected_work_cb, (void *)0xdeadbeef,
&environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
timer = NULL;
status = pTpAllocTimer(&timer, unexpected_timer_cb, (void *)0xdeadbeef,
&environment);
- ok(!status, "TpAllocTimer failed with status %x\n", status);
+ ok(!status, "TpAllocTimer failed with status %lx\n", status);
ok(timer != NULL, "expected timer != NULL\n");
wait = NULL;
status = pTpAllocWait(&wait, unexpected_wait_cb, (void *)0xdeadbeef,
&environment);
- ok(!status, "TpAllocWait failed with status %x\n", status);
+ ok(!status, "TpAllocWait failed with status %lx\n", status);
ok(wait != NULL, "expected wait != NULL\n");
group_cancel_tid = 0xdeadbeef;
pTpReleaseCleanupGroupMembers(group, TRUE, semaphores);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %x, got %x\n",
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %lx, got
%lx\n",
GetCurrentThreadId(), group_cancel_tid);
/* test if cancellation callbacks are executed before or after wait */
@@ -985,19 +1100,19 @@ static void test_tp_group_cancel(void)
environment.CleanupGroup = group;
environment.CleanupGroupCancelCallback = group_cancel_cleanup_release2_cb;
status = pTpAllocWork(&work, work_group_cancel_cb, semaphores,
&environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
pTpPostWork(work);
pTpPostWork(work);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
group_cancel_tid = 0xdeadbeef;
pTpReleaseCleanupGroupMembers(group, TRUE, semaphores);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %x, got %x\n",
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %lx, got
%lx\n",
GetCurrentThreadId(), group_cancel_tid);
/* group cancel callback is not executed if object is destroyed while waiting */
@@ -1008,12 +1123,12 @@ static void test_tp_group_cancel(void)
environment.CleanupGroup = group;
environment.CleanupGroupCancelCallback = unexpected_group_cancel_cleanup_cb;
status = pTpAllocWork(&work, work_release_cb, semaphores[1], &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
pTpPostWork(work);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
pTpReleaseCleanupGroupMembers(group, TRUE, NULL);
/* terminated simple callbacks should not trigger the group cancel callback */
@@ -1023,9 +1138,9 @@ static void test_tp_group_cancel(void)
environment.CleanupGroup = group;
environment.CleanupGroupCancelCallback = unexpected_group_cancel_cleanup_cb;
status = pTpSimpleTryPost(simple_release_cb, semaphores[1], &environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
pTpReleaseCleanupGroupMembers(group, TRUE, semaphores);
/* test cancellation callback for objects with multiple instances */
@@ -1036,7 +1151,7 @@ static void test_tp_group_cancel(void)
environment.CleanupGroup = group;
environment.CleanupGroupCancelCallback = group_cancel_cleanup_increment_cb;
status = pTpAllocWork(&work, work_cb, &userdata, &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
/* post 10 identical work items at once */
@@ -1047,9 +1162,9 @@ static void test_tp_group_cancel(void)
/* check if we get multiple cancellation callbacks */
group_cancel_tid = 0xdeadbeef;
pTpReleaseCleanupGroupMembers(group, TRUE, &userdata2);
- ok(userdata <= 5, "expected userdata <= 5, got %u\n", userdata);
- ok(userdata2 == 1, "expected only one cancellation callback, got %u\n",
userdata2);
- ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %x, got %x\n",
+ ok(userdata <= 5, "expected userdata <= 5, got %lu\n", userdata);
+ ok(userdata2 == 1, "expected only one cancellation callback, got %lu\n",
userdata2);
+ ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %lx, got
%lx\n",
GetCurrentThreadId(), group_cancel_tid);
/* cleanup */
@@ -1062,19 +1177,12 @@ static void test_tp_group_cancel(void)
static void CALLBACK instance_semaphore_completion_cb(TP_CALLBACK_INSTANCE *instance,
void *userdata)
{
HANDLE *semaphores = userdata;
- trace("Running instance completion callback\n");
pTpCallbackReleaseSemaphoreOnCompletion(instance, semaphores[0], 1);
}
static void CALLBACK instance_finalization_cb(TP_CALLBACK_INSTANCE *instance, void
*userdata)
{
HANDLE *semaphores = userdata;
- DWORD result;
-
- trace("Running instance finalization callback\n");
-
- result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
ReleaseSemaphore(semaphores[1], 1, NULL);
}
@@ -1094,7 +1202,7 @@ static void test_tp_instance(void)
/* allocate new threadpool */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
/* test for TpCallbackReleaseSemaphoreOnCompletion */
@@ -1102,9 +1210,9 @@ static void test_tp_instance(void)
environment.Version = 1;
environment.Pool = pool;
status = pTpSimpleTryPost(instance_semaphore_completion_cb, semaphores,
&environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* test for finalization callback */
memset(&environment, 0, sizeof(environment));
@@ -1112,11 +1220,11 @@ static void test_tp_instance(void)
environment.Pool = pool;
environment.FinalizationCallback = instance_finalization_cb;
status = pTpSimpleTryPost(instance_semaphore_completion_cb, semaphores,
&environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* cleanup */
pTpReleasePool(pool);
@@ -1129,11 +1237,9 @@ static void CALLBACK disassociate_cb(TP_CALLBACK_INSTANCE
*instance, void *userd
HANDLE *semaphores = userdata;
DWORD result;
- trace("Running disassociate callback\n");
-
pTpDisassociateCallback(instance);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
ReleaseSemaphore(semaphores[1], 1, NULL);
}
@@ -1142,11 +1248,9 @@ static void CALLBACK disassociate2_cb(TP_CALLBACK_INSTANCE
*instance, void *user
HANDLE *semaphores = userdata;
DWORD result;
- trace("Running disassociate2 callback\n");
-
pTpDisassociateCallback(instance);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
ReleaseSemaphore(semaphores[1], 1, NULL);
}
@@ -1155,11 +1259,9 @@ static void CALLBACK disassociate3_cb(TP_CALLBACK_INSTANCE
*instance, void *user
HANDLE *semaphores = userdata;
DWORD result;
- trace("Running disassociate3 callback\n");
-
pTpDisassociateCallback(instance);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
ReleaseSemaphore(semaphores[1], 1, NULL);
}
@@ -1181,12 +1283,12 @@ static void test_tp_disassociate(void)
/* allocate new threadpool and cleanup group */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
group = NULL;
status = pTpAllocCleanupGroup(&group);
- ok(!status, "TpAllocCleanupGroup failed with status %x\n", status);
+ ok(!status, "TpAllocCleanupGroup failed with status %lx\n", status);
ok(group != NULL, "expected pool != NULL\n");
/* test TpDisassociateCallback on work objects without group */
@@ -1195,17 +1297,17 @@ static void test_tp_disassociate(void)
environment.Version = 1;
environment.Pool = pool;
status = pTpAllocWork(&work, disassociate_cb, semaphores, &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
pTpPostWork(work);
pTpWaitForWork(work, FALSE);
result = WaitForSingleObject(semaphores[1], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
ReleaseSemaphore(semaphores[0], 1, NULL);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
pTpReleaseWork(work);
/* test TpDisassociateCallback on work objects with group (1) */
@@ -1215,17 +1317,17 @@ static void test_tp_disassociate(void)
environment.Pool = pool;
environment.CleanupGroup = group;
status = pTpAllocWork(&work, disassociate_cb, semaphores, &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
pTpPostWork(work);
pTpWaitForWork(work, FALSE);
result = WaitForSingleObject(semaphores[1], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
ReleaseSemaphore(semaphores[0], 1, NULL);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
/* test TpDisassociateCallback on work objects with group (2) */
@@ -1235,7 +1337,7 @@ static void test_tp_disassociate(void)
environment.Pool = pool;
environment.CleanupGroup = group;
status = pTpAllocWork(&work, disassociate2_cb, semaphores, &environment);
- ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(!status, "TpAllocWork failed with status %lx\n", status);
ok(work != NULL, "expected work != NULL\n");
pTpPostWork(work);
@@ -1243,9 +1345,9 @@ static void test_tp_disassociate(void)
ReleaseSemaphore(semaphores[0], 1, NULL);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* test TpDisassociateCallback on simple callbacks */
memset(&environment, 0, sizeof(environment));
@@ -1253,15 +1355,15 @@ static void test_tp_disassociate(void)
environment.Pool = pool;
environment.CleanupGroup = group;
status = pTpSimpleTryPost(disassociate3_cb, semaphores, &environment);
- ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+ ok(!status, "TpSimpleTryPost failed with status %lx\n", status);
pTpReleaseCleanupGroupMembers(group, FALSE, NULL);
ReleaseSemaphore(semaphores[0], 1, NULL);
result = WaitForSingleObject(semaphores[1], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphores[0], 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* cleanup */
pTpReleaseCleanupGroup(group);
@@ -1273,7 +1375,6 @@ static void test_tp_disassociate(void)
static void CALLBACK timer_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_TIMER
*timer)
{
HANDLE semaphore = userdata;
- trace("Running timer callback\n");
ReleaseSemaphore(semaphore, 1, NULL);
}
@@ -1290,12 +1391,12 @@ static void test_tp_timer(void)
int i;
semaphore = CreateSemaphoreA(NULL, 0, 1, NULL);
- ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
+ ok(semaphore != NULL, "CreateSemaphoreA failed %lu\n", GetLastError());
/* allocate new threadpool */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
/* allocate new timer */
@@ -1304,7 +1405,7 @@ static void test_tp_timer(void)
environment.Version = 1;
environment.Pool = pool;
status = pTpAllocTimer(&timer, timer_cb, semaphore, &environment);
- ok(!status, "TpAllocTimer failed with status %x\n", status);
+ ok(!status, "TpAllocTimer failed with status %lx\n", status);
ok(timer != NULL, "expected timer != NULL\n");
success = pTpIsTimerSet(timer);
@@ -1319,9 +1420,9 @@ static void test_tp_timer(void)
pTpWaitForTimer(timer, FALSE);
result = WaitForSingleObject(semaphore, 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
result = WaitForSingleObject(semaphore, 200);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
success = pTpIsTimerSet(timer);
ok(success, "TpIsTimerSet returned FALSE\n");
@@ -1335,9 +1436,9 @@ static void test_tp_timer(void)
pTpWaitForTimer(timer, FALSE);
result = WaitForSingleObject(semaphore, 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
result = WaitForSingleObject(semaphore, 200);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
success = pTpIsTimerSet(timer);
ok(success, "TpIsTimerSet returned FALSE\n");
@@ -1350,7 +1451,7 @@ static void test_tp_timer(void)
pTpWaitForTimer(timer, FALSE);
result = WaitForSingleObject(semaphore, 50);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
success = pTpIsTimerSet(timer);
ok(success, "TpIsTimerSet returned FALSE\n");
@@ -1364,7 +1465,7 @@ static void test_tp_timer(void)
CloseHandle(semaphore);
semaphore = CreateSemaphoreA(NULL, 0, 3, NULL);
- ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
+ ok(semaphore != NULL, "CreateSemaphoreA failed %lu\n", GetLastError());
/* allocate a new timer */
timer = NULL;
@@ -1372,7 +1473,7 @@ static void test_tp_timer(void)
environment.Version = 1;
environment.Pool = pool;
status = pTpAllocTimer(&timer, timer_cb, semaphore, &environment);
- ok(!status, "TpAllocTimer failed with status %x\n", status);
+ ok(!status, "TpAllocTimer failed with status %lx\n", status);
ok(timer != NULL, "expected timer != NULL\n");
/* test a relative timeout repeated periodically */
@@ -1386,11 +1487,11 @@ static void test_tp_timer(void)
for (i = 0; i < 3; i++)
{
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n",
result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
}
ticks = GetTickCount() - ticks;
ok(ticks >= 500 && (ticks <= 700 || broken(ticks <= 750)) /* Win 7
*/,
- "expected approximately 600 ticks, got %u\n", ticks);
+ "expected approximately 600 ticks, got %lu\n", ticks);
/* unset the timer */
pTpSetTimer(timer, NULL, 0, 0);
@@ -1413,7 +1514,6 @@ struct window_length_info
static void CALLBACK window_length_cb(TP_CALLBACK_INSTANCE *instance, void *userdata,
TP_TIMER *timer)
{
struct window_length_info *info = userdata;
- trace("Running window length callback\n");
info->ticks = GetTickCount();
ReleaseSemaphore(info->semaphore, 1, NULL);
}
@@ -1431,12 +1531,12 @@ static void test_tp_window_length(void)
BOOL merged;
semaphore = CreateSemaphoreA(NULL, 0, 2, NULL);
- ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
+ ok(semaphore != NULL, "CreateSemaphoreA failed %lu\n", GetLastError());
/* allocate new threadpool */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
/* allocate two identical timers */
@@ -1447,13 +1547,13 @@ static void test_tp_window_length(void)
timer1 = NULL;
info1.semaphore = semaphore;
status = pTpAllocTimer(&timer1, window_length_cb, &info1,
&environment);
- ok(!status, "TpAllocTimer failed with status %x\n", status);
+ ok(!status, "TpAllocTimer failed with status %lx\n", status);
ok(timer1 != NULL, "expected timer1 != NULL\n");
timer2 = NULL;
info2.semaphore = semaphore;
status = pTpAllocTimer(&timer2, window_length_cb, &info2,
&environment);
- ok(!status, "TpAllocTimer failed with status %x\n", status);
+ ok(!status, "TpAllocTimer failed with status %lx\n", status);
ok(timer2 != NULL, "expected timer2 != NULL\n");
/* choose parameters so that timers are not merged */
@@ -1468,9 +1568,9 @@ static void test_tp_window_length(void)
pTpSetTimer(timer1, &when, 0, 75);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
ok(info1.ticks != 0 && info2.ticks != 0, "expected that ticks are
nonzero\n");
ok(info2.ticks >= info1.ticks + 75 || broken(info2.ticks < info1.ticks + 75) /*
Win 2008 */,
"expected that timers are not merged\n");
@@ -1487,9 +1587,9 @@ static void test_tp_window_length(void)
pTpSetTimer(timer1, &when, 0, 200);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
ok(info1.ticks != 0 && info2.ticks != 0, "expected that ticks are
nonzero\n");
merged = info2.ticks >= info1.ticks - 50 && info2.ticks <= info1.ticks
+ 50;
ok(merged || broken(!merged) /* Win 10 */, "expected that timers are
merged\n");
@@ -1506,9 +1606,9 @@ static void test_tp_window_length(void)
pTpSetTimer(timer2, &when, 0, 0);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphore, 1000);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
ok(info1.ticks != 0 && info2.ticks != 0, "expected that ticks are
nonzero\n");
merged = info2.ticks >= info1.ticks - 50 && info2.ticks <= info1.ticks
+ 50;
todo_wine
@@ -1531,14 +1631,12 @@ static void CALLBACK wait_cb(TP_CALLBACK_INSTANCE *instance, void
*userdata,
TP_WAIT *wait, TP_WAIT_RESULT result)
{
struct wait_info *info = userdata;
- trace("Running wait callback\n");
-
if (result == WAIT_OBJECT_0)
InterlockedIncrement(&info->userdata);
else if (result == WAIT_TIMEOUT)
InterlockedExchangeAdd(&info->userdata, 0x10000);
else
- ok(0, "unexpected result %u\n", result);
+ ok(0, "unexpected result %lu\n", result);
ReleaseSemaphore(info->semaphore, 1, NULL);
}
@@ -1562,7 +1660,7 @@ static void test_tp_wait(void)
/* allocate new threadpool */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
/* allocate new wait items */
@@ -1572,12 +1670,12 @@ static void test_tp_wait(void)
wait1 = NULL;
status = pTpAllocWait(&wait1, wait_cb, &info, &environment);
- ok(!status, "TpAllocWait failed with status %x\n", status);
+ ok(!status, "TpAllocWait failed with status %lx\n", status);
ok(wait1 != NULL, "expected wait1 != NULL\n");
wait2 = NULL;
status = pTpAllocWait(&wait2, wait_cb, &info, &environment);
- ok(!status, "TpAllocWait failed with status %x\n", status);
+ ok(!status, "TpAllocWait failed with status %lx\n", status);
ok(wait2 != NULL, "expected wait2 != NULL\n");
/* infinite timeout, signal the semaphore immediately */
@@ -1585,79 +1683,79 @@ static void test_tp_wait(void)
pTpSetWait(wait1, semaphores[1], NULL);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* relative timeout, no event */
info.userdata = 0;
when.QuadPart = (ULONGLONG)200 * -10000;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[0], 200);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* repeat test with call to TpWaitForWait(..., TRUE) */
info.userdata = 0;
when.QuadPart = (ULONGLONG)200 * -10000;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
pTpWaitForWait(wait1, TRUE);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[0], 200);
ok(result == WAIT_OBJECT_0 || broken(result == WAIT_TIMEOUT) /* Win 8 */,
- "WaitForSingleObject returned %u\n", result);
+ "WaitForSingleObject returned %lu\n", result);
if (result == WAIT_OBJECT_0)
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got
%u\n", info.userdata);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got
%lu\n", info.userdata);
else
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* relative timeout, with event */
info.userdata = 0;
when.QuadPart = (ULONGLONG)200 * -10000;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* repeat test with call to TpWaitForWait(..., TRUE) */
info.userdata = 0;
when.QuadPart = (ULONGLONG)200 * -10000;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
pTpWaitForWait(wait1, TRUE);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
ok(result == WAIT_OBJECT_0 || broken(result == WAIT_TIMEOUT) /* Win 8 */,
- "WaitForSingleObject returned %u\n", result);
+ "WaitForSingleObject returned %lu\n", result);
if (result == WAIT_OBJECT_0)
{
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n",
result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n",
result);
}
else
{
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n",
result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
}
/* absolute timeout, no event */
@@ -1666,13 +1764,13 @@ static void test_tp_wait(void)
when.QuadPart += (ULONGLONG)200 * 10000;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[0], 200);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* absolute timeout, with event */
info.userdata = 0;
@@ -1680,63 +1778,63 @@ static void test_tp_wait(void)
when.QuadPart += (ULONGLONG)200 * 10000;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* test timeout of zero */
info.userdata = 0;
when.QuadPart = 0;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* cancel a pending wait */
info.userdata = 0;
when.QuadPart = (ULONGLONG)250 * -10000;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
pTpSetWait(wait1, NULL, (void *)0xdeadbeef);
Sleep(50);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0, "expected info.userdata = 0, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
/* test with INVALID_HANDLE_VALUE */
info.userdata = 0;
when.QuadPart = 0;
pTpSetWait(wait1, INVALID_HANDLE_VALUE, &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
/* cancel a pending wait with INVALID_HANDLE_VALUE */
info.userdata = 0;
when.QuadPart = (ULONGLONG)250 * -10000;
pTpSetWait(wait1, semaphores[1], &when);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
when.QuadPart = 0;
pTpSetWait(wait1, INVALID_HANDLE_VALUE, &when);
Sleep(50);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
CloseHandle(semaphores[1]);
semaphores[1] = CreateSemaphoreW(NULL, 0, 2, NULL);
@@ -1749,12 +1847,12 @@ static void test_tp_wait(void)
Sleep(50);
ReleaseSemaphore(semaphores[1], 1, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 1, "expected info.userdata = 1, got %u\n",
info.userdata);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* repeat test above with release count 2 */
info.userdata = 0;
@@ -1763,12 +1861,12 @@ static void test_tp_wait(void)
Sleep(50);
result = ReleaseSemaphore(semaphores[1], 2, NULL);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
result = WaitForSingleObject(semaphores[0], 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
- ok(info.userdata == 2, "expected info.userdata = 2, got %u\n",
info.userdata);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(info.userdata == 2, "expected info.userdata = 2, got %lu\n",
info.userdata);
result = WaitForSingleObject(semaphores[1], 0);
- ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %lu\n", result);
/* cleanup */
pTpReleaseWait(wait1);
@@ -1793,12 +1891,13 @@ static void CALLBACK multi_wait_cb(TP_CALLBACK_INSTANCE *instance,
void *userdat
else if (result == WAIT_TIMEOUT)
multi_wait_info.result = 0x10000 | index;
else
- ok(0, "unexpected result %u\n", result);
+ ok(0, "unexpected result %lu\n", result);
ReleaseSemaphore(multi_wait_info.semaphore, 1, NULL);
}
static void test_tp_multi_wait(void)
{
+ TP_POOL_STACK_INFORMATION stack_info;
TP_CALLBACK_ENVIRON environment;
HANDLE semaphores[512];
TP_WAIT *waits[512];
@@ -1816,78 +1915,83 @@ static void test_tp_multi_wait(void)
/* allocate new threadpool */
pool = NULL;
status = pTpAllocPool(&pool, NULL);
- ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(!status, "TpAllocPool failed with status %lx\n", status);
ok(pool != NULL, "expected pool != NULL\n");
+ /* many threads -> use the smallest stack possible */
+ stack_info.StackReserve = 256 * 1024;
+ stack_info.StackCommit = 4 * 1024;
+ status = pTpSetPoolStackInformation(pool, &stack_info);
+ ok(!status, "TpQueryPoolStackInformation failed: %lx\n", status);
memset(&environment, 0, sizeof(environment));
environment.Version = 1;
environment.Pool = pool;
/* create semaphores and corresponding wait objects */
- for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(semaphores); i++)
{
semaphores[i] = CreateSemaphoreW(NULL, 0, 1, NULL);
ok(semaphores[i] != NULL, "failed to create semaphore %i\n", i);
waits[i] = NULL;
status = pTpAllocWait(&waits[i], multi_wait_cb, (void *)(DWORD_PTR)i,
&environment);
- ok(!status, "TpAllocWait failed with status %x\n", status);
+ ok(!status, "TpAllocWait failed with status %lx\n", status);
ok(waits[i] != NULL, "expected waits[%d] != NULL\n", i);
pTpSetWait(waits[i], semaphores[i], NULL);
}
/* release all semaphores and wait for callback */
- for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(semaphores); i++)
{
multi_wait_info.result = 0;
ReleaseSemaphore(semaphores[i], 1, NULL);
- result = WaitForSingleObject(semaphore, 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n",
result);
- ok(multi_wait_info.result == i, "expected result %d, got %u\n", i,
multi_wait_info.result);
+ result = WaitForSingleObject(semaphore, 2000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(multi_wait_info.result == i, "expected result %d, got %lu\n", i,
multi_wait_info.result);
pTpSetWait(waits[i], semaphores[i], NULL);
}
/* repeat the same test in reverse order */
- for (i = sizeof(semaphores)/sizeof(semaphores[0]) - 1; i >= 0; i--)
+ for (i = ARRAY_SIZE(semaphores) - 1; i >= 0; i--)
{
multi_wait_info.result = 0;
ReleaseSemaphore(semaphores[i], 1, NULL);
- result = WaitForSingleObject(semaphore, 100);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n",
result);
- ok(multi_wait_info.result == i, "expected result %d, got %u\n", i,
multi_wait_info.result);
+ result = WaitForSingleObject(semaphore, 2000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
+ ok(multi_wait_info.result == i, "expected result %d, got %lu\n", i,
multi_wait_info.result);
pTpSetWait(waits[i], semaphores[i], NULL);
}
/* test timeout of wait objects */
multi_wait_info.result = 0;
- for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(semaphores); i++)
{
when.QuadPart = (ULONGLONG)50 * -10000;
pTpSetWait(waits[i], semaphores[i], &when);
}
- for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(semaphores); i++)
{
- result = WaitForSingleObject(semaphore, 150);
- ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n",
result);
+ result = WaitForSingleObject(semaphore, 2000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n",
result);
}
ok(multi_wait_info.result >> 16, "expected multi_wait_info.result >>
16 != 0\n");
/* destroy the wait objects and semaphores while waiting */
- for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(semaphores); i++)
{
pTpSetWait(waits[i], semaphores[i], NULL);
}
Sleep(50);
- for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(semaphores); i++)
{
pTpReleaseWait(waits[i]);
NtClose(semaphores[i]);
@@ -1897,6 +2001,385 @@ static void test_tp_multi_wait(void)
CloseHandle(semaphore);
}
+struct io_cb_ctx
+{
+ unsigned int count;
+ void *ovl;
+ NTSTATUS ret;
+ ULONG_PTR length;
+ TP_IO *io;
+};
+
+static void CALLBACK io_cb(TP_CALLBACK_INSTANCE *instance, void *userdata,
+ void *cvalue, IO_STATUS_BLOCK *iosb, TP_IO *io)
+{
+ struct io_cb_ctx *ctx = userdata;
+ ++ctx->count;
+ ctx->ovl = cvalue;
+ ctx->ret = iosb->Status;
+ ctx->length = iosb->Information;
+ ctx->io = io;
+}
+
+static DWORD WINAPI io_wait_thread(void *arg)
+{
+ TP_IO *io = arg;
+ pTpWaitForIoCompletion(io, FALSE);
+ return 0;
+}
+
+static void test_tp_io(void)
+{
+ TP_CALLBACK_ENVIRON environment = {.Version = 1};
+ OVERLAPPED ovl = {}, ovl2 = {};
+ HANDLE client, server, thread;
+ struct io_cb_ctx userdata;
+ char in[1], in2[1];
+ const char out[1];
+ NTSTATUS status;
+ DWORD ret_size;
+ TP_POOL *pool;
+ TP_IO *io;
+ BOOL ret;
+
+ ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+ status = pTpAllocPool(&pool, NULL);
+ ok(!status, "failed to allocate pool, status %#lx\n", status);
+
+ server = CreateNamedPipeA("\\\\.\\pipe\\wine_tp_test",
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL);
+ ok(server != INVALID_HANDLE_VALUE, "Failed to create server pipe, error
%lu.\n", GetLastError());
+ client = CreateFileA("\\\\.\\pipe\\wine_tp_test", GENERIC_READ |
GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(client != INVALID_HANDLE_VALUE, "Failed to create client pipe, error
%lu.\n", GetLastError());
+
+ environment.Pool = pool;
+ io = NULL;
+ status = pTpAllocIoCompletion(&io, server, io_cb, &userdata,
&environment);
+ ok(!status, "got %#lx\n", status);
+ ok(!!io, "expected non-NULL TP_IO\n");
+
+ pTpWaitForIoCompletion(io, FALSE);
+
+ userdata.count = 0;
+ pTpStartAsyncIoOperation(io);
+
+ thread = CreateThread(NULL, 0, io_wait_thread, io, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "TpWaitForIoCompletion()
should not return\n");
+
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+
+ pTpWaitForIoCompletion(io, FALSE);
+ ok(userdata.count == 1, "callback ran %u times\n", userdata.count);
+ ok(userdata.ovl == &ovl, "expected %p, got %p\n", &ovl,
userdata.ovl);
+ ok(userdata.ret == STATUS_SUCCESS, "got status %#lx\n", userdata.ret);
+ ok(userdata.length == 1, "got length %Iu\n", userdata.length);
+ ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
+
+ ok(!WaitForSingleObject(thread, 1000), "wait timed out\n");
+ CloseHandle(thread);
+
+ userdata.count = 0;
+ pTpStartAsyncIoOperation(io);
+ pTpStartAsyncIoOperation(io);
+
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+ ret = ReadFile(server, in2, sizeof(in2), NULL, &ovl2);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+
+ pTpWaitForIoCompletion(io, FALSE);
+ ok(userdata.count == 2, "callback ran %u times\n", userdata.count);
+ ok(userdata.ret == STATUS_SUCCESS, "got status %#lx\n", userdata.ret);
+ ok(userdata.length == 1, "got length %Iu\n", userdata.length);
+ ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
+
+ /* The documentation is a bit unclear about passing TRUE to
+ * WaitForThreadpoolIoCallbacks()—"pending I/O requests are not canceled"
+ * [as with CancelIoEx()], but pending threadpool callbacks are, even those
+ * which have not yet reached the completion port [as with
+ * TpCancelAsyncIoOperation()]. */
+ userdata.count = 0;
+ pTpStartAsyncIoOperation(io);
+
+ pTpWaitForIoCompletion(io, TRUE);
+ ok(!userdata.count, "callback ran %u times\n", userdata.count);
+
+ pTpStartAsyncIoOperation(io);
+
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(ret, "wrong ret %d\n", ret);
+
+ pTpWaitForIoCompletion(io, FALSE);
+ ok(userdata.count == 1, "callback ran %u times\n", userdata.count);
+ ok(userdata.ovl == &ovl, "expected %p, got %p\n", &ovl,
userdata.ovl);
+ ok(userdata.ret == STATUS_SUCCESS, "got status %#lx\n", userdata.ret);
+ ok(userdata.length == 1, "got length %Iu\n", userdata.length);
+ ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
+
+ userdata.count = 0;
+ pTpStartAsyncIoOperation(io);
+
+ ret = ReadFile(server, NULL, 1, NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_NOACCESS, "wrong error %lu\n",
GetLastError());
+
+ pTpCancelAsyncIoOperation(io);
+ pTpWaitForIoCompletion(io, FALSE);
+ ok(!userdata.count, "callback ran %u times\n", userdata.count);
+
+ userdata.count = 0;
+ pTpStartAsyncIoOperation(io);
+
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+ ret = CancelIo(server);
+ ok(ret, "CancelIo() failed, error %lu\n", GetLastError());
+
+ pTpWaitForIoCompletion(io, FALSE);
+ ok(userdata.count == 1, "callback ran %u times\n", userdata.count);
+ ok(userdata.ovl == &ovl, "expected %p, got %p\n", &ovl,
userdata.ovl);
+ ok(userdata.ret == STATUS_CANCELLED, "got status %#lx\n", userdata.ret);
+ ok(!userdata.length, "got length %Iu\n", userdata.length);
+ ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
+
+ userdata.count = 0;
+ pTpStartAsyncIoOperation(io);
+ pTpCancelAsyncIoOperation(io);
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+
+ pTpWaitForIoCompletion(io, FALSE);
+ if (0)
+ {
+ /* Add a sleep to check that callback is not called later. Commented out to
+ * save the test time. */
+ Sleep(200);
+ }
+ ok(userdata.count == 0, "callback ran %u times\n", userdata.count);
+
+ pTpReleaseIoCompletion(io);
+ CloseHandle(server);
+
+ /* Test TPIO object destruction. */
+ server = CreateNamedPipeA("\\\\.\\pipe\\wine_tp_test",
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL);
+ ok(server != INVALID_HANDLE_VALUE, "Failed to create server pipe, error
%lu.\n", GetLastError());
+ io = NULL;
+ status = pTpAllocIoCompletion(&io, server, io_cb, &userdata,
&environment);
+ ok(!status, "got %#lx\n", status);
+
+ ret = HeapValidate(GetProcessHeap(), 0, io);
+ ok(ret, "Got unexpected ret %#x.\n", ret);
+ pTpReleaseIoCompletion(io);
+ ret = HeapValidate(GetProcessHeap(), 0, io);
+ ok(!ret, "Got unexpected ret %#x.\n", ret);
+ CloseHandle(server);
+ CloseHandle(client);
+
+ server = CreateNamedPipeA("\\\\.\\pipe\\wine_tp_test",
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL);
+ ok(server != INVALID_HANDLE_VALUE, "Failed to create server pipe, error
%lu.\n", GetLastError());
+ client = CreateFileA("\\\\.\\pipe\\wine_tp_test", GENERIC_READ |
GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(client != INVALID_HANDLE_VALUE, "Failed to create client pipe, error
%lu.\n", GetLastError());
+
+ io = NULL;
+ status = pTpAllocIoCompletion(&io, server, io_cb, &userdata,
&environment);
+ ok(!status, "got %#lx\n", status);
+ pTpStartAsyncIoOperation(io);
+ pTpWaitForIoCompletion(io, TRUE);
+ ret = HeapValidate(GetProcessHeap(), 0, io);
+ ok(ret, "Got unexpected ret %#x.\n", ret);
+ pTpReleaseIoCompletion(io);
+ ret = HeapValidate(GetProcessHeap(), 0, io);
+ ok(ret, "Got unexpected ret %#x.\n", ret);
+
+ if (0)
+ {
+ /* Object destruction will wait until one completion arrives (which was started
but not cancelled).
+ * Commented out to save test time. */
+ Sleep(1000);
+ ret = HeapValidate(GetProcessHeap(), 0, io);
+ ok(ret, "Got unexpected ret %#x.\n", ret);
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+ Sleep(2000);
+ ret = HeapValidate(GetProcessHeap(), 0, io);
+ ok(!ret, "Got unexpected ret %#x.\n", ret);
+ }
+
+ CloseHandle(server);
+ CloseHandle(ovl.hEvent);
+ CloseHandle(client);
+ pTpReleasePool(pool);
+}
+
+static void CALLBACK kernel32_io_cb(TP_CALLBACK_INSTANCE *instance, void *userdata,
+ void *ovl, ULONG ret, ULONG_PTR length, TP_IO *io)
+{
+ struct io_cb_ctx *ctx = userdata;
+ ++ctx->count;
+ ctx->ovl = ovl;
+ ctx->ret = ret;
+ ctx->length = length;
+ ctx->io = io;
+}
+
+static void test_kernel32_tp_io(void)
+{
+ TP_CALLBACK_ENVIRON environment = {.Version = 1};
+ OVERLAPPED ovl = {}, ovl2 = {};
+ HANDLE client, server, thread;
+ struct io_cb_ctx userdata;
+ char in[1], in2[1];
+ const char out[1];
+ NTSTATUS status;
+ DWORD ret_size;
+ TP_POOL *pool;
+ TP_IO *io;
+ BOOL ret;
+
+ ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+ status = pTpAllocPool(&pool, NULL);
+ ok(!status, "failed to allocate pool, status %#lx\n", status);
+
+ server = CreateNamedPipeA("\\\\.\\pipe\\wine_tp_test",
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL);
+ ok(server != INVALID_HANDLE_VALUE, "Failed to create server pipe, error
%lu.\n", GetLastError());
+ client = CreateFileA("\\\\.\\pipe\\wine_tp_test", GENERIC_READ |
GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(client != INVALID_HANDLE_VALUE, "Failed to create client pipe, error
%lu.\n", GetLastError());
+
+ environment.Pool = pool;
+ io = NULL;
+ io = pCreateThreadpoolIo(server, kernel32_io_cb, &userdata, &environment);
+ ok(!!io, "expected non-NULL TP_IO\n");
+
+ pWaitForThreadpoolIoCallbacks(io, FALSE);
+
+ userdata.count = 0;
+ pStartThreadpoolIo(io);
+
+ thread = CreateThread(NULL, 0, io_wait_thread, io, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "TpWaitForIoCompletion()
should not return\n");
+
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+
+ pWaitForThreadpoolIoCallbacks(io, FALSE);
+ ok(userdata.count == 1, "callback ran %u times\n", userdata.count);
+ ok(userdata.ovl == &ovl, "expected %p, got %p\n", &ovl,
userdata.ovl);
+ ok(userdata.ret == ERROR_SUCCESS, "got status %#lx\n", userdata.ret);
+ ok(userdata.length == 1, "got length %Iu\n", userdata.length);
+ ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
+
+ ok(!WaitForSingleObject(thread, 1000), "wait timed out\n");
+ CloseHandle(thread);
+
+ userdata.count = 0;
+ pStartThreadpoolIo(io);
+ pStartThreadpoolIo(io);
+
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+ ret = ReadFile(server, in2, sizeof(in2), NULL, &ovl2);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+
+ pWaitForThreadpoolIoCallbacks(io, FALSE);
+ ok(userdata.count == 2, "callback ran %u times\n", userdata.count);
+ ok(userdata.ret == STATUS_SUCCESS, "got status %#lx\n", userdata.ret);
+ ok(userdata.length == 1, "got length %Iu\n", userdata.length);
+ ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
+
+ userdata.count = 0;
+ pStartThreadpoolIo(io);
+ pWaitForThreadpoolIoCallbacks(io, TRUE);
+ ok(!userdata.count, "callback ran %u times\n", userdata.count);
+
+ pStartThreadpoolIo(io);
+
+ ret = WriteFile(client, out, sizeof(out), &ret_size, NULL);
+ ok(ret, "WriteFile() failed, error %lu\n", GetLastError());
+
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(ret, "wrong ret %d\n", ret);
+
+ pWaitForThreadpoolIoCallbacks(io, FALSE);
+ ok(userdata.count == 1, "callback ran %u times\n", userdata.count);
+ ok(userdata.ovl == &ovl, "expected %p, got %p\n", &ovl,
userdata.ovl);
+ ok(userdata.ret == ERROR_SUCCESS, "got status %#lx\n", userdata.ret);
+ ok(userdata.length == 1, "got length %Iu\n", userdata.length);
+ ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
+
+ userdata.count = 0;
+ pStartThreadpoolIo(io);
+
+ ret = ReadFile(server, NULL, 1, NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_NOACCESS, "wrong error %lu\n",
GetLastError());
+
+ pCancelThreadpoolIo(io);
+ pWaitForThreadpoolIoCallbacks(io, FALSE);
+ ok(!userdata.count, "callback ran %u times\n", userdata.count);
+
+ userdata.count = 0;
+ pStartThreadpoolIo(io);
+
+ ret = ReadFile(server, in, sizeof(in), NULL, &ovl);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_IO_PENDING, "wrong error %lu\n",
GetLastError());
+ ret = CancelIo(server);
+ ok(ret, "CancelIo() failed, error %lu\n", GetLastError());
+
+ pWaitForThreadpoolIoCallbacks(io, FALSE);
+ ok(userdata.count == 1, "callback ran %u times\n", userdata.count);
+ ok(userdata.ovl == &ovl, "expected %p, got %p\n", &ovl,
userdata.ovl);
+ ok(userdata.ret == ERROR_OPERATION_ABORTED, "got status %#lx\n",
userdata.ret);
+ ok(!userdata.length, "got length %Iu\n", userdata.length);
+ ok(userdata.io == io, "expected %p, got %p\n", io, userdata.io);
+
+ CloseHandle(ovl.hEvent);
+ CloseHandle(client);
+ CloseHandle(server);
+ pCloseThreadpoolIo(io);
+ pTpReleasePool(pool);
+}
+
START_TEST(threadpool)
{
test_RtlQueueWorkItem();
@@ -1916,4 +2399,6 @@ START_TEST(threadpool)
test_tp_window_length();
test_tp_wait();
test_tp_multi_wait();
+ test_tp_io();
+ test_kernel32_tp_io();
}