1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*=====================================================================
6**
7** Source: test10.c (DuplicateHandle)
8**
9** Purpose: Tests the PAL implementation of the DuplicateHandle function.
10** This tests the operation of a duplicated Semaphore handle
11**
12**
13**===================================================================*/
14
15#include <palsuite.h>
16
17enum wait_results
18{
19 WR_WAITING,
20 WR_GOT_MUTEX,
21 WR_TIMED_OUT,
22 WR_RELEASED
23};
24
25
26volatile int t1_result=WR_WAITING;
27volatile int t2_result=WR_WAITING;
28
29
30DWORD PALAPI ThreadTest1(LPVOID lpParam)
31{
32 DWORD dwWait;
33
34 dwWait = WaitForSingleObject((HANDLE)lpParam, 0);
35 if (dwWait == WAIT_OBJECT_0)
36 {
37 /* tell the main thread we got the mutex */
38 t1_result=WR_GOT_MUTEX;
39
40 /* wait for main thread to tell us to release the mutex */
41 while(WR_GOT_MUTEX == t1_result)
42 Sleep(1);
43 ReleaseSemaphore((HANDLE)lpParam, 1, NULL);
44
45 /* tell the main thread we released the mutex */
46 t1_result = WR_RELEASED;
47 }
48 else
49 {
50 t1_result = WR_TIMED_OUT;
51 }
52 return 0;
53}
54
55DWORD PALAPI ThreadTest2(LPVOID lpParam)
56{
57 DWORD dwWait;
58
59 dwWait = WaitForSingleObject((HANDLE)lpParam, 0 );
60 if (dwWait == WAIT_OBJECT_0)
61 {
62 ReleaseSemaphore((HANDLE)lpParam, 1, NULL);
63 t2_result = WR_GOT_MUTEX;
64 }
65 else
66 {
67 t2_result = WR_TIMED_OUT;
68 }
69
70 return 0;
71}
72
73
74int __cdecl main(int argc, char **argv)
75{
76
77 HANDLE hDupSemaphore;
78 HANDLE hSemaphore;
79 HANDLE hThread;
80 HANDLE hThread2;
81 BOOL bDupHandle=FALSE;
82 DWORD dwThreadId = 0;
83
84 if ((PAL_Initialize(argc,argv)) != 0)
85 {
86 return(FAIL);
87 }
88
89 hSemaphore = CreateSemaphoreW( NULL,
90 1,
91 1,
92 NULL);
93 if (hSemaphore == NULL)
94 {
95 Fail("PALSUITE ERROR:%u: Unable to create mutex\n",
96 GetLastError());
97 }
98
99 /*Create Duplicate of the Semaphore above*/
100 bDupHandle = DuplicateHandle(GetCurrentProcess(),
101 hSemaphore,
102 GetCurrentProcess(),
103 &hDupSemaphore,
104 GENERIC_READ|GENERIC_WRITE,
105 FALSE,
106 DUPLICATE_SAME_ACCESS);
107 if (!bDupHandle)
108 {
109 Trace("PALSUITE ERROR:%u: Created the duplicate handle to "
110 "closed event handle hSemaphore=0x%lx\n",
111 GetLastError(),
112 hSemaphore);
113 CloseHandle(hSemaphore);
114 Fail("");
115 }
116
117 /*Create a thread to test the Semaphore*/
118 hThread = CreateThread(NULL,
119 0,
120 &ThreadTest1,
121 hSemaphore,
122 0,
123 &dwThreadId);
124 if (hThread == NULL)
125 {
126 Trace("PALSUITE ERROR:%u: unable to create thread\n",
127 GetLastError());
128 CloseHandle(hSemaphore);
129 CloseHandle(hDupSemaphore);
130 Fail("");
131 }
132
133 /* wait until thread has taken the mutex */
134 while (WR_WAITING == t1_result)
135 Sleep(1);
136
137 if(WR_TIMED_OUT == t1_result)
138 {
139 Trace("PALSUITE ERROR: %u: thread couldn't acquire the semaphore\n",
140 GetLastError());
141 CloseHandle(hSemaphore);
142 CloseHandle(hDupSemaphore);
143 CloseHandle(hThread);
144 Fail("");
145 }
146
147 /*Create a second thread to use the Semaphore's duplicate handle*/
148 /*This thread should block since the Semaphore is owned by another
149 thread*/
150 hThread2 = CreateThread(NULL,
151 0,
152 &ThreadTest2,
153 hDupSemaphore,
154 0,
155 &dwThreadId);
156
157 if (hThread2 == NULL)
158 {
159 Trace("PALSUITE ERROR:%u: unable to create thread\n",
160 GetLastError());
161 CloseHandle(hSemaphore);
162 CloseHandle(hDupSemaphore);
163 CloseHandle(hThread);
164 Fail("");
165 }
166
167 /* wait until thread has tried to take the mutex */
168 while (WR_WAITING == t2_result)
169 Sleep(1);
170
171 if (WR_TIMED_OUT != t2_result )
172 {
173 Trace("PALSUITE ERROR:%u: Able to take mutex %#x while its "
174 "duplicate %#x is held\n", GetLastError(), hDupSemaphore,
175 hSemaphore);
176 CloseHandle(hSemaphore);
177 CloseHandle(hDupSemaphore);
178 CloseHandle(hThread);
179 CloseHandle(hThread2);
180 Fail("");
181 }
182
183 /* reset second thread status */
184 t2_result = WR_WAITING;
185
186 /* tell thread 1 to release the mutex */
187 t1_result = WR_WAITING;
188
189 /* wait for thread 1 to release the mutex */
190 while (WR_WAITING == t1_result)
191 Sleep(1);
192
193 CloseHandle(hThread2);
194
195 /*Re-Create the second thread to reuse the duplicated Semaphore*/
196 /*Since the Semaphore has since been released, the thread should
197 put WR_GOT_MUTEX into t2_result */
198 hThread2 = CreateThread(NULL,
199 0,
200 &ThreadTest2,
201 hDupSemaphore,
202 0,
203 &dwThreadId);
204
205 if (hThread2 == NULL)
206 {
207 Trace("PALSUITE ERROR:%u: unable to create thread\n",
208 GetLastError());
209 CloseHandle(hSemaphore);
210 CloseHandle(hDupSemaphore);
211 CloseHandle(hThread);
212 Fail("");
213 }
214
215 /* wait until thread has taken the semaphore */
216 while (WR_WAITING == t2_result)
217 Sleep(1);
218
219 if (WR_GOT_MUTEX != t2_result )
220 {
221 Trace("PALSUITE ERROR:%u: Unable to take semaphore %#x after its"
222 " duplicate %#x was released\n", GetLastError(), hDupSemaphore,
223 hSemaphore);
224 CloseHandle(hSemaphore);
225 CloseHandle(hDupSemaphore);
226 CloseHandle(hThread);
227 CloseHandle(hThread2);
228 Fail("");
229 }
230
231 /*Cleanup.*/
232 CloseHandle(hSemaphore);
233 CloseHandle(hDupSemaphore);
234 CloseHandle(hThread);
235 CloseHandle(hThread2);
236
237 PAL_Terminate();
238 return (PASS);
239}
240