2 * Synchronization tests
4 * Copyright 2005 Mike McCormack for CodeWeavers
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.
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.
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
27 #include "wine/test.h"
29 static void test_signalandwait(void)
31 DWORD (WINAPI
*pSignalObjectAndWait
)(HANDLE
, HANDLE
, DWORD
, BOOL
);
35 HANDLE event
[2], maxevents
[MAXIMUM_WAIT_OBJECTS
], semaphore
[2], file
;
37 kernel32
= GetModuleHandle("kernel32");
38 pSignalObjectAndWait
= (void*) GetProcAddress(kernel32
, "SignalObjectAndWait");
40 if (!pSignalObjectAndWait
)
43 /* invalid parameters */
44 r
= pSignalObjectAndWait(NULL
, NULL
, 0, 0);
45 if (r
== ERROR_INVALID_FUNCTION
)
47 trace("SignalObjectAndWait not implemented, skipping tests\n");
48 return; /* Win98/ME */
50 ok( r
== WAIT_FAILED
, "should fail\n");
52 event
[0] = CreateEvent(NULL
, 0, 0, NULL
);
53 event
[1] = CreateEvent(NULL
, 1, 1, NULL
);
55 ok( event
[0] && event
[1], "failed to create event flags\n");
57 r
= pSignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
58 ok( r
== WAIT_FAILED
, "should fail\n");
60 r
= pSignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
61 ok( r
== WAIT_FAILED
, "should fail\n");
64 /* valid parameters */
65 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
66 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
68 /* event[0] is now signalled */
69 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
70 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
72 /* event[0] is not signalled */
73 r
= WaitForSingleObject(event
[0], 0);
74 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
76 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
77 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
79 /* clear event[1] and check for a timeout */
80 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
81 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
82 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
84 CloseHandle(event
[0]);
85 CloseHandle(event
[1]);
87 /* create the maximum number of events and make sure
88 * we can wait on that many */
89 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
91 maxevents
[i
] = CreateEvent(NULL
, 1, 1, NULL
);
92 ok( maxevents
[i
] != 0, "should create enough events\n");
94 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
95 ok( r
!= WAIT_FAILED
&& r
!= WAIT_TIMEOUT
, "should succeed\n");
97 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
98 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
101 semaphore
[0] = CreateSemaphore( NULL
, 0, 1, NULL
);
102 semaphore
[1] = CreateSemaphore( NULL
, 1, 1, NULL
);
103 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
105 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
106 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
108 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
109 ok( r
== WAIT_FAILED
, "should fail\n");
111 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
112 ok( r
== FALSE
, "should fail\n");
114 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
115 ok( r
== TRUE
, "should succeed\n");
117 CloseHandle(semaphore
[0]);
118 CloseHandle(semaphore
[1]);
120 /* try a registry key */
121 file
= CreateFile("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
122 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
123 r
= pSignalObjectAndWait(file
, file
, 0, FALSE
);
124 ok( r
== WAIT_FAILED
, "should fail\n");
125 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
129 static void test_mutex(void)
136 hCreated
= CreateMutex(NULL
, FALSE
, "WineTestMutex");
137 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
138 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
139 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
141 /* yes, opening with just READ_CONTROL access allows us to successfully
142 * call ReleaseMutex */
143 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "WineTestMutex");
144 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
145 ret
= ReleaseMutex(hOpened
);
146 todo_wine
ok(ret
, "ReleaseMutex failed with error %d\n", GetLastError());
147 ret
= ReleaseMutex(hCreated
);
148 todo_wine
ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
149 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
151 CloseHandle(hOpened
);
152 CloseHandle(hCreated
);
155 static void test_slist(void)
161 } item1
, item2
, item3
, *pitem
;
163 SLIST_HEADER slist_header
, test_header
;
167 VOID (WINAPI
*pInitializeSListHead
)(PSLIST_HEADER
);
168 USHORT (WINAPI
*pQueryDepthSList
)(PSLIST_HEADER
);
169 PSLIST_ENTRY (WINAPI
*pInterlockedFlushSList
)(PSLIST_HEADER
);
170 PSLIST_ENTRY (WINAPI
*pInterlockedPopEntrySList
)(PSLIST_HEADER
);
171 PSLIST_ENTRY (WINAPI
*pInterlockedPushEntrySList
)(PSLIST_HEADER
,PSLIST_ENTRY
);
174 kernel32
= GetModuleHandle("KERNEL32.DLL");
175 pInitializeSListHead
= (void*) GetProcAddress(kernel32
, "InitializeSListHead");
176 pQueryDepthSList
= (void*) GetProcAddress(kernel32
, "QueryDepthSList");
177 pInterlockedFlushSList
= (void*) GetProcAddress(kernel32
, "InterlockedFlushSList");
178 pInterlockedPopEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPopEntrySList");
179 pInterlockedPushEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPushEntrySList");
180 if (pInitializeSListHead
== NULL
||
181 pQueryDepthSList
== NULL
||
182 pInterlockedFlushSList
== NULL
||
183 pInterlockedPopEntrySList
== NULL
||
184 pInterlockedPushEntrySList
== NULL
)
186 skip("some required slist entrypoints were not found, skipping tests\n");
190 memset(&test_header
, 0, sizeof(test_header
));
191 memset(&slist_header
, 0xFF, sizeof(slist_header
));
192 pInitializeSListHead(&slist_header
);
193 ok(memcmp(&test_header
, &slist_header
, sizeof(SLIST_HEADER
)) == 0,
194 "InitializeSListHead didn't zero-fill list header\n");
195 size
= pQueryDepthSList(&slist_header
);
196 ok(size
== 0, "initially created slist has size %d, expected 0\n", size
);
199 ok(pInterlockedPushEntrySList(&slist_header
, &item1
.entry
) == NULL
,
200 "previous entry in empty slist wasn't NULL\n");
201 size
= pQueryDepthSList(&slist_header
);
202 ok(size
== 1, "slist with 1 item has size %d\n", size
);
205 entry
= pInterlockedPushEntrySList(&slist_header
, &item2
.entry
);
206 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
209 pitem
= (struct item
*) entry
;
210 ok(pitem
->value
== 1, "previous entry in slist wasn't the one added\n");
212 size
= pQueryDepthSList(&slist_header
);
213 ok(size
== 2, "slist with 2 items has size %d\n", size
);
216 entry
= pInterlockedPushEntrySList(&slist_header
, &item3
.entry
);
217 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
220 pitem
= (struct item
*) entry
;
221 ok(pitem
->value
== 2, "previous entry in slist wasn't the one added\n");
223 size
= pQueryDepthSList(&slist_header
);
224 ok(size
== 3, "slist with 3 items has size %d\n", size
);
226 entry
= pInterlockedPopEntrySList(&slist_header
);
227 ok(entry
!= NULL
, "entry shouldn't be NULL\n");
230 pitem
= (struct item
*) entry
;
231 ok(pitem
->value
== 3, "unexpected entry removed\n");
233 size
= pQueryDepthSList(&slist_header
);
234 ok(size
== 2, "slist with 2 items has size %d\n", size
);
236 entry
= pInterlockedFlushSList(&slist_header
);
237 size
= pQueryDepthSList(&slist_header
);
238 ok(size
== 0, "flushed slist should be empty, size is %d\n", size
);
241 ok(pInterlockedPopEntrySList(&slist_header
) == NULL
,
242 "popping empty slist didn't return NULL\n");
244 ok(((struct item
*)entry
)->value
== 2, "item 2 not in front of list\n");
245 ok(((struct item
*)entry
->Next
)->value
== 1, "item 1 not at the back of list\n");
250 test_signalandwait();