ReactOS 0.4.17-dev-37-g0bfb40d
sync.c
Go to the documentation of this file.
1/*
2 * Unit tests for NT synchronization objects
3 *
4 * Copyright 2020 Zebediah Figura
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdarg.h>
22
23#include "ntstatus.h"
24#define WIN32_NO_STATUS
25#include "windef.h"
26#include "winternl.h"
27#include "wine/test.h"
28
29#if defined (__REACTOS__) && (DLL_EXPORT_VERSION < 0x601)
30static
33NtRemoveIoCompletionEx_(
34 _In_ HANDLE IoCompletionHandle,
35 _Out_writes_to_(Count, *NumEntriesRemoved) PFILE_IO_COMPLETION_INFORMATION IoCompletionInformation,
37 _Out_ PULONG NumEntriesRemoved,
40{
41 // HACK!
42 *NumEntriesRemoved = Count;
43 return NtRemoveIoCompletion(IoCompletionHandle,
44 &IoCompletionInformation[0].CompletionKey,
45 &IoCompletionInformation[0].CompletionValue,
46 &IoCompletionInformation[0].IoStatusBlock,
47 Timeout);
48}
49#define NtRemoveIoCompletionEx NtRemoveIoCompletionEx_
50#endif
51
52static NTSTATUS (WINAPI *pNtAlertThreadByThreadId)( HANDLE );
53static NTSTATUS (WINAPI *pNtClose)( HANDLE );
54static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const OBJECT_ATTRIBUTES *, EVENT_TYPE, BOOLEAN);
55static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
56static NTSTATUS (WINAPI *pNtCreateMutant)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, BOOLEAN );
57static NTSTATUS (WINAPI *pNtCreateSemaphore)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, LONG, LONG );
58static NTSTATUS (WINAPI *pNtOpenEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
59static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
60static NTSTATUS (WINAPI *pNtPulseEvent)( HANDLE, LONG * );
61static NTSTATUS (WINAPI *pNtQueryEvent)( HANDLE, EVENT_INFORMATION_CLASS, void *, ULONG, ULONG * );
62static NTSTATUS (WINAPI *pNtQueryMutant)( HANDLE, MUTANT_INFORMATION_CLASS, void *, ULONG, ULONG * );
63static NTSTATUS (WINAPI *pNtQuerySemaphore)( HANDLE, SEMAPHORE_INFORMATION_CLASS, void *, ULONG, ULONG * );
64static NTSTATUS (WINAPI *pNtQuerySystemTime)( LARGE_INTEGER * );
65static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
66static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * );
67static NTSTATUS (WINAPI *pNtReleaseSemaphore)( HANDLE, ULONG, ULONG * );
68static NTSTATUS (WINAPI *pNtResetEvent)( HANDLE, LONG * );
69static NTSTATUS (WINAPI *pNtSetEvent)( HANDLE, LONG * );
70static NTSTATUS (WINAPI *pNtWaitForAlertByThreadId)( void *, const LARGE_INTEGER * );
71static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
72static BOOLEAN (WINAPI *pRtlAcquireResourceExclusive)( RTL_RWLOCK *, BOOLEAN );
73static BOOLEAN (WINAPI *pRtlAcquireResourceShared)( RTL_RWLOCK *, BOOLEAN );
74static void (WINAPI *pRtlDeleteResource)( RTL_RWLOCK * );
75static void (WINAPI *pRtlInitializeResource)( RTL_RWLOCK * );
76static void (WINAPI *pRtlInitUnicodeString)( UNICODE_STRING *, const WCHAR * );
77static void (WINAPI *pRtlReleaseResource)( RTL_RWLOCK * );
78static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * );
79static void (WINAPI *pRtlWakeAddressAll)( const void * );
80static void (WINAPI *pRtlWakeAddressSingle)( const void * );
81
82#define KEYEDEVENT_WAIT 0x0001
83#define KEYEDEVENT_WAKE 0x0002
84#define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x0003)
85
86static void test_event(void)
87{
89 HANDLE event2;
90 LONG prev_state = 0xdeadbeef;
95
96 pRtlInitUnicodeString( &str, L"\\BaseNamedObjects\\testEvent" );
98
99 status = pNtCreateEvent(&event, GENERIC_ALL, &attr, 2, 0);
100 ok( status == STATUS_INVALID_PARAMETER, "NtCreateEvent failed %08lx\n", status );
101
102 status = pNtCreateEvent(&event, GENERIC_ALL, &attr, NotificationEvent, 0);
103 ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08lx\n", status );
104 memset(&info, 0xcc, sizeof(info));
105 status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
106 ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08lx\n", status );
107 ok( info.EventType == NotificationEvent && info.EventState == 0,
108 "NtQueryEvent failed, expected 0 0, got %d %ld\n", info.EventType, info.EventState );
109 pNtClose(event);
110
111 status = pNtCreateEvent(&event, GENERIC_ALL, &attr, SynchronizationEvent, 0);
112 ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08lx\n", status );
113
114 status = pNtPulseEvent(event, &prev_state);
115 ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08lx\n", status );
116 ok( !prev_state, "prev_state = %lx\n", prev_state );
117
118 memset(&info, 0xcc, sizeof(info));
119 status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
120 ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08lx\n", status );
121 ok( info.EventType == SynchronizationEvent && info.EventState == 0,
122 "NtQueryEvent failed, expected 1 0, got %d %ld\n", info.EventType, info.EventState );
123
124 status = pNtOpenEvent(&event2, GENERIC_ALL, &attr);
125 ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08lx\n", status );
126
127 pNtClose(event);
128 event = event2;
129
130 memset(&info, 0xcc, sizeof(info));
131 status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
132 ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08lx\n", status );
133 ok( info.EventType == SynchronizationEvent && info.EventState == 0,
134 "NtQueryEvent failed, expected 1 0, got %d %ld\n", info.EventType, info.EventState );
135
136 status = pNtSetEvent( event, &prev_state );
137 ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08lx\n", status );
138 ok( !prev_state, "prev_state = %lx\n", prev_state );
139
140 memset(&info, 0xcc, sizeof(info));
141 status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
142 ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08lx\n", status );
143 ok( info.EventType == SynchronizationEvent && info.EventState == 1,
144 "NtQueryEvent failed, expected 1 1, got %d %ld\n", info.EventType, info.EventState );
145
146 status = pNtSetEvent( event, &prev_state );
147 ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08lx\n", status );
148 ok( prev_state == 1, "prev_state = %lx\n", prev_state );
149
150 status = pNtResetEvent( event, &prev_state );
151 ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08lx\n", status );
152 ok( prev_state == 1, "prev_state = %lx\n", prev_state );
153
154 status = pNtResetEvent( event, &prev_state );
155 ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08lx\n", status );
156 ok( !prev_state, "prev_state = %lx\n", prev_state );
157
158 status = pNtPulseEvent( event, &prev_state );
159 ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08lx\n", status );
160 ok( !prev_state, "prev_state = %lx\n", prev_state );
161
162 status = pNtSetEvent( event, &prev_state );
163 ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08lx\n", status );
164 ok( !prev_state, "prev_state = %lx\n", prev_state );
165
166 status = pNtPulseEvent( event, &prev_state );
167 ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08lx\n", status );
168 ok( prev_state == 1, "prev_state = %lx\n", prev_state );
169
170 pNtClose(event);
171}
172
173static const WCHAR keyed_nameW[] = L"\\BaseNamedObjects\\WineTestEvent";
174
176{
182 ULONG_PTR i;
183
184 attr.Length = sizeof(attr);
185 attr.RootDirectory = 0;
186 attr.ObjectName = &str;
187 attr.Attributes = 0;
188 attr.SecurityDescriptor = NULL;
189 attr.SecurityQualityOfService = NULL;
191
192 status = pNtOpenKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr );
193 ok( !status, "NtOpenKeyedEvent failed %lx\n", status );
194
195 for (i = 0; i < 20; i++)
196 {
197 if (i & 1)
198 status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
199 else
200 status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
201 ok( status == STATUS_SUCCESS, "%Ii: failed %lx\n", i, status );
202 Sleep( 20 - i );
203 }
204
205 status = pNtReleaseKeyedEvent( handle, (void *)0x1234, 0, NULL );
206 ok( status == STATUS_SUCCESS, "NtReleaseKeyedEvent %lx\n", status );
207
208 timeout.QuadPart = -10000;
209 status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
210 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %lx\n", status );
211 status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
212 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %lx\n", status );
213
214 NtClose( handle );
215 return 0;
216}
217
218static void test_keyed_events(void)
219{
225 ULONG_PTR i;
226
227 if (!pNtCreateKeyedEvent)
228 {
229 win_skip( "Keyed events not supported\n" );
230 return;
231 }
232
233 attr.Length = sizeof(attr);
234 attr.RootDirectory = 0;
235 attr.ObjectName = &str;
236 attr.Attributes = 0;
237 attr.SecurityDescriptor = NULL;
238 attr.SecurityQualityOfService = NULL;
240
241 status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS | SYNCHRONIZE, &attr, 0 );
242 ok( !status, "NtCreateKeyedEvent failed %lx\n", status );
243
245 ok( status == 0, "WaitForSingleObject %lx\n", status );
246
247 timeout.QuadPart = -100000;
248 status = pNtWaitForKeyedEvent( handle, (void *)255, 0, &timeout );
249 ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %lx\n", status );
250 status = pNtReleaseKeyedEvent( handle, (void *)255, 0, &timeout );
251 ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %lx\n", status );
252
253 status = pNtWaitForKeyedEvent( handle, (void *)254, 0, &timeout );
254 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %lx\n", status );
255 status = pNtReleaseKeyedEvent( handle, (void *)254, 0, &timeout );
256 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %lx\n", status );
257
258 status = pNtWaitForKeyedEvent( handle, NULL, 0, &timeout );
259 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %lx\n", status );
260 status = pNtReleaseKeyedEvent( handle, NULL, 0, &timeout );
261 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %lx\n", status );
262
263 status = pNtWaitForKeyedEvent( NULL, (void *)8, 0, &timeout );
265 "NtWaitForKeyedEvent %lx\n", status );
266 status = pNtReleaseKeyedEvent( NULL, (void *)8, 0, &timeout );
268 "NtReleaseKeyedEvent %lx\n", status );
269
270 status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
271 ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %lx\n", status );
272 status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
273 ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %lx\n", status );
274
275 status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
276 ok( status == STATUS_INVALID_HANDLE, "NtWaitForKeyedEvent %lx\n", status );
277 status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
278 ok( status == STATUS_INVALID_HANDLE, "NtReleaseKeyedEvent %lx\n", status );
279
281 for (i = 0; i < 20; i++)
282 {
283 if (i & 1)
284 status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
285 else
286 status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
287 ok( status == STATUS_SUCCESS, "%Ii: failed %lx\n", i, status );
288 Sleep( i );
289 }
290 status = pNtWaitForKeyedEvent( handle, (void *)0x1234, 0, &timeout );
291 ok( status == STATUS_SUCCESS, "NtWaitForKeyedEvent %lx\n", status );
292 status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
293 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %lx\n", status );
294 status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
295 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %lx\n", status );
296
297 ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" );
298
299 NtClose( handle );
300
301 /* test access rights */
302
303 status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAIT, &attr, 0 );
304 ok( !status, "NtCreateKeyedEvent failed %lx\n", status );
305 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
306 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %lx\n", status );
307 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
308 ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %lx\n", status );
309 NtClose( handle );
310
311 status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAKE, &attr, 0 );
312 ok( !status, "NtCreateKeyedEvent failed %lx\n", status );
313 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
314 ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %lx\n", status );
315 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
316 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %lx\n", status );
317 NtClose( handle );
318
319 status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr, 0 );
320 ok( !status, "NtCreateKeyedEvent failed %lx\n", status );
323 "WaitForSingleObject %lx err %lu\n", status, GetLastError() );
324 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
325 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %lx\n", status );
326 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
327 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %lx\n", status );
328 NtClose( handle );
329
330 /* GENERIC_READ gives wait access */
331 status = pNtCreateKeyedEvent( &handle, GENERIC_READ, &attr, 0 );
332 ok( !status, "NtCreateKeyedEvent failed %lx\n", status );
333 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
334 ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %lx\n", status );
335 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
336 ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %lx\n", status );
337 NtClose( handle );
338
339 /* GENERIC_WRITE gives wake access */
340 status = pNtCreateKeyedEvent( &handle, GENERIC_WRITE, &attr, 0 );
341 ok( !status, "NtCreateKeyedEvent failed %lx\n", status );
342 status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
343 ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %lx\n", status );
344 status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
345 ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %lx\n", status );
346
347 /* it's not an event */
348 status = pNtPulseEvent( handle, NULL );
349 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %lx\n", status );
350
351 status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
353 "CreateEvent %lx\n", status );
354
355 NtClose( handle );
356
357 status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
358 ok( status == 0, "CreateEvent %lx\n", status );
359 status = pNtWaitForKeyedEvent( event, (void *)8, 0, &timeout );
360 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtWaitForKeyedEvent %lx\n", status );
361 status = pNtReleaseKeyedEvent( event, (void *)8, 0, &timeout );
362 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtReleaseKeyedEvent %lx\n", status );
363 NtClose( event );
364}
365
367{
370 HANDLE mutant;
371 DWORD ret;
372
373 mutant = arg;
374 ret = WaitForSingleObject( mutant, 1000 );
375 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08lx\n", ret );
376
377 memset(&info, 0xcc, sizeof(info));
378 status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
379 ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08lx\n", status );
380 ok( info.CurrentCount == 0, "expected 0, got %ld\n", info.CurrentCount );
381 ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
382 ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
383 /* abandon mutant */
384
385 return 0;
386}
387
388static void test_mutant(void)
389{
394 HANDLE mutant;
396 DWORD ret;
397 ULONG len;
398 LONG prev;
399
400 pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_mutant");
402 status = pNtCreateMutant(&mutant, GENERIC_ALL, &attr, TRUE);
403 ok( status == STATUS_SUCCESS, "Failed to create Mutant(%08lx)\n", status );
404
405 /* bogus */
406 status = pNtQueryMutant(mutant, MutantBasicInformation, &info, 0, NULL);
408 "Failed to NtQueryMutant, expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
409 status = pNtQueryMutant(mutant, 0x42, &info, sizeof(info), NULL);
410 ok( status == STATUS_INVALID_INFO_CLASS || broken(status == STATUS_NOT_IMPLEMENTED), /* 32-bit on Vista/2k8 */
411 "Failed to NtQueryMutant, expected STATUS_INVALID_INFO_CLASS, got %08lx\n", status );
412 status = pNtQueryMutant((HANDLE)0xdeadbeef, MutantBasicInformation, &info, sizeof(info), NULL);
414 "Failed to NtQueryMutant, expected STATUS_INVALID_HANDLE, got %08lx\n", status );
415
416 /* new */
417 len = -1;
418 memset(&info, 0xcc, sizeof(info));
419 status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), &len);
420 ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08lx\n", status );
421 ok( info.CurrentCount == 0, "expected 0, got %ld\n", info.CurrentCount );
422 ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
423 ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
424 ok( len == sizeof(info), "got %lu\n", len );
425
426 ret = WaitForSingleObject( mutant, 1000 );
427 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08lx\n", ret );
428
429 memset(&info, 0xcc, sizeof(info));
430 status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
431 ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08lx\n", status );
432 ok( info.CurrentCount == -1, "expected -1, got %ld\n", info.CurrentCount );
433 ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
434 ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
435
436 prev = 0xdeadbeef;
437 status = pNtReleaseMutant(mutant, &prev);
438 ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08lx\n", status );
439 ok( prev == -1, "NtReleaseMutant failed, expected -1, got %ld\n", prev );
440
441 prev = 0xdeadbeef;
442 status = pNtReleaseMutant(mutant, &prev);
443 ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08lx\n", status );
444 ok( prev == 0, "NtReleaseMutant failed, expected 0, got %ld\n", prev );
445
446 memset(&info, 0xcc, sizeof(info));
447 status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
448 ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08lx\n", status );
449 ok( info.CurrentCount == 1, "expected 1, got %ld\n", info.CurrentCount );
450 ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
451 ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
452
453 /* abandoned */
454 thread = CreateThread( NULL, 0, mutant_thread, mutant, 0, NULL );
455 ret = WaitForSingleObject( thread, 1000 );
456 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08lx\n", ret );
458
459 memset(&info, 0xcc, sizeof(info));
460 status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
461 ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08lx\n", status );
462 ok( info.CurrentCount == 1, "expected 0, got %ld\n", info.CurrentCount );
463 ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
464 ok( info.AbandonedState == TRUE, "expected TRUE, got %d\n", info.AbandonedState );
465
466 ret = WaitForSingleObject( mutant, 1000 );
467 ok( ret == WAIT_ABANDONED_0, "WaitForSingleObject failed %08lx\n", ret );
468
469 memset(&info, 0xcc, sizeof(info));
470 status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
471 ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08lx\n", status );
472 ok( info.CurrentCount == 0, "expected 0, got %ld\n", info.CurrentCount );
473 ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
474 ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
475
476 NtClose( mutant );
477}
478
479static void test_semaphore(void)
480{
486 ULONG prev;
487 ULONG len;
488 DWORD ret;
489
490 pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_semaphore");
492
493 status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 2, 1);
494 ok( status == STATUS_INVALID_PARAMETER, "Failed to create Semaphore(%08lx)\n", status );
495 status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 1, 2);
496 ok( status == STATUS_SUCCESS, "Failed to create Semaphore(%08lx)\n", status );
497
498 /* bogus */
499 status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, 0, NULL);
501 "Failed to NtQuerySemaphore, expected STATUS_INFO_LENGTH_MISMATCH, got %08lx\n", status );
502 status = pNtQuerySemaphore(semaphore, 0x42, &info, sizeof(info), NULL);
504 "Failed to NtQuerySemaphore, expected STATUS_INVALID_INFO_CLASS, got %08lx\n", status );
505 status = pNtQuerySemaphore((HANDLE)0xdeadbeef, SemaphoreBasicInformation, &info, sizeof(info), NULL);
507 "Failed to NtQuerySemaphore, expected STATUS_INVALID_HANDLE, got %08lx\n", status );
508
509 len = -1;
510 memset(&info, 0xcc, sizeof(info));
511 status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), &len);
512 ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08lx\n", status );
513 ok( info.CurrentCount == 1, "expected 1, got %ld\n", info.CurrentCount );
514 ok( info.MaximumCount == 2, "expected 2, got %ld\n", info.MaximumCount );
515 ok( len == sizeof(info), "got %lu\n", len );
516
518 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08lx\n", ret );
519
520 memset(&info, 0xcc, sizeof(info));
521 status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
522 ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08lx\n", status );
523 ok( info.CurrentCount == 0, "expected 0, got %ld\n", info.CurrentCount );
524 ok( info.MaximumCount == 2, "expected 2, got %ld\n", info.MaximumCount );
525
526 prev = 0xdeadbeef;
527 status = pNtReleaseSemaphore(semaphore, 3, &prev);
528 ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08lx\n", status );
529 ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %ld\n", prev );
530
531 prev = 0xdeadbeef;
532 status = pNtReleaseSemaphore(semaphore, 1, &prev);
533 ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08lx\n", status );
534 ok( prev == 0, "NtReleaseSemaphore failed, expected 0, got %ld\n", prev );
535
536 prev = 0xdeadbeef;
537 status = pNtReleaseSemaphore(semaphore, 1, &prev);
538 ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08lx\n", status );
539 ok( prev == 1, "NtReleaseSemaphore failed, expected 1, got %ld\n", prev );
540
541 prev = 0xdeadbeef;
542 status = pNtReleaseSemaphore(semaphore, 1, &prev);
543 ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08lx\n", status );
544 ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %ld\n", prev );
545
546 memset(&info, 0xcc, sizeof(info));
547 status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
548 ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08lx\n", status );
549 ok( info.CurrentCount == 2, "expected 2, got %ld\n", info.CurrentCount );
550 ok( info.MaximumCount == 2, "expected 2, got %ld\n", info.MaximumCount );
551
553}
554
555static void test_wait_on_address(void)
556{
557 SIZE_T size;
560 DWORD elapsed;
562
563 if (!pRtlWaitOnAddress)
564 {
565 win_skip("RtlWaitOnAddress not supported, skipping test\n");
566 return;
567 }
568
569 if (0) /* crash on Windows */
570 {
571 pRtlWaitOnAddress(&address, NULL, 8, NULL);
572 pRtlWaitOnAddress(NULL, &compare, 8, NULL);
573 pRtlWaitOnAddress(NULL, NULL, 8, NULL);
574 }
575
576 /* don't crash */
577 pRtlWakeAddressSingle(NULL);
578 pRtlWakeAddressAll(NULL);
579
580 /* invalid values */
581 address = 0;
582 compare = 0;
583 status = pRtlWaitOnAddress(&address, &compare, 5, NULL);
584 ok(status == STATUS_INVALID_PARAMETER, "got %lx\n", status);
585
586 /* values match */
587 address = 0;
588 compare = 0;
589 pNtQuerySystemTime(&start);
590 timeout.QuadPart = start.QuadPart + 100 * 10000;
591 status = pRtlWaitOnAddress(&address, &compare, 8, &timeout);
592 pNtQuerySystemTime(&end);
593 ok(status == STATUS_TIMEOUT, "got 0x%08lx\n", status);
594 elapsed = (end.QuadPart - start.QuadPart) / 10000;
595 ok(90 <= elapsed && elapsed <= 900, "timed out in %lu ms\n", elapsed);
596 ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
597 ok(compare == 0, "got %s\n", wine_dbgstr_longlong(compare));
598
599 /* different address size */
600 for (size = 1; size <= 4; size <<= 1)
601 {
602 compare = ~0;
603 compare <<= size * 8;
604
605 pNtQuerySystemTime(&start);
606 timeout.QuadPart = -100 * 10000;
607 status = pRtlWaitOnAddress(&address, &compare, size, &timeout);
608 pNtQuerySystemTime(&end);
609 ok(status == STATUS_TIMEOUT, "got 0x%08lx\n", status);
610 elapsed = (end.QuadPart - start.QuadPart) / 10000;
611 ok(90 <= elapsed && elapsed <= 900, "timed out in %lu ms\n", elapsed);
612
613 status = pRtlWaitOnAddress(&address, &compare, size << 1, &timeout);
614 ok(!status, "got 0x%08lx\n", status);
615 }
616 address = 0;
617 compare = 1;
618 status = pRtlWaitOnAddress(&address, &compare, 8, NULL);
619 ok(!status, "got 0x%08lx\n", status);
620
621 /* no waiters */
622 address = 0;
623 pRtlWakeAddressSingle(&address);
624 ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
625 pRtlWakeAddressAll(&address);
626 ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
627}
628
630
632{
634 BOOLEAN ret;
635
636 ret = pRtlAcquireResourceShared(resource, TRUE);
637 ok(ret == TRUE, "got %u\n", ret);
638
640 ok(!WaitForSingleObject(thread_done, 1000), "wait failed\n");
641 pRtlReleaseResource(resource);
642 return 0;
643}
644
646{
648 BOOLEAN ret;
649
650 ret = pRtlAcquireResourceExclusive(resource, TRUE);
651 ok(ret == TRUE, "got %u\n", ret);
652
654 ok(!WaitForSingleObject(thread_done, 1000), "wait failed\n");
655 pRtlReleaseResource(resource);
656 return 0;
657}
658
659static void test_resource(void)
660{
663 BOOLEAN ret;
664
665 pRtlInitializeResource(&resource);
668
669 ret = pRtlAcquireResourceShared(&resource, FALSE);
670 ok(ret == TRUE, "got %u\n", ret);
671 ret = pRtlAcquireResourceShared(&resource, FALSE);
672 ok(ret == TRUE, "got %u\n", ret);
673 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
674 ok(ret == FALSE, "got %u\n", ret);
675 pRtlReleaseResource(&resource);
676 pRtlReleaseResource(&resource);
677
678 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
679 ok(ret == TRUE, "got %u\n", ret);
680 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
681 ok(ret == TRUE, "got %u\n", ret);
682 ret = pRtlAcquireResourceShared(&resource, FALSE);
683 ok(ret == TRUE, "got %u\n", ret);
684 pRtlReleaseResource(&resource);
685 pRtlReleaseResource(&resource);
686 pRtlReleaseResource(&resource);
687
688 /* Do not acquire the resource ourselves, but spawn a shared thread holding it. */
689
691 ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
692
693 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
694 ok(ret == FALSE, "got %u\n", ret);
695 ret = pRtlAcquireResourceShared(&resource, FALSE);
696 ok(ret == TRUE, "got %u\n", ret);
697 pRtlReleaseResource(&resource);
698
700 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
702
703 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
704 ok(ret == TRUE, "got %u\n", ret);
705 pRtlReleaseResource(&resource);
706 ret = pRtlAcquireResourceShared(&resource, FALSE);
707 ok(ret == TRUE, "got %u\n", ret);
708 pRtlReleaseResource(&resource);
709
710 /* Acquire the resource as exclusive, and then spawn a shared thread. */
711
712 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
713 ok(ret == TRUE, "got %u\n", ret);
715 ok(WaitForSingleObject(thread_ready, 100) == WAIT_TIMEOUT, "expected timeout\n");
716
717 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
718 ok(ret == TRUE, "got %u\n", ret);
719 pRtlReleaseResource(&resource);
720 ret = pRtlAcquireResourceShared(&resource, FALSE);
721 ok(ret == TRUE, "got %u\n", ret);
722 pRtlReleaseResource(&resource);
723
724 pRtlReleaseResource(&resource);
725 ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
727 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
729
730 /* Acquire the resource as shared, and then spawn an exclusive thread. */
731
732 ret = pRtlAcquireResourceShared(&resource, FALSE);
733 ok(ret == TRUE, "got %u\n", ret);
735 ok(WaitForSingleObject(thread_ready, 100) == WAIT_TIMEOUT, "expected timeout\n");
736
737 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
738 ok(ret == FALSE, "got %u\n", ret);
739 ret = pRtlAcquireResourceShared(&resource, FALSE);
740 ok(ret == TRUE, "got %u\n", ret);
741 pRtlReleaseResource(&resource);
742
743 pRtlReleaseResource(&resource);
744 ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
746 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
748
749 /* Spawn a shared and then exclusive waiter. */
751 ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
753 ok(WaitForSingleObject(thread_ready, 100) == WAIT_TIMEOUT, "expected timeout\n");
754
755 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
756 ok(ret == FALSE, "got %u\n", ret);
757 ret = pRtlAcquireResourceShared(&resource, FALSE);
758 ok(ret == TRUE, "got %u\n", ret);
759 pRtlReleaseResource(&resource);
760
762 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
764
765 ok(!WaitForSingleObject(thread_ready, 1000), "wait failed\n");
767 ok(!WaitForSingleObject(thread2, 1000), "wait failed\n");
769
770 ret = pRtlAcquireResourceExclusive(&resource, FALSE);
771 ok(ret == TRUE, "got %u\n", ret);
772 pRtlReleaseResource(&resource);
773 ret = pRtlAcquireResourceShared(&resource, FALSE);
774 ok(ret == TRUE, "got %u\n", ret);
775 pRtlReleaseResource(&resource);
776
779 pRtlDeleteResource(&resource);
780}
781
783{
785
786 ret = pNtAlertThreadByThreadId( arg );
787 ok(!ret, "got %#lx\n", ret);
788
789 ret = pNtWaitForAlertByThreadId( (void *)0x123, NULL );
790 ok(ret == STATUS_ALERTED, "got %#lx\n", ret);
791
792 return 0;
793}
794
795static void test_tid_alert( char **argv )
796{
797 LARGE_INTEGER timeout = {{0}};
798 char cmdline[MAX_PATH];
799 STARTUPINFOA si = {0};
803 DWORD tid;
804
805 if (!pNtWaitForAlertByThreadId)
806 {
807 win_skip("NtWaitForAlertByThreadId is not available\n");
808 return;
809 }
810
811 ret = pNtWaitForAlertByThreadId( (void *)0x123, &timeout );
812 ok(ret == STATUS_TIMEOUT, "got %#lx\n", ret);
813
814 ret = pNtAlertThreadByThreadId( 0 );
815 ok(ret == STATUS_INVALID_CID, "got %#lx\n", ret);
816
817 ret = pNtAlertThreadByThreadId( (HANDLE)0xdeadbeef );
818 ok(ret == STATUS_INVALID_CID, "got %#lx\n", ret);
819
820 ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)GetCurrentThreadId() );
821 ok(!ret, "got %#lx\n", ret);
822
823 ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)GetCurrentThreadId() );
824 ok(!ret, "got %#lx\n", ret);
825
826 ret = pNtWaitForAlertByThreadId( (void *)0x123, &timeout );
827 ok(ret == STATUS_ALERTED, "got %#lx\n", ret);
828
829 ret = pNtWaitForAlertByThreadId( (void *)0x123, &timeout );
830 ok(ret == STATUS_TIMEOUT, "got %#lx\n", ret);
831
832 ret = pNtWaitForAlertByThreadId( (void *)0x321, &timeout );
833 ok(ret == STATUS_TIMEOUT, "got %#lx\n", ret);
834
836 timeout.QuadPart = -1000 * 10000;
837 ret = pNtWaitForAlertByThreadId( (void *)0x123, &timeout );
838 ok(ret == STATUS_ALERTED, "got %#lx\n", ret);
839
841 ok(ret == WAIT_TIMEOUT, "got %ld\n", ret);
842 ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)tid );
843 ok(!ret, "got %#lx\n", ret);
844
845 ret = WaitForSingleObject( thread, 1000 );
846 ok(!ret, "got %ld\n", ret);
847
848 ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)tid );
849 ok(!ret, "got %#lx\n", ret);
850
852
853 sprintf( cmdline, "%s %s subprocess", argv[0], argv[1] );
855 ok(ret, "failed to create process, error %lu\n", GetLastError());
856 ret = pNtAlertThreadByThreadId( (HANDLE)(DWORD_PTR)pi.dwThreadId );
857 todo_wine ok(ret == STATUS_ACCESS_DENIED, "got %#lx\n", ret);
858 ok(!WaitForSingleObject( pi.hProcess, 1000 ), "wait failed\n");
861}
862
864{
867 int index;
868};
869
871{
874 OVERLAPPED_ENTRY overlapped_entry;
879 DWORD ret, err;
880 ULONG count;
881 BOOL bret;
882
883 /* both threads are woken when comleption added. */
884 ret = WaitForSingleObject( p->ready, INFINITE );
885 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
886 ret = WaitForSingleObject( p->port, INFINITE );
887 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
888 SetEvent( p->test_ready );
889
890 /* if a thread is waiting for completion which is added threads which wait on port handle are not woken. */
891 ret = WaitForSingleObject( p->ready, INFINITE );
892 if (p->index)
893 {
895 ok( bret, "got error %lu.\n", GetLastError() );
896 }
897 else
898 {
899 ret = WaitForSingleObject( p->port, 100 );
900 ok( ret == WAIT_TIMEOUT || broken( !ret ) /* before Win10 1607 */, "got %#lx.\n", ret );
901 }
902 SetEvent( p->test_ready );
903
904 /* Two threads in GetQueuedCompletionStatus, the second is supposed to start first. */
905 ret = WaitForSingleObject( p->ready, INFINITE );
906 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
908 ok( bret, "got error %lu.\n", GetLastError() );
909 ok( key == 3 + p->index || broken( p->index && key == 5 ) /* before Win10 */, "got %Iu, expected %u.\n", key, 3 + p->index );
910 SetEvent( p->test_ready );
911
912 /* Port is being closed. */
913 ret = WaitForSingleObject( p->ready, INFINITE );
914 ret = WaitForSingleObject( p->port, INFINITE );
915 if (ret == WAIT_FAILED)
916 skip( "Handle closed before wait started.\n" );
917 else
918 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
919 SetEvent( p->test_ready );
920
921 /* Port is being closed. */
922 ret = WaitForSingleObject( p->ready, INFINITE );
923 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
924 SetEvent( p->test_ready );
925 status = NtRemoveIoCompletion( p->port, &key, &value, &iosb, NULL );
927 skip( "Handle closed before wait started.\n" );
928 else
929 ok( status == STATUS_ABANDONED_WAIT_0, "got %#lx.\n", status );
930
931 /* Port is being closed. */
932 ret = WaitForSingleObject( p->ready, INFINITE );
933 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
934 SetEvent( p->test_ready );
935 count = 0xdeadbeef;
936 status = NtRemoveIoCompletionEx( p->port, &info, 1, &count, NULL, FALSE );
937 ok( count <= 1, "Got unexpected count %lu.\n", count );
939 skip( "Handle closed before wait started.\n" );
940 else
941 ok( status == STATUS_ABANDONED_WAIT_0, "got %#lx.\n", status );
942
943 /* Port is being closed. */
944 ret = WaitForSingleObject( p->ready, INFINITE );
945 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
946 SetEvent( p->test_ready );
948 err = GetLastError();
949 ok( !bret, "got %d.\n", bret );
951 skip( "Handle closed before wait started.\n" );
952 else
953 ok( err == ERROR_ABANDONED_WAIT_0, "got error %#lx.\n", err );
954
955#if !defined (__REACTOS__) || (DLL_EXPORT_VERSION >= 0x601)
956 /* Port is being closed. */
957 ret = WaitForSingleObject( p->ready, INFINITE );
958 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
959 SetEvent( p->test_ready );
960 bret = GetQueuedCompletionStatusEx( p->port, &overlapped_entry, 1, &count, INFINITE, TRUE );
961 err = GetLastError();
962 ok( !bret, "got %d.\n", bret );
964 skip( "Handle closed before wait started.\n" );
965 else
966 ok( err == ERROR_ABANDONED_WAIT_0, "got error %#lx.\n", err );
967#endif
968
969 return 0;
970}
971
973{
975 HANDLE threads[2], port;
977 unsigned int i, j;
978 DWORD ret, count;
981 BOOL bret;
982
983#if defined(__REACTOS__)
984 if ((GetNTVersion() < _WIN32_WINNT_WIN7) || is_reactos())
985 {
986 skip("Skipping completion port scheduling test, because it hangs on Windows 2003, Vista and ReactOS\n");
987 return;
988 }
989#endif
990
991 for (i = 0; i < 2; ++i)
992 {
993 p[i].index = 0;
994 p[i].ready = CreateEventA(NULL, FALSE, FALSE, NULL);
995 p[i].test_ready = CreateEventA(NULL, FALSE, FALSE, NULL);
997 ok( !!threads[i], "got error %lu.\n", GetLastError() );
998 }
999
1001 ok( !status, "got %#lx.\n", status );
1002 /* Waking multiple threads directly waiting on port */
1003 for (i = 0; i < 2; ++i)
1004 {
1005 p[i].index = i;
1006 p[i].port = port;
1007 SetEvent( p[i].ready );
1008 }
1010 for (i = 0; i < 2; ++i) WaitForSingleObject( p[i].test_ready, INFINITE );
1012 ok( bret, "got error %lu.\n", GetLastError() );
1013
1014 /* One thread is waiting on port, another in GetQueuedCompletionStatus(). */
1015 SetEvent( p[1].ready );
1016 Sleep( 40 );
1017 SetEvent( p[0].ready );
1018 Sleep( 10 );
1020 for (i = 0; i < 2; ++i) WaitForSingleObject( p[i].test_ready, INFINITE );
1021
1022 /* Both threads are waiting in GetQueuedCompletionStatus, LIFO wake up order. */
1023 SetEvent( p[1].ready );
1024 Sleep( 40 );
1025 SetEvent( p[0].ready );
1026 Sleep( 20 );
1030 bret = GetQueuedCompletionStatus( p->port, &count, &key, &overlapped, INFINITE );
1031 ok( bret, "got error %lu.\n", GetLastError() );
1032 ok( key == 5 || broken( key == 4 ) /* before Win10 */, "got %Iu, expected 5.\n", key );
1033
1034 /* Close port handle while threads are waiting on it directly. */
1035 for (i = 0; i < 2; ++i) SetEvent( p[i].ready );
1036 Sleep( 20 );
1037 NtClose( port );
1038 for (i = 0; i < 2; ++i) WaitForSingleObject( p[i].test_ready, INFINITE );
1039
1040 /* Test signaling on port close. */
1041 for (i = 0; i < 4; ++i)
1042 {
1044 ok( !status, "got %#lx.\n", status );
1045 for (j = 0; j < 2; ++j)
1046 {
1047 p[j].port = port;
1049 INFINITE, FALSE );
1050 ok( ret == WAIT_OBJECT_0, "got %#lx.\n", ret );
1051 }
1052 Sleep( 20 );
1053 status = NtClose( port );
1054 ok( !status, "got %#lx.\n", status );
1055 }
1056
1058 for (i = 0; i < 2; ++i)
1059 {
1060 CloseHandle( threads[i] );
1061 CloseHandle( p[i].ready );
1063 }
1064}
1065
1067{
1068 HMODULE module = GetModuleHandleA("ntdll.dll");
1069 char **argv;
1070 int argc;
1071
1073
1074 if (argc > 2) return;
1075
1076 pNtAlertThreadByThreadId = (void *)GetProcAddress(module, "NtAlertThreadByThreadId");
1077 pNtClose = (void *)GetProcAddress(module, "NtClose");
1078 pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent");
1079 pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent");
1080 pNtCreateMutant = (void *)GetProcAddress(module, "NtCreateMutant");
1081 pNtCreateSemaphore = (void *)GetProcAddress(module, "NtCreateSemaphore");
1082 pNtOpenEvent = (void *)GetProcAddress(module, "NtOpenEvent");
1083 pNtOpenKeyedEvent = (void *)GetProcAddress(module, "NtOpenKeyedEvent");
1084 pNtPulseEvent = (void *)GetProcAddress(module, "NtPulseEvent");
1085 pNtQueryEvent = (void *)GetProcAddress(module, "NtQueryEvent");
1086 pNtQueryMutant = (void *)GetProcAddress(module, "NtQueryMutant");
1087 pNtQuerySemaphore = (void *)GetProcAddress(module, "NtQuerySemaphore");
1088 pNtQuerySystemTime = (void *)GetProcAddress(module, "NtQuerySystemTime");
1089 pNtReleaseKeyedEvent = (void *)GetProcAddress(module, "NtReleaseKeyedEvent");
1090 pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant");
1091 pNtReleaseSemaphore = (void *)GetProcAddress(module, "NtReleaseSemaphore");
1092 pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent");
1093 pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent");
1094 pNtWaitForAlertByThreadId = (void *)GetProcAddress(module, "NtWaitForAlertByThreadId");
1095 pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent");
1096 pRtlAcquireResourceExclusive = (void *)GetProcAddress(module, "RtlAcquireResourceExclusive");
1097 pRtlAcquireResourceShared = (void *)GetProcAddress(module, "RtlAcquireResourceShared");
1098 pRtlDeleteResource = (void *)GetProcAddress(module, "RtlDeleteResource");
1099 pRtlInitializeResource = (void *)GetProcAddress(module, "RtlInitializeResource");
1100 pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString");
1101 pRtlReleaseResource = (void *)GetProcAddress(module, "RtlReleaseResource");
1102 pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress");
1103 pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll");
1104 pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle");
1105
1107 test_event();
1108 test_mutant();
1111 test_resource();
1114}
#define compare
unsigned char BOOLEAN
Definition: actypes.h:127
#define GetNTVersion()
Definition: apitest.h:17
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
static HANDLE thread
Definition: service.c:33
#define STATUS_TIMEOUT
Definition: d3dkmdt.h:49
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: d3dkmdt.h:46
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NTSTATUS
Definition: precomp.h:19
#define CloseHandle
Definition: compat.h:739
#define GetProcAddress(x, y)
Definition: compat.h:753
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(SECURITY_ATTRIBUTES *sa, BOOL manual_reset, BOOL initial_state, LPCSTR name)
Definition: sync.c:510
DWORD WINAPI DECLSPEC_HOTPATCH SignalObjectAndWait(HANDLE signal, HANDLE wait, DWORD timeout, BOOL alertable)
Definition: sync.c:309
void WINAPI DECLSPEC_HOTPATCH Sleep(DWORD timeout)
Definition: sync.c:330
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(HANDLE handle)
Definition: sync.c:637
BOOL WINAPI DECLSPEC_HOTPATCH GetQueuedCompletionStatusEx(HANDLE port, OVERLAPPED_ENTRY *entries, ULONG count, ULONG *written, DWORD timeout, BOOL alertable)
Definition: sync.c:1209
DWORD WINAPI DECLSPEC_HOTPATCH WaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout)
Definition: sync.c:382
BOOL WINAPI DECLSPEC_HOTPATCH PostQueuedCompletionStatus(HANDLE port, DWORD count, ULONG_PTR key, LPOVERLAPPED overlapped)
Definition: sync.c:1232
DWORD WINAPI DECLSPEC_HOTPATCH WaitForSingleObject(HANDLE handle, DWORD timeout)
Definition: sync.c:364
BOOL WINAPI DECLSPEC_HOTPATCH GetQueuedCompletionStatus(HANDLE port, LPDWORD count, PULONG_PTR key, LPOVERLAPPED *overlapped, DWORD timeout)
Definition: sync.c:1180
MonoAssembly int argc
Definition: metahost.c:107
USHORT port
Definition: uri.c:228
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
struct _cl_event * event
Definition: glext.h:7739
GLuint address
Definition: glext.h:9393
GLsizeiptr size
Definition: glext.h:5919
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static TfClientId tid
NTSTATUS NTAPI NtRemoveIoCompletion(IN HANDLE IoCompletionHandle, OUT PVOID *KeyContext, OUT PVOID *ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: iocomp.c:445
NTSTATUS NTAPI NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG NumberOfConcurrentThreads)
Definition: iocomp.c:253
#define resource
Definition: kernel32.h:9
#define win_skip
Definition: minitest.h:67
#define todo_wine
Definition: minitest.h:80
#define sprintf
Definition: sprintf.c:45
DWORD WINAPI thread2(LPVOID crap)
Definition: mutex.c:57
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
static HANDLE semaphore
Definition: loader.c:2947
static HANDLE ULONG_PTR DWORD threads
Definition: process.c:83
static ULONG
Definition: sync.c:47
static void test_semaphore(void)
Definition: sync.c:667
static BOOLEAN
Definition: sync.c:61
static void test_event(void)
Definition: sync.c:514
static SYSTEM_INFO si
Definition: virtual.c:39
#define IO_COMPLETION_ALL_ACCESS
Definition: file.c:43
static PIO_STATUS_BLOCK iosb
Definition: file.c:70
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
static const OBJECT_ATTRIBUTES LONG
Definition: sync.c:57
static HANDLE thread_ready
Definition: sync.c:629
static const WCHAR keyed_nameW[]
Definition: sync.c:173
static void test_completion_port_scheduling(void)
Definition: sync.c:972
static void test_resource(void)
Definition: sync.c:659
static const OBJECT_ATTRIBUTES *static const OBJECT_ATTRIBUTES *static LONG *static EVENT_INFORMATION_CLASS
Definition: sync.c:61
static DWORD WINAPI tid_alert_thread(void *arg)
Definition: sync.c:782
static HANDLE thread_done
Definition: sync.c:629
#define KEYEDEVENT_WAIT
Definition: sync.c:82
#define KEYEDEVENT_ALL_ACCESS
Definition: sync.c:84
static DWORD WINAPI resource_shared_thread(void *arg)
Definition: sync.c:631
#define KEYEDEVENT_WAKE
Definition: sync.c:83
static const OBJECT_ATTRIBUTES EVENT_TYPE
Definition: sync.c:54
static void test_tid_alert(char **argv)
Definition: sync.c:795
static const OBJECT_ATTRIBUTES *static const OBJECT_ATTRIBUTES *static LONG *static void ULONG *static void ULONG *static SEMAPHORE_INFORMATION_CLASS
Definition: sync.c:63
static void test_mutant(void)
Definition: sync.c:388
static const void SIZE_T
Definition: sync.c:78
static DWORD WINAPI resource_exclusive_thread(void *arg)
Definition: sync.c:645
static DWORD WINAPI keyed_event_thread(void *arg)
Definition: sync.c:175
static const OBJECT_ATTRIBUTES *static const OBJECT_ATTRIBUTES *static LONG *static void ULONG *static MUTANT_INFORMATION_CLASS
Definition: sync.c:62
static void test_keyed_events(void)
Definition: sync.c:218
static DWORD WINAPI mutant_thread(void *arg)
Definition: sync.c:366
static void test_wait_on_address(void)
Definition: sync.c:555
static ACCESS_MASK
Definition: sync.c:54
static DWORD WINAPI test_completion_port_scheduling_thread(void *param)
Definition: sync.c:870
#define argv
Definition: mplay32.c:18
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:453
@ SemaphoreBasicInformation
Definition: extypes.h:520
@ MutantBasicInformation
Definition: extypes.h:494
@ EventBasicInformation
Definition: extypes.h:528
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _Out_writes_to_(s, c)
Definition: no_sal2.h:188
int Count
Definition: noreturn.cpp:7
#define SYNCHRONIZE
Definition: nt_native.h:61
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define GENERIC_ALL
Definition: nt_native.h:92
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define GENERIC_WRITE
Definition: nt_native.h:90
@ NotificationEvent
@ SynchronizationEvent
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:100
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_ALERTED
Definition: ntstatus.h:133
#define STATUS_INVALID_CID
Definition: ntstatus.h:341
#define STATUS_SEMAPHORE_LIMIT_EXCEEDED
Definition: ntstatus.h:401
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:569
#define STATUS_ABANDONED_WAIT_0
Definition: ntstatus.h:128
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
static ULONG Timeout
Definition: ping.c:61
#define err(...)
const WCHAR * str
int winetest_get_mainargs(char ***pargv)
#define memset(x, y, z)
Definition: compat.h:39
#define _WIN32_WINNT_WIN7
Definition: sdkddkver.h:28
#define STATUS_SUCCESS
Definition: shellext.h:65
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED * overlapped
Definition: sock.c:81
TCHAR * cmdline
Definition: stretchblt.cpp:32
Definition: minwinbase.h:234
Definition: cookie.c:202
Definition: bug.cpp:8
Definition: copy.c:22
Definition: ps.c:97
Definition: dhcpd.h:248
uint32_t * PULONG
Definition: typedefs.h:59
int64_t LONG64
Definition: typedefs.h:68
uint32_t DWORD_PTR
Definition: typedefs.h:65
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
Definition: pdh_main.c:96
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
#define WAIT_ABANDONED_0
Definition: winbase.h:384
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define WAIT_FAILED
Definition: winbase.h:390
void * arg
Definition: msvc.h:10
#define WINAPI
Definition: msvc.h:6
NTSYSAPI NTSTATUS WINAPI NtRemoveIoCompletionEx(HANDLE, FILE_IO_COMPLETION_INFORMATION *, ULONG, ULONG *, LARGE_INTEGER *, BOOLEAN)
#define ERROR_ABANDONED_WAIT_0
Definition: winerror.h:813