2 * Unit tests for named pipe functions in Wine
4 * Copyright (c) 2002 Dan Kegel
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
23 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
24 #define PIPENAME_SPECIAL "\\\\.\\PiPe\\tests->pipe.c"
26 #define NB_SERVER_LOOPS 8
28 static HANDLE alarm_event
;
29 static BOOL (WINAPI
*pDuplicateTokenEx
)(HANDLE
,DWORD
,LPSECURITY_ATTRIBUTES
,
30 SECURITY_IMPERSONATION_LEVEL
,TOKEN_TYPE
,PHANDLE
);
31 static DWORD (WINAPI
*pQueueUserAPC
)(PAPCFUNC pfnAPC
, HANDLE hThread
, ULONG_PTR dwData
);
32 static BOOL (WINAPI
*pCancelIoEx
)(HANDLE handle
, LPOVERLAPPED lpOverlapped
);
34 static BOOL user_apc_ran
;
35 static void CALLBACK
user_apc(ULONG_PTR param
)
48 ULONG_PTR returnValue
;
54 static DWORD CALLBACK
rpcThreadMain(LPVOID arg
)
56 struct rpcThreadArgs
*rpcargs
= (struct rpcThreadArgs
*)arg
;
57 trace("rpcThreadMain starting\n");
58 SetLastError( rpcargs
->lastError
);
63 rpcargs
->returnValue
= (ULONG_PTR
)ReadFile( (HANDLE
)rpcargs
->args
[0], /* hFile */
64 (LPVOID
)rpcargs
->args
[1], /* buffer */
65 (DWORD
)rpcargs
->args
[2], /* bytesToRead */
66 (LPDWORD
)rpcargs
->args
[3], /* bytesRead */
67 (LPOVERLAPPED
)rpcargs
->args
[4] ); /* overlapped */
71 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
72 rpcargs
->returnValue
= 0;
76 rpcargs
->lastError
= GetLastError();
77 trace("rpcThreadMain returning\n");
81 /* Runs ReadFile(...) from a different thread */
82 static BOOL
RpcReadFile(HANDLE hFile
, LPVOID buffer
, DWORD bytesToRead
, LPDWORD bytesRead
, LPOVERLAPPED overlapped
)
84 struct rpcThreadArgs rpcargs
;
88 rpcargs
.returnValue
= 0;
89 rpcargs
.lastError
= GetLastError();
90 rpcargs
.op
= RPC_READFILE
;
91 rpcargs
.args
[0] = (ULONG_PTR
)hFile
;
92 rpcargs
.args
[1] = (ULONG_PTR
)buffer
;
93 rpcargs
.args
[2] = (ULONG_PTR
)bytesToRead
;
94 rpcargs
.args
[3] = (ULONG_PTR
)bytesRead
;
95 rpcargs
.args
[4] = (ULONG_PTR
)overlapped
;
97 thread
= CreateThread(NULL
, 0, rpcThreadMain
, (void *)&rpcargs
, 0, &threadId
);
98 ok(thread
!= NULL
, "CreateThread failed. %d\n", GetLastError());
99 ret
= WaitForSingleObject(thread
, INFINITE
);
100 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with %d.\n", GetLastError());
103 SetLastError(rpcargs
.lastError
);
104 return (BOOL
)rpcargs
.returnValue
;
107 #define test_not_signaled(h) _test_not_signaled(__LINE__,h)
108 static void _test_not_signaled(unsigned line
, HANDLE handle
)
110 DWORD res
= WaitForSingleObject(handle
, 0);
111 ok_(__FILE__
,line
)(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %u (%u)\n", res
, GetLastError());
114 #define test_signaled(h) _test_signaled(__LINE__,h)
115 static void _test_signaled(unsigned line
, HANDLE handle
)
117 DWORD res
= WaitForSingleObject(handle
, 0);
118 ok_(__FILE__
,line
)(res
== WAIT_OBJECT_0
, "WaitForSingleObject returned %u\n", res
);
121 #define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
122 static void _test_pipe_info(unsigned line
, HANDLE pipe
, DWORD ex_flags
, DWORD ex_out_buf_size
, DWORD ex_in_buf_size
, DWORD ex_max_instances
)
124 DWORD flags
= 0xdeadbeef, out_buf_size
= 0xdeadbeef, in_buf_size
= 0xdeadbeef, max_instances
= 0xdeadbeef;
127 res
= GetNamedPipeInfo(pipe
, &flags
, &out_buf_size
, &in_buf_size
, &max_instances
);
128 ok_(__FILE__
,line
)(res
, "GetNamedPipeInfo failed: %x\n", res
);
129 ok_(__FILE__
,line
)(flags
== ex_flags
, "flags = %x, expected %x\n", flags
, ex_flags
);
130 ok_(__FILE__
,line
)(out_buf_size
== ex_out_buf_size
, "out_buf_size = %x, expected %u\n", out_buf_size
, ex_out_buf_size
);
131 ok_(__FILE__
,line
)(in_buf_size
== ex_in_buf_size
, "in_buf_size = %x, expected %u\n", in_buf_size
, ex_in_buf_size
);
132 ok_(__FILE__
,line
)(max_instances
== ex_max_instances
, "max_instances = %x, expected %u\n", max_instances
, ex_max_instances
);
135 static void test_CreateNamedPipe(int pipemode
)
139 static const char obuf
[] = "Bit Bucket";
140 static const char obuf2
[] = "More bits";
141 char ibuf
[32], *pbuf
;
149 if (pipemode
== PIPE_TYPE_BYTE
)
150 trace("test_CreateNamedPipe starting in byte mode\n");
152 trace("test_CreateNamedPipe starting in message mode\n");
154 /* Wait for nonexistent pipe */
155 ret
= WaitNamedPipeA(PIPENAME
, 2000);
156 ok(ret
== 0, "WaitNamedPipe returned %d for nonexistent pipe\n", ret
);
157 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
159 /* Bad parameter checks */
160 hnp
= CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX
, pipemode
| PIPE_WAIT
,
161 /* nMaxInstances */ 1,
162 /* nOutBufSize */ 1024,
163 /* nInBufSize */ 1024,
164 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
165 /* lpSecurityAttrib */ NULL
);
166 ok(hnp
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_INVALID_NAME
,
167 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
169 if (pipemode
== PIPE_TYPE_BYTE
)
171 /* Bad parameter checks */
172 hnp
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_READMODE_MESSAGE
,
173 /* nMaxInstances */ 1,
174 /* nOutBufSize */ 1024,
175 /* nInBufSize */ 1024,
176 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
177 /* lpSecurityAttrib */ NULL
);
178 ok(hnp
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_INVALID_PARAMETER
,
179 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
182 hnp
= CreateNamedPipeA(NULL
,
183 PIPE_ACCESS_DUPLEX
, pipemode
| PIPE_WAIT
,
184 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
185 ok(hnp
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_PATH_NOT_FOUND
,
186 "CreateNamedPipe should fail if name is NULL\n");
188 hFile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
189 ok(hFile
== INVALID_HANDLE_VALUE
190 && GetLastError() == ERROR_FILE_NOT_FOUND
,
191 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
193 /* Functional checks */
195 hnp
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, pipemode
| PIPE_WAIT
,
196 /* nMaxInstances */ 1,
197 /* nOutBufSize */ 1024,
198 /* nInBufSize */ 1024,
199 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
200 /* lpSecurityAttrib */ NULL
);
201 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
204 ret
= WaitNamedPipeA(PIPENAME
, 2000);
205 ok(ret
, "WaitNamedPipe failed (%d)\n", GetLastError());
207 hFile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
208 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed (%d)\n", GetLastError());
210 ok(!WaitNamedPipeA(PIPENAME
, 100), "WaitNamedPipe succeeded\n");
212 ok(GetLastError() == ERROR_SEM_TIMEOUT
, "wrong error %u\n", GetLastError());
214 /* don't try to do i/o if one side couldn't be opened, as it hangs */
215 if (hFile
!= INVALID_HANDLE_VALUE
) {
218 /* Make sure we can read and write a few bytes in both directions */
219 memset(ibuf
, 0, sizeof(ibuf
));
220 ok(WriteFile(hnp
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile\n");
221 ok(written
== sizeof(obuf
), "write file len\n");
222 ok(ReadFile(hFile
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
223 ok(readden
== sizeof(obuf
), "read got %d bytes\n", readden
);
224 ok(memcmp(obuf
, ibuf
, written
) == 0, "content check\n");
226 memset(ibuf
, 0, sizeof(ibuf
));
227 ok(WriteFile(hFile
, obuf2
, sizeof(obuf2
), &written
, NULL
), "WriteFile\n");
228 ok(written
== sizeof(obuf2
), "write file len\n");
229 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
230 ok(readden
== sizeof(obuf2
), "read got %d bytes\n", readden
);
231 ok(memcmp(obuf2
, ibuf
, written
) == 0, "content check\n");
233 /* Now the same again, but with an additional call to PeekNamedPipe */
234 memset(ibuf
, 0, sizeof(ibuf
));
235 ok(WriteFile(hnp
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile\n");
236 ok(written
== sizeof(obuf
), "write file len 1\n");
237 ok(PeekNamedPipe(hFile
, NULL
, 0, NULL
, &avail
, &left
), "Peek\n");
238 ok(avail
== sizeof(obuf
), "peek 1 got %d bytes\n", avail
);
239 if (pipemode
== PIPE_TYPE_BYTE
)
240 ok(left
== 0, "peek 1 got %d bytes left\n", left
);
242 ok(left
== sizeof(obuf
), "peek 1 got %d bytes left\n", left
);
243 ok(ReadFile(hFile
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
244 ok(readden
== sizeof(obuf
), "read 1 got %d bytes\n", readden
);
245 ok(memcmp(obuf
, ibuf
, written
) == 0, "content 1 check\n");
247 memset(ibuf
, 0, sizeof(ibuf
));
248 ok(WriteFile(hFile
, obuf2
, sizeof(obuf2
), &written
, NULL
), "WriteFile\n");
249 ok(written
== sizeof(obuf2
), "write file len 2\n");
250 ok(PeekNamedPipe(hnp
, NULL
, 0, NULL
, &avail
, &left
), "Peek\n");
251 ok(avail
== sizeof(obuf2
), "peek 2 got %d bytes\n", avail
);
252 if (pipemode
== PIPE_TYPE_BYTE
)
253 ok(left
== 0, "peek 2 got %d bytes left\n", left
);
255 ok(left
== sizeof(obuf2
), "peek 2 got %d bytes left\n", left
);
256 ok(PeekNamedPipe(hnp
, (LPVOID
)1, 0, NULL
, &avail
, &left
), "Peek\n");
257 ok(avail
== sizeof(obuf2
), "peek 2 got %d bytes\n", avail
);
258 if (pipemode
== PIPE_TYPE_BYTE
)
259 ok(left
== 0, "peek 2 got %d bytes left\n", left
);
261 ok(left
== sizeof(obuf2
), "peek 2 got %d bytes left\n", left
);
262 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
263 ok(readden
== sizeof(obuf2
), "read 2 got %d bytes\n", readden
);
264 ok(memcmp(obuf2
, ibuf
, written
) == 0, "content 2 check\n");
266 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
267 memset(ibuf
, 0, sizeof(ibuf
));
268 ok(WriteFile(hnp
, obuf2
, sizeof(obuf2
), &written
, NULL
), "WriteFile\n");
269 ok(written
== sizeof(obuf2
), "write file len\n");
270 ok(PeekNamedPipe(hFile
, ibuf
, 4, &readden
, &avail
, &left
), "Peek\n");
271 ok(readden
== 4, "peek got %d bytes\n", readden
);
272 ok(avail
== sizeof(obuf2
), "peek got %d bytes available\n", avail
);
273 if (pipemode
== PIPE_TYPE_BYTE
)
274 ok(left
== -4, "peek got %d bytes left\n", left
);
276 ok(left
== sizeof(obuf2
)-4, "peek got %d bytes left\n", left
);
277 ok(ReadFile(hFile
, ibuf
, 4, &readden
, NULL
), "ReadFile\n");
278 ok(readden
== 4, "read got %d bytes\n", readden
);
279 ok(ReadFile(hFile
, ibuf
+ 4, sizeof(ibuf
) - 4, &readden
, NULL
), "ReadFile\n");
280 ok(readden
== sizeof(obuf2
) - 4, "read got %d bytes\n", readden
);
281 ok(memcmp(obuf2
, ibuf
, written
) == 0, "content check\n");
283 memset(ibuf
, 0, sizeof(ibuf
));
284 ok(WriteFile(hFile
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile\n");
285 ok(written
== sizeof(obuf
), "write file len\n");
286 ok(PeekNamedPipe(hnp
, ibuf
, 4, &readden
, &avail
, &left
), "Peek\n");
287 ok(readden
== 4, "peek got %d bytes\n", readden
);
288 ok(avail
== sizeof(obuf
), "peek got %d bytes available\n", avail
);
289 if (pipemode
== PIPE_TYPE_BYTE
)
291 ok(left
== -4, "peek got %d bytes left\n", left
);
292 ok(ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile\n");
296 ok(left
== sizeof(obuf
)-4, "peek got %d bytes left\n", left
);
297 SetLastError(0xdeadbeef);
298 ok(!ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile\n");
299 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error\n");
301 ok(readden
== 4, "read got %d bytes\n", readden
);
302 ok(ReadFile(hnp
, ibuf
+ 4, sizeof(ibuf
) - 4, &readden
, NULL
), "ReadFile\n");
303 ok(readden
== sizeof(obuf
) - 4, "read got %d bytes\n", readden
);
304 ok(memcmp(obuf
, ibuf
, written
) == 0, "content check\n");
306 /* Similar to above, but use a read buffer size small enough to read in three parts */
307 memset(ibuf
, 0, sizeof(ibuf
));
308 ok(WriteFile(hFile
, obuf2
, sizeof(obuf2
), &written
, NULL
), "WriteFile\n");
309 ok(written
== sizeof(obuf2
), "write file len\n");
310 if (pipemode
== PIPE_TYPE_BYTE
)
312 ok(ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile\n");
313 ok(readden
== 4, "read got %d bytes\n", readden
);
314 ok(ReadFile(hnp
, ibuf
+ 4, 4, &readden
, NULL
), "ReadFile\n");
318 SetLastError(0xdeadbeef);
319 ok(!ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile\n");
320 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error\n");
321 ok(readden
== 4, "read got %d bytes\n", readden
);
322 SetLastError(0xdeadbeef);
323 ok(!ReadFile(hnp
, ibuf
+ 4, 4, &readden
, NULL
), "ReadFile\n");
324 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error\n");
326 ok(readden
== 4, "read got %d bytes\n", readden
);
327 ok(ReadFile(hnp
, ibuf
+ 8, sizeof(ibuf
) - 8, &readden
, NULL
), "ReadFile\n");
328 ok(readden
== sizeof(obuf2
) - 8, "read got %d bytes\n", readden
);
329 ok(memcmp(obuf2
, ibuf
, written
) == 0, "content check\n");
331 /* Test reading of multiple writes */
332 memset(ibuf
, 0, sizeof(ibuf
));
333 ok(WriteFile(hnp
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile3a\n");
334 ok(written
== sizeof(obuf
), "write file len 3a\n");
335 ok(WriteFile(hnp
, obuf2
, sizeof(obuf2
), &written
, NULL
), " WriteFile3b\n");
336 ok(written
== sizeof(obuf2
), "write file len 3b\n");
337 ok(PeekNamedPipe(hFile
, ibuf
, 4, &readden
, &avail
, &left
), "Peek3\n");
338 ok(readden
== 4, "peek3 got %d bytes\n", readden
);
339 if (pipemode
== PIPE_TYPE_BYTE
)
340 ok(left
== -4, "peek3 got %d bytes left\n", left
);
342 ok(left
== sizeof(obuf
)-4, "peek3 got %d bytes left\n", left
);
343 ok(avail
== sizeof(obuf
) + sizeof(obuf2
), "peek3 got %d bytes available\n", avail
);
344 ok(PeekNamedPipe(hFile
, ibuf
, sizeof(ibuf
), &readden
, &avail
, &left
), "Peek3\n");
345 if (pipemode
== PIPE_TYPE_BYTE
) {
346 /* currently the Wine behavior depends on the kernel version */
347 /* ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden); */
348 if (readden
!= sizeof(obuf
) + sizeof(obuf2
)) todo_wine
ok(0, "peek3 got %d bytes\n", readden
);
349 ok(left
== (DWORD
) -(sizeof(obuf
) + sizeof(obuf2
)), "peek3 got %d bytes left\n", left
);
353 ok(readden
== sizeof(obuf
), "peek3 got %d bytes\n", readden
);
354 ok(left
== 0, "peek3 got %d bytes left\n", left
);
356 ok(avail
== sizeof(obuf
) + sizeof(obuf2
), "peek3 got %d bytes available\n", avail
);
358 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "pipe content 3a check\n");
359 if (pipemode
== PIPE_TYPE_BYTE
&& readden
>= sizeof(obuf
)+sizeof(obuf2
)) {
360 pbuf
+= sizeof(obuf
);
361 ok(memcmp(obuf2
, pbuf
, sizeof(obuf2
)) == 0, "pipe content 3b check\n");
363 ok(ReadFile(hFile
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
364 ok(readden
== sizeof(obuf
) + sizeof(obuf2
), "read 3 got %d bytes\n", readden
);
366 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "content 3a check\n");
367 pbuf
+= sizeof(obuf
);
368 ok(memcmp(obuf2
, pbuf
, sizeof(obuf2
)) == 0, "content 3b check\n");
370 /* Multiple writes in the reverse direction */
371 memset(ibuf
, 0, sizeof(ibuf
));
372 ok(WriteFile(hFile
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile4a\n");
373 ok(written
== sizeof(obuf
), "write file len 4a\n");
374 ok(WriteFile(hFile
, obuf2
, sizeof(obuf2
), &written
, NULL
), " WriteFile4b\n");
375 ok(written
== sizeof(obuf2
), "write file len 4b\n");
376 ok(PeekNamedPipe(hnp
, ibuf
, 4, &readden
, &avail
, &left
), "Peek3\n");
377 ok(readden
== 4, "peek3 got %d bytes\n", readden
);
378 if (pipemode
== PIPE_TYPE_BYTE
)
379 ok(left
== -4, "peek3 got %d bytes left\n", left
);
381 ok(left
== sizeof(obuf
)-4, "peek3 got %d bytes left\n", left
);
382 ok(avail
== sizeof(obuf
) + sizeof(obuf2
), "peek3 got %d bytes available\n", avail
);
383 ok(PeekNamedPipe(hnp
, ibuf
, sizeof(ibuf
), &readden
, &avail
, &left
), "Peek4\n");
384 if (pipemode
== PIPE_TYPE_BYTE
) {
385 /* currently the Wine behavior depends on the kernel version */
386 /* ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden); */
387 if (readden
!= sizeof(obuf
) + sizeof(obuf2
)) todo_wine
ok(0, "peek4 got %d bytes\n", readden
);
388 ok(left
== (DWORD
) -(sizeof(obuf
) + sizeof(obuf2
)), "peek4 got %d bytes left\n", left
);
392 ok(readden
== sizeof(obuf
), "peek4 got %d bytes\n", readden
);
393 ok(left
== 0, "peek4 got %d bytes left\n", left
);
395 ok(avail
== sizeof(obuf
) + sizeof(obuf2
), "peek4 got %d bytes available\n", avail
);
397 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "pipe content 4a check\n");
398 if (pipemode
== PIPE_TYPE_BYTE
&& readden
>= sizeof(obuf
)+sizeof(obuf2
)) {
399 pbuf
+= sizeof(obuf
);
400 ok(memcmp(obuf2
, pbuf
, sizeof(obuf2
)) == 0, "pipe content 4b check\n");
402 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
403 if (pipemode
== PIPE_TYPE_BYTE
) {
404 ok(readden
== sizeof(obuf
) + sizeof(obuf2
), "read 4 got %d bytes\n", readden
);
407 ok(readden
== sizeof(obuf
), "read 4 got %d bytes\n", readden
);
410 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "content 4a check\n");
411 if (pipemode
== PIPE_TYPE_BYTE
) {
412 pbuf
+= sizeof(obuf
);
413 ok(memcmp(obuf2
, pbuf
, sizeof(obuf2
)) == 0, "content 4b check\n");
416 /* Test reading of multiple writes after a mode change
417 (CreateFile always creates a byte mode pipe) */
418 lpmode
= PIPE_READMODE_MESSAGE
;
419 if (pipemode
== PIPE_TYPE_BYTE
) {
420 /* trying to change the client end of a byte pipe to message mode should fail */
421 ok(!SetNamedPipeHandleState(hFile
, &lpmode
, NULL
, NULL
), "Change mode\n");
424 ok(SetNamedPipeHandleState(hFile
, &lpmode
, NULL
, NULL
), "Change mode\n");
426 memset(ibuf
, 0, sizeof(ibuf
));
427 ok(WriteFile(hnp
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile5a\n");
428 ok(written
== sizeof(obuf
), "write file len 3a\n");
429 ok(WriteFile(hnp
, obuf2
, sizeof(obuf2
), &written
, NULL
), " WriteFile5b\n");
430 ok(written
== sizeof(obuf2
), "write file len 3b\n");
431 ok(PeekNamedPipe(hFile
, ibuf
, sizeof(ibuf
), &readden
, &avail
, &left
), "Peek5\n");
432 ok(readden
== sizeof(obuf
), "peek5 got %d bytes\n", readden
);
433 ok(avail
== sizeof(obuf
) + sizeof(obuf2
), "peek5 got %d bytes available\n", avail
);
434 ok(left
== 0, "peek5 got %d bytes left\n", left
);
436 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "content 5a check\n");
437 ok(ReadFile(hFile
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
438 ok(readden
== sizeof(obuf
), "read 5 got %d bytes\n", readden
);
440 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "content 5a check\n");
441 if (readden
<= sizeof(obuf
))
442 ok(ReadFile(hFile
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
444 /* Multiple writes in the reverse direction */
445 /* the write of obuf2 from write4 should still be in the buffer */
446 ok(PeekNamedPipe(hnp
, ibuf
, sizeof(ibuf
), &readden
, &avail
, NULL
), "Peek6a\n");
447 ok(readden
== sizeof(obuf2
), "peek6a got %d bytes\n", readden
);
448 ok(avail
== sizeof(obuf2
), "peek6a got %d bytes available\n", avail
);
450 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
451 ok(readden
== sizeof(obuf2
), "read 6a got %d bytes\n", readden
);
453 ok(memcmp(obuf2
, pbuf
, sizeof(obuf2
)) == 0, "content 6a check\n");
455 memset(ibuf
, 0, sizeof(ibuf
));
456 ok(WriteFile(hFile
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile6a\n");
457 ok(written
== sizeof(obuf
), "write file len 6a\n");
458 ok(WriteFile(hFile
, obuf2
, sizeof(obuf2
), &written
, NULL
), " WriteFile6b\n");
459 ok(written
== sizeof(obuf2
), "write file len 6b\n");
460 ok(PeekNamedPipe(hnp
, ibuf
, sizeof(ibuf
), &readden
, &avail
, NULL
), "Peek6\n");
461 ok(readden
== sizeof(obuf
), "peek6 got %d bytes\n", readden
);
463 ok(avail
== sizeof(obuf
) + sizeof(obuf2
), "peek6b got %d bytes available\n", avail
);
465 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "content 6a check\n");
466 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
467 ok(readden
== sizeof(obuf
), "read 6b got %d bytes\n", readden
);
469 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "content 6a check\n");
470 if (readden
<= sizeof(obuf
))
471 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
473 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
474 memset(ibuf
, 0, sizeof(ibuf
));
475 ok(WriteFile(hnp
, obuf2
, sizeof(obuf2
), &written
, NULL
), "WriteFile 7\n");
476 ok(written
== sizeof(obuf2
), "write file len 7\n");
477 SetLastError(0xdeadbeef);
478 ok(!ReadFile(hFile
, ibuf
, 4, &readden
, NULL
), "ReadFile 7\n");
479 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 7\n");
480 ok(readden
== 4, "read got %d bytes 7\n", readden
);
481 ok(ReadFile(hFile
, ibuf
+ 4, sizeof(ibuf
) - 4, &readden
, NULL
), "ReadFile 7\n");
482 ok(readden
== sizeof(obuf2
) - 4, "read got %d bytes 7\n", readden
);
483 ok(memcmp(obuf2
, ibuf
, written
) == 0, "content check 7\n");
485 memset(ibuf
, 0, sizeof(ibuf
));
486 ok(WriteFile(hFile
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile 8\n");
487 ok(written
== sizeof(obuf
), "write file len 8\n");
488 SetLastError(0xdeadbeef);
489 ok(!ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile 8\n");
490 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 8\n");
491 ok(readden
== 4, "read got %d bytes 8\n", readden
);
492 ok(ReadFile(hnp
, ibuf
+ 4, sizeof(ibuf
) - 4, &readden
, NULL
), "ReadFile 8\n");
493 ok(readden
== sizeof(obuf
) - 4, "read got %d bytes 8\n", readden
);
494 ok(memcmp(obuf
, ibuf
, written
) == 0, "content check 8\n");
496 /* The following test shows that when doing a partial read of a message, the rest
497 * is still in the pipe, and can be received from a second thread. This shows
498 * especially that the content is _not_ stored in thread-local-storage until it is
499 * completely transmitted. The same method works even across multiple processes. */
500 memset(ibuf
, 0, sizeof(ibuf
));
501 ok(WriteFile(hnp
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile 9\n");
502 ok(written
== sizeof(obuf
), "write file len 9\n");
503 ok(WriteFile(hnp
, obuf2
, sizeof(obuf2
), &written
, NULL
), "WriteFile 9\n");
504 ok(written
== sizeof(obuf2
), "write file len 9\n");
505 SetLastError(0xdeadbeef);
506 ok(!ReadFile(hFile
, ibuf
, 4, &readden
, NULL
), "ReadFile 9\n");
507 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 9\n");
508 ok(readden
== 4, "read got %d bytes 9\n", readden
);
509 SetLastError(0xdeadbeef);
510 ret
= RpcReadFile(hFile
, ibuf
+ 4, 4, &readden
, NULL
);
511 ok(!ret
, "RpcReadFile 9\n");
512 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 9\n");
513 ok(readden
== 4, "read got %d bytes 9\n", readden
);
514 ret
= RpcReadFile(hFile
, ibuf
+ 8, sizeof(ibuf
), &readden
, NULL
);
515 ok(ret
, "RpcReadFile 9\n");
516 ok(readden
== sizeof(obuf
) - 8, "read got %d bytes 9\n", readden
);
517 ok(memcmp(obuf
, ibuf
, sizeof(obuf
)) == 0, "content check 9\n");
518 if (readden
<= sizeof(obuf
) - 8) /* blocks forever if second part was already received */
520 memset(ibuf
, 0, sizeof(ibuf
));
521 SetLastError(0xdeadbeef);
522 ret
= RpcReadFile(hFile
, ibuf
, 4, &readden
, NULL
);
523 ok(!ret
, "RpcReadFile 9\n");
524 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 9\n");
525 ok(readden
== 4, "read got %d bytes 9\n", readden
);
526 SetLastError(0xdeadbeef);
527 ok(!ReadFile(hFile
, ibuf
+ 4, 4, &readden
, NULL
), "ReadFile 9\n");
528 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 9\n");
529 ok(readden
== 4, "read got %d bytes 9\n", readden
);
530 ret
= RpcReadFile(hFile
, ibuf
+ 8, sizeof(ibuf
), &readden
, NULL
);
531 ok(ret
, "RpcReadFile 9\n");
532 ok(readden
== sizeof(obuf2
) - 8, "read got %d bytes 9\n", readden
);
533 ok(memcmp(obuf2
, ibuf
, sizeof(obuf2
)) == 0, "content check 9\n");
536 /* Now the reverse direction */
537 memset(ibuf
, 0, sizeof(ibuf
));
538 ok(WriteFile(hFile
, obuf2
, sizeof(obuf2
), &written
, NULL
), "WriteFile 10\n");
539 ok(written
== sizeof(obuf2
), "write file len 10\n");
540 ok(WriteFile(hFile
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile 10\n");
541 ok(written
== sizeof(obuf
), "write file len 10\n");
542 SetLastError(0xdeadbeef);
543 ok(!ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile 10\n");
544 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 10\n");
545 ok(readden
== 4, "read got %d bytes 10\n", readden
);
546 SetLastError(0xdeadbeef);
547 ret
= RpcReadFile(hnp
, ibuf
+ 4, 4, &readden
, NULL
);
548 ok(!ret
, "RpcReadFile 10\n");
549 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 10\n");
550 ok(readden
== 4, "read got %d bytes 10\n", readden
);
551 ret
= RpcReadFile(hnp
, ibuf
+ 8, sizeof(ibuf
), &readden
, NULL
);
552 ok(ret
, "RpcReadFile 10\n");
553 ok(readden
== sizeof(obuf2
) - 8, "read got %d bytes 10\n", readden
);
554 ok(memcmp(obuf2
, ibuf
, sizeof(obuf2
)) == 0, "content check 10\n");
555 if (readden
<= sizeof(obuf2
) - 8) /* blocks forever if second part was already received */
557 memset(ibuf
, 0, sizeof(ibuf
));
558 SetLastError(0xdeadbeef);
559 ret
= RpcReadFile(hnp
, ibuf
, 4, &readden
, NULL
);
560 ok(!ret
, "RpcReadFile 10\n");
561 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 10\n");
562 ok(readden
== 4, "read got %d bytes 10\n", readden
);
563 SetLastError(0xdeadbeef);
564 ok(!ReadFile(hnp
, ibuf
+ 4, 4, &readden
, NULL
), "ReadFile 10\n");
565 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 10\n");
566 ok(readden
== 4, "read got %d bytes 10\n", readden
);
567 ret
= RpcReadFile(hnp
, ibuf
+ 8, sizeof(ibuf
), &readden
, NULL
);
568 ok(ret
, "RpcReadFile 10\n");
569 ok(readden
== sizeof(obuf
) - 8, "read got %d bytes 10\n", readden
);
570 ok(memcmp(obuf
, ibuf
, sizeof(obuf
)) == 0, "content check 10\n");
575 /* Picky conformance tests */
577 /* Verify that you can't connect to pipe again
578 * until server calls DisconnectNamedPipe+ConnectNamedPipe
579 * or creates a new pipe
580 * case 1: other client not yet closed
582 hFile2
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
583 ok(hFile2
== INVALID_HANDLE_VALUE
,
584 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
585 ok(GetLastError() == ERROR_PIPE_BUSY
,
586 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
588 ok(CloseHandle(hFile
), "CloseHandle\n");
590 /* case 2: other client already closed */
591 hFile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
592 ok(hFile
== INVALID_HANDLE_VALUE
,
593 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
594 ok(GetLastError() == ERROR_PIPE_BUSY
,
595 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
597 ok(DisconnectNamedPipe(hnp
), "DisconnectNamedPipe\n");
599 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
600 hFile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
601 ok(hFile
== INVALID_HANDLE_VALUE
,
602 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
603 ok(GetLastError() == ERROR_PIPE_BUSY
,
604 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
606 /* to be complete, we'd call ConnectNamedPipe here and loop,
607 * but by default that's blocking, so we'd either have
608 * to turn on the uncommon nonblocking mode, or
609 * use another thread.
613 ok(CloseHandle(hnp
), "CloseHandle\n");
615 hnp
= CreateNamedPipeA(PIPENAME_SPECIAL
, PIPE_ACCESS_DUPLEX
, pipemode
| PIPE_WAIT
,
616 /* nMaxInstances */ 1,
617 /* nOutBufSize */ 1024,
618 /* nInBufSize */ 1024,
619 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
620 /* lpSecurityAttrib */ NULL
);
621 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe with special characters failed\n");
622 ok(CloseHandle(hnp
), "CloseHandle\n");
624 trace("test_CreateNamedPipe returning\n");
627 static void test_CreateNamedPipe_instances_must_match(void)
631 /* Check no mismatch */
632 hnp
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
633 /* nMaxInstances */ 2,
634 /* nOutBufSize */ 1024,
635 /* nInBufSize */ 1024,
636 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
637 /* lpSecurityAttrib */ NULL
);
638 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
640 hnp2
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
641 /* nMaxInstances */ 2,
642 /* nOutBufSize */ 1024,
643 /* nInBufSize */ 1024,
644 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
645 /* lpSecurityAttrib */ NULL
);
646 ok(hnp2
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
648 ok(CloseHandle(hnp
), "CloseHandle\n");
649 ok(CloseHandle(hnp2
), "CloseHandle\n");
651 /* Check nMaxInstances */
652 hnp
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
653 /* nMaxInstances */ 1,
654 /* nOutBufSize */ 1024,
655 /* nInBufSize */ 1024,
656 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
657 /* lpSecurityAttrib */ NULL
);
658 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
660 hnp2
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
661 /* nMaxInstances */ 1,
662 /* nOutBufSize */ 1024,
663 /* nInBufSize */ 1024,
664 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
665 /* lpSecurityAttrib */ NULL
);
666 ok(hnp2
== INVALID_HANDLE_VALUE
667 && GetLastError() == ERROR_PIPE_BUSY
, "nMaxInstances not obeyed\n");
669 ok(CloseHandle(hnp
), "CloseHandle\n");
671 /* Check PIPE_ACCESS_* */
672 hnp
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
673 /* nMaxInstances */ 2,
674 /* nOutBufSize */ 1024,
675 /* nInBufSize */ 1024,
676 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
677 /* lpSecurityAttrib */ NULL
);
678 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
680 hnp2
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_INBOUND
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
681 /* nMaxInstances */ 2,
682 /* nOutBufSize */ 1024,
683 /* nInBufSize */ 1024,
684 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
685 /* lpSecurityAttrib */ NULL
);
686 ok(hnp2
== INVALID_HANDLE_VALUE
687 && GetLastError() == ERROR_ACCESS_DENIED
, "PIPE_ACCESS_* mismatch allowed\n");
689 ok(CloseHandle(hnp
), "CloseHandle\n");
691 /* check everything else */
692 hnp
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
693 /* nMaxInstances */ 4,
694 /* nOutBufSize */ 1024,
695 /* nInBufSize */ 1024,
696 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
697 /* lpSecurityAttrib */ NULL
);
698 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
700 hnp2
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_MESSAGE
,
701 /* nMaxInstances */ 3,
702 /* nOutBufSize */ 102,
704 /* nDefaultWait */ 1234,
705 /* lpSecurityAttrib */ NULL
);
706 ok(hnp2
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
708 ok(CloseHandle(hnp
), "CloseHandle\n");
709 ok(CloseHandle(hnp2
), "CloseHandle\n");
712 /** implementation of alarm() */
713 static DWORD CALLBACK
alarmThreadMain(LPVOID arg
)
715 DWORD_PTR timeout
= (DWORD_PTR
) arg
;
716 trace("alarmThreadMain\n");
717 if (WaitForSingleObject( alarm_event
, timeout
) == WAIT_TIMEOUT
)
719 ok(FALSE
, "alarm\n");
725 static HANDLE hnp
= INVALID_HANDLE_VALUE
;
727 /** Trivial byte echo server - disconnects after each session */
728 static DWORD CALLBACK
serverThreadMain1(LPVOID arg
)
732 trace("serverThreadMain1 start\n");
733 /* Set up a simple echo server */
734 hnp
= CreateNamedPipeA(PIPENAME
"serverThreadMain1", PIPE_ACCESS_DUPLEX
,
735 PIPE_TYPE_BYTE
| PIPE_WAIT
,
736 /* nMaxInstances */ 1,
737 /* nOutBufSize */ 1024,
738 /* nInBufSize */ 1024,
739 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
740 /* lpSecurityAttrib */ NULL
);
742 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
743 for (i
= 0; i
< NB_SERVER_LOOPS
; i
++) {
749 /* Wait for client to connect */
750 trace("Server calling ConnectNamedPipe...\n");
751 ok(ConnectNamedPipe(hnp
, NULL
)
752 || GetLastError() == ERROR_PIPE_CONNECTED
, "ConnectNamedPipe\n");
753 trace("ConnectNamedPipe returned.\n");
755 /* Echo bytes once */
756 memset(buf
, 0, sizeof(buf
));
758 trace("Server reading...\n");
759 success
= ReadFile(hnp
, buf
, sizeof(buf
), &readden
, NULL
);
760 trace("Server done reading.\n");
761 ok(success
, "ReadFile\n");
762 ok(readden
, "short read\n");
764 trace("Server writing...\n");
765 ok(WriteFile(hnp
, buf
, readden
, &written
, NULL
), "WriteFile\n");
766 trace("Server done writing.\n");
767 ok(written
== readden
, "write file len\n");
769 /* finish this connection, wait for next one */
770 ok(FlushFileBuffers(hnp
), "FlushFileBuffers\n");
771 trace("Server done flushing.\n");
772 ok(DisconnectNamedPipe(hnp
), "DisconnectNamedPipe\n");
773 trace("Server done disconnecting.\n");
778 /** Trivial byte echo server - closes after each connection */
779 static DWORD CALLBACK
serverThreadMain2(LPVOID arg
)
784 trace("serverThreadMain2\n");
785 /* Set up a simple echo server */
786 hnp
= CreateNamedPipeA(PIPENAME
"serverThreadMain2", PIPE_ACCESS_DUPLEX
,
787 PIPE_TYPE_BYTE
| PIPE_WAIT
,
788 /* nMaxInstances */ 2,
789 /* nOutBufSize */ 1024,
790 /* nInBufSize */ 1024,
791 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
792 /* lpSecurityAttrib */ NULL
);
793 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
795 for (i
= 0; i
< NB_SERVER_LOOPS
; i
++) {
803 user_apc_ran
= FALSE
;
804 if (i
== 0 && pQueueUserAPC
) {
805 trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
806 ret
= pQueueUserAPC(&user_apc
, GetCurrentThread(), 0);
807 ok(ret
, "QueueUserAPC failed: %d\n", GetLastError());
810 /* Wait for client to connect */
811 trace("Server calling ConnectNamedPipe...\n");
812 ok(ConnectNamedPipe(hnp
, NULL
)
813 || GetLastError() == ERROR_PIPE_CONNECTED
, "ConnectNamedPipe\n");
814 trace("ConnectNamedPipe returned.\n");
816 /* Echo bytes once */
817 memset(buf
, 0, sizeof(buf
));
819 trace("Server reading...\n");
820 success
= ReadFile(hnp
, buf
, sizeof(buf
), &readden
, NULL
);
821 trace("Server done reading.\n");
822 ok(success
, "ReadFile\n");
824 trace("Server writing...\n");
825 ok(WriteFile(hnp
, buf
, readden
, &written
, NULL
), "WriteFile\n");
826 trace("Server done writing.\n");
827 ok(written
== readden
, "write file len\n");
829 /* finish this connection, wait for next one */
830 ok(FlushFileBuffers(hnp
), "FlushFileBuffers\n");
831 ok(DisconnectNamedPipe(hnp
), "DisconnectNamedPipe\n");
833 ok(user_apc_ran
== FALSE
, "UserAPC ran, pipe using alertable io mode\n");
835 if (i
== 0 && pQueueUserAPC
)
836 SleepEx(0, TRUE
); /* get rid of apc */
838 /* Set up next echo server */
840 CreateNamedPipeA(PIPENAME
"serverThreadMain2", PIPE_ACCESS_DUPLEX
,
841 PIPE_TYPE_BYTE
| PIPE_WAIT
,
842 /* nMaxInstances */ 2,
843 /* nOutBufSize */ 1024,
844 /* nInBufSize */ 1024,
845 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
846 /* lpSecurityAttrib */ NULL
);
848 ok(hnpNext
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
850 ok(CloseHandle(hnp
), "CloseHandle\n");
856 /** Trivial byte echo server - uses overlapped named pipe calls */
857 static DWORD CALLBACK
serverThreadMain3(LPVOID arg
)
862 trace("serverThreadMain3\n");
863 /* Set up a simple echo server */
864 hnp
= CreateNamedPipeA(PIPENAME
"serverThreadMain3", PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
865 PIPE_TYPE_BYTE
| PIPE_WAIT
,
866 /* nMaxInstances */ 1,
867 /* nOutBufSize */ 1024,
868 /* nInBufSize */ 1024,
869 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
870 /* lpSecurityAttrib */ NULL
);
871 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
873 hEvent
= CreateEventW(NULL
, /* security attribute */
874 TRUE
, /* manual reset event */
875 FALSE
, /* initial state */
877 ok(hEvent
!= NULL
, "CreateEvent\n");
879 for (i
= 0; i
< NB_SERVER_LOOPS
; i
++) {
886 int letWFSOEwait
= (i
& 2);
887 int letGORwait
= (i
& 1);
890 memset(&oOverlap
, 0, sizeof(oOverlap
));
891 oOverlap
.hEvent
= hEvent
;
893 /* Wait for client to connect */
895 trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
896 success
= ConnectNamedPipe(hnp
, NULL
);
897 err
= GetLastError();
898 ok(success
|| (err
== ERROR_PIPE_CONNECTED
), "ConnectNamedPipe failed: %d\n", err
);
899 trace("ConnectNamedPipe operation complete.\n");
901 trace("Server calling overlapped ConnectNamedPipe...\n");
902 success
= ConnectNamedPipe(hnp
, &oOverlap
);
903 err
= GetLastError();
904 ok(!success
&& (err
== ERROR_IO_PENDING
|| err
== ERROR_PIPE_CONNECTED
), "overlapped ConnectNamedPipe\n");
905 trace("overlapped ConnectNamedPipe returned.\n");
906 if (!success
&& (err
== ERROR_IO_PENDING
)) {
911 ret
= WaitForSingleObjectEx(hEvent
, INFINITE
, TRUE
);
912 } while (ret
== WAIT_IO_COMPLETION
);
913 ok(ret
== 0, "wait ConnectNamedPipe returned %x\n", ret
);
915 success
= GetOverlappedResult(hnp
, &oOverlap
, &dummy
, letGORwait
);
916 if (!letGORwait
&& !letWFSOEwait
&& !success
) {
917 ok(GetLastError() == ERROR_IO_INCOMPLETE
, "GetOverlappedResult\n");
918 success
= GetOverlappedResult(hnp
, &oOverlap
, &dummy
, TRUE
);
921 ok(success
|| (err
== ERROR_PIPE_CONNECTED
), "GetOverlappedResult ConnectNamedPipe\n");
922 trace("overlapped ConnectNamedPipe operation complete.\n");
925 /* Echo bytes once */
926 memset(buf
, 0, sizeof(buf
));
928 trace("Server reading...\n");
929 success
= ReadFile(hnp
, buf
, sizeof(buf
), &readden
, &oOverlap
);
930 trace("Server ReadFile returned...\n");
931 err
= GetLastError();
932 ok(success
|| err
== ERROR_IO_PENDING
, "overlapped ReadFile\n");
933 trace("overlapped ReadFile returned.\n");
934 if (!success
&& (err
== ERROR_IO_PENDING
)) {
939 ret
= WaitForSingleObjectEx(hEvent
, INFINITE
, TRUE
);
940 } while (ret
== WAIT_IO_COMPLETION
);
941 ok(ret
== 0, "wait ReadFile returned %x\n", ret
);
943 success
= GetOverlappedResult(hnp
, &oOverlap
, &readden
, letGORwait
);
944 if (!letGORwait
&& !letWFSOEwait
&& !success
) {
945 ok(GetLastError() == ERROR_IO_INCOMPLETE
, "GetOverlappedResult\n");
946 success
= GetOverlappedResult(hnp
, &oOverlap
, &readden
, TRUE
);
949 trace("Server done reading.\n");
950 ok(success
, "overlapped ReadFile\n");
952 trace("Server writing...\n");
953 success
= WriteFile(hnp
, buf
, readden
, &written
, &oOverlap
);
954 trace("Server WriteFile returned...\n");
955 err
= GetLastError();
956 ok(success
|| err
== ERROR_IO_PENDING
, "overlapped WriteFile\n");
957 trace("overlapped WriteFile returned.\n");
958 if (!success
&& (err
== ERROR_IO_PENDING
)) {
963 ret
= WaitForSingleObjectEx(hEvent
, INFINITE
, TRUE
);
964 } while (ret
== WAIT_IO_COMPLETION
);
965 ok(ret
== 0, "wait WriteFile returned %x\n", ret
);
967 success
= GetOverlappedResult(hnp
, &oOverlap
, &written
, letGORwait
);
968 if (!letGORwait
&& !letWFSOEwait
&& !success
) {
969 ok(GetLastError() == ERROR_IO_INCOMPLETE
, "GetOverlappedResult\n");
970 success
= GetOverlappedResult(hnp
, &oOverlap
, &written
, TRUE
);
973 trace("Server done writing.\n");
974 ok(success
, "overlapped WriteFile\n");
975 ok(written
== readden
, "write file len\n");
977 /* finish this connection, wait for next one */
978 ok(FlushFileBuffers(hnp
), "FlushFileBuffers\n");
979 ok(DisconnectNamedPipe(hnp
), "DisconnectNamedPipe\n");
984 /** Trivial byte echo server - uses i/o completion ports */
985 static DWORD CALLBACK
serverThreadMain4(LPVOID arg
)
991 trace("serverThreadMain4\n");
992 /* Set up a simple echo server */
993 hnp
= CreateNamedPipeA(PIPENAME
"serverThreadMain4", PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
994 PIPE_TYPE_BYTE
| PIPE_WAIT
,
995 /* nMaxInstances */ 1,
996 /* nOutBufSize */ 1024,
997 /* nInBufSize */ 1024,
998 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
999 /* lpSecurityAttrib */ NULL
);
1000 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
1002 hcompletion
= CreateIoCompletionPort(hnp
, NULL
, 12345, 1);
1003 ok(hcompletion
!= NULL
, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
1005 for (i
= 0; i
< NB_SERVER_LOOPS
; i
++) {
1011 OVERLAPPED oConnect
;
1014 OVERLAPPED
*oResult
;
1018 memset(&oConnect
, 0, sizeof(oConnect
));
1019 memset(&oRead
, 0, sizeof(oRead
));
1020 memset(&oWrite
, 0, sizeof(oWrite
));
1022 /* Wait for client to connect */
1023 trace("Server calling overlapped ConnectNamedPipe...\n");
1024 success
= ConnectNamedPipe(hnp
, &oConnect
);
1025 err
= GetLastError();
1026 ok(!success
&& (err
== ERROR_IO_PENDING
|| err
== ERROR_PIPE_CONNECTED
),
1027 "overlapped ConnectNamedPipe got %u err %u\n", success
, err
);
1028 if (!success
&& err
== ERROR_IO_PENDING
) {
1029 trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
1030 success
= GetQueuedCompletionStatus(hcompletion
, &dummy
, &compkey
, &oResult
, 0);
1033 ok( GetLastError() == WAIT_TIMEOUT
,
1034 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
1035 success
= GetQueuedCompletionStatus(hcompletion
, &dummy
, &compkey
, &oResult
, 10000);
1037 ok(success
, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1040 ok(compkey
== 12345, "got completion key %i instead of 12345\n", (int)compkey
);
1041 ok(oResult
== &oConnect
, "got overlapped pointer %p instead of %p\n", oResult
, &oConnect
);
1044 trace("overlapped ConnectNamedPipe operation complete.\n");
1046 /* Echo bytes once */
1047 memset(buf
, 0, sizeof(buf
));
1049 trace("Server reading...\n");
1050 success
= ReadFile(hnp
, buf
, sizeof(buf
), &readden
, &oRead
);
1051 trace("Server ReadFile returned...\n");
1052 err
= GetLastError();
1053 ok(success
|| err
== ERROR_IO_PENDING
, "overlapped ReadFile, err=%i\n", err
);
1054 success
= GetQueuedCompletionStatus(hcompletion
, &readden
, &compkey
,
1056 ok(success
, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1059 ok(compkey
== 12345, "got completion key %i instead of 12345\n", (int)compkey
);
1060 ok(oResult
== &oRead
, "got overlapped pointer %p instead of %p\n", oResult
, &oRead
);
1062 trace("Server done reading.\n");
1064 trace("Server writing...\n");
1065 success
= WriteFile(hnp
, buf
, readden
, &written
, &oWrite
);
1066 trace("Server WriteFile returned...\n");
1067 err
= GetLastError();
1068 ok(success
|| err
== ERROR_IO_PENDING
, "overlapped WriteFile failed, err=%u\n", err
);
1069 success
= GetQueuedCompletionStatus(hcompletion
, &written
, &compkey
,
1071 ok(success
, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1074 ok(compkey
== 12345, "got completion key %i instead of 12345\n", (int)compkey
);
1075 ok(oResult
== &oWrite
, "got overlapped pointer %p instead of %p\n", oResult
, &oWrite
);
1076 ok(written
== readden
, "write file len\n");
1078 trace("Server done writing.\n");
1080 /* finish this connection, wait for next one */
1081 ok(FlushFileBuffers(hnp
), "FlushFileBuffers\n");
1082 success
= DisconnectNamedPipe(hnp
);
1083 ok(success
, "DisconnectNamedPipe failed, err %u\n", GetLastError());
1086 ret
= CloseHandle(hnp
);
1087 ok(ret
, "CloseHandle named pipe failed, err=%i\n", GetLastError());
1088 ret
= CloseHandle(hcompletion
);
1089 ok(ret
, "CloseHandle completion failed, err=%i\n", GetLastError());
1094 static int completion_called
;
1095 static DWORD completion_errorcode
;
1096 static DWORD completion_num_bytes
;
1097 static LPOVERLAPPED completion_lpoverlapped
;
1099 static VOID WINAPI
completion_routine(DWORD errorcode
, DWORD num_bytes
, LPOVERLAPPED lpoverlapped
)
1101 completion_called
++;
1102 completion_errorcode
= errorcode
;
1103 completion_num_bytes
= num_bytes
;
1104 completion_lpoverlapped
= lpoverlapped
;
1105 SetEvent(lpoverlapped
->hEvent
);
1108 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
1109 static DWORD CALLBACK
serverThreadMain5(LPVOID arg
)
1114 trace("serverThreadMain5\n");
1115 /* Set up a simple echo server */
1116 hnp
= CreateNamedPipeA(PIPENAME
"serverThreadMain5", PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
1117 PIPE_TYPE_BYTE
| PIPE_WAIT
,
1118 /* nMaxInstances */ 1,
1119 /* nOutBufSize */ 1024,
1120 /* nInBufSize */ 1024,
1121 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
1122 /* lpSecurityAttrib */ NULL
);
1123 ok(hnp
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
1125 hEvent
= CreateEventW(NULL
, /* security attribute */
1126 TRUE
, /* manual reset event */
1127 FALSE
, /* initial state */
1129 ok(hEvent
!= NULL
, "CreateEvent\n");
1131 for (i
= 0; i
< NB_SERVER_LOOPS
; i
++) {
1135 OVERLAPPED oOverlap
;
1138 memset(&oOverlap
, 0, sizeof(oOverlap
));
1139 oOverlap
.hEvent
= hEvent
;
1141 /* Wait for client to connect */
1142 trace("Server calling ConnectNamedPipe...\n");
1143 success
= ConnectNamedPipe(hnp
, NULL
);
1144 err
= GetLastError();
1145 ok(success
|| (err
== ERROR_PIPE_CONNECTED
), "ConnectNamedPipe failed: %d\n", err
);
1146 trace("ConnectNamedPipe operation complete.\n");
1148 /* Echo bytes once */
1149 memset(buf
, 0, sizeof(buf
));
1151 trace("Server reading...\n");
1152 completion_called
= 0;
1154 success
= ReadFileEx(hnp
, buf
, sizeof(buf
), &oOverlap
, completion_routine
);
1155 trace("Server ReadFileEx returned...\n");
1156 ok(success
, "ReadFileEx failed, err=%i\n", GetLastError());
1157 ok(completion_called
== 0, "completion routine called before ReadFileEx return\n");
1158 trace("ReadFileEx returned.\n");
1162 ret
= WaitForSingleObjectEx(hEvent
, INFINITE
, TRUE
);
1163 } while (ret
== WAIT_IO_COMPLETION
);
1164 ok(ret
== 0, "wait ReadFileEx returned %x\n", ret
);
1166 ok(completion_called
== 1, "completion routine called %i times\n", completion_called
);
1167 ok(completion_errorcode
== ERROR_SUCCESS
, "completion routine got error %d\n", completion_errorcode
);
1168 ok(completion_num_bytes
!= 0, "read 0 bytes\n");
1169 ok(completion_lpoverlapped
== &oOverlap
, "got wrong overlapped pointer %p\n", completion_lpoverlapped
);
1170 readden
= completion_num_bytes
;
1171 trace("Server done reading.\n");
1173 trace("Server writing...\n");
1174 completion_called
= 0;
1176 success
= WriteFileEx(hnp
, buf
, readden
, &oOverlap
, completion_routine
);
1177 trace("Server WriteFileEx returned...\n");
1178 ok(success
, "WriteFileEx failed, err=%i\n", GetLastError());
1179 ok(completion_called
== 0, "completion routine called before ReadFileEx return\n");
1180 trace("overlapped WriteFile returned.\n");
1184 ret
= WaitForSingleObjectEx(hEvent
, INFINITE
, TRUE
);
1185 } while (ret
== WAIT_IO_COMPLETION
);
1186 ok(ret
== 0, "wait WriteFileEx returned %x\n", ret
);
1188 trace("Server done writing.\n");
1189 ok(completion_called
== 1, "completion routine called %i times\n", completion_called
);
1190 ok(completion_errorcode
== ERROR_SUCCESS
, "completion routine got error %d\n", completion_errorcode
);
1191 ok(completion_num_bytes
== readden
, "read %i bytes wrote %i\n", readden
, completion_num_bytes
);
1192 ok(completion_lpoverlapped
== &oOverlap
, "got wrong overlapped pointer %p\n", completion_lpoverlapped
);
1194 /* finish this connection, wait for next one */
1195 ok(FlushFileBuffers(hnp
), "FlushFileBuffers\n");
1196 ok(DisconnectNamedPipe(hnp
), "DisconnectNamedPipe\n");
1201 static void exercizeServer(const char *pipename
, HANDLE serverThread
)
1205 trace("exercizeServer starting\n");
1206 for (i
= 0; i
< NB_SERVER_LOOPS
; i
++) {
1207 HANDLE hFile
=INVALID_HANDLE_VALUE
;
1208 static const char obuf
[] = "Bit Bucket";
1214 for (loop
= 0; loop
< 3; loop
++) {
1216 trace("Client connecting...\n");
1217 /* Connect to the server */
1218 hFile
= CreateFileA(pipename
, GENERIC_READ
| GENERIC_WRITE
, 0,
1219 NULL
, OPEN_EXISTING
, 0, 0);
1220 if (hFile
!= INVALID_HANDLE_VALUE
)
1222 err
= GetLastError();
1224 ok(err
== ERROR_PIPE_BUSY
|| err
== ERROR_FILE_NOT_FOUND
, "connecting to pipe\n");
1226 ok(err
== ERROR_PIPE_BUSY
, "connecting to pipe\n");
1227 trace("connect failed, retrying\n");
1230 ok(hFile
!= INVALID_HANDLE_VALUE
, "client opening named pipe\n");
1232 /* Make sure it can echo */
1233 memset(ibuf
, 0, sizeof(ibuf
));
1234 trace("Client writing...\n");
1235 ok(WriteFile(hFile
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile to client end of pipe\n");
1236 ok(written
== sizeof(obuf
), "write file len\n");
1237 trace("Client reading...\n");
1238 ok(ReadFile(hFile
, ibuf
, sizeof(obuf
), &readden
, NULL
), "ReadFile from client end of pipe\n");
1239 ok(readden
== sizeof(obuf
), "read file len\n");
1240 ok(memcmp(obuf
, ibuf
, written
) == 0, "content check\n");
1242 trace("Client closing...\n");
1243 ok(CloseHandle(hFile
), "CloseHandle\n");
1246 ok(WaitForSingleObject(serverThread
,INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject\n");
1248 trace("exercizeServer returning\n");
1251 static void test_NamedPipe_2(void)
1253 HANDLE serverThread
;
1254 DWORD serverThreadId
;
1256 DWORD alarmThreadId
;
1258 trace("test_NamedPipe_2 starting\n");
1259 /* Set up a twenty second timeout */
1260 alarm_event
= CreateEventW( NULL
, TRUE
, FALSE
, NULL
);
1261 SetLastError(0xdeadbeef);
1262 alarmThread
= CreateThread(NULL
, 0, alarmThreadMain
, (void *) 20000, 0, &alarmThreadId
);
1263 ok(alarmThread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1265 /* The servers we're about to exercise do try to clean up carefully,
1266 * but to reduce the chance of a test failure due to a pipe handle
1267 * leak in the test code, we'll use a different pipe name for each server.
1271 SetLastError(0xdeadbeef);
1272 serverThread
= CreateThread(NULL
, 0, serverThreadMain1
, (void *)8, 0, &serverThreadId
);
1273 ok(serverThread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1274 exercizeServer(PIPENAME
"serverThreadMain1", serverThread
);
1277 SetLastError(0xdeadbeef);
1278 serverThread
= CreateThread(NULL
, 0, serverThreadMain2
, 0, 0, &serverThreadId
);
1279 ok(serverThread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1280 exercizeServer(PIPENAME
"serverThreadMain2", serverThread
);
1283 SetLastError(0xdeadbeef);
1284 serverThread
= CreateThread(NULL
, 0, serverThreadMain3
, 0, 0, &serverThreadId
);
1285 ok(serverThread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1286 exercizeServer(PIPENAME
"serverThreadMain3", serverThread
);
1289 SetLastError(0xdeadbeef);
1290 serverThread
= CreateThread(NULL
, 0, serverThreadMain4
, 0, 0, &serverThreadId
);
1291 ok(serverThread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1292 exercizeServer(PIPENAME
"serverThreadMain4", serverThread
);
1295 SetLastError(0xdeadbeef);
1296 serverThread
= CreateThread(NULL
, 0, serverThreadMain5
, 0, 0, &serverThreadId
);
1297 ok(serverThread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1298 exercizeServer(PIPENAME
"serverThreadMain5", serverThread
);
1300 ok(SetEvent( alarm_event
), "SetEvent\n");
1301 CloseHandle( alarm_event
);
1302 trace("test_NamedPipe_2 returning\n");
1305 static int test_DisconnectNamedPipe(void)
1309 static const char obuf
[] = "Bit Bucket";
1315 SetLastError(0xdeadbeef);
1316 hnp
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_WAIT
,
1317 /* nMaxInstances */ 1,
1318 /* nOutBufSize */ 1024,
1319 /* nInBufSize */ 1024,
1320 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
1321 /* lpSecurityAttrib */ NULL
);
1322 if ((hnp
== INVALID_HANDLE_VALUE
/* Win98 */ || !hnp
/* Win95 */)
1323 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
1325 win_skip("Named pipes are not implemented\n");
1329 ok(WriteFile(hnp
, obuf
, sizeof(obuf
), &written
, NULL
) == 0
1330 && GetLastError() == ERROR_PIPE_LISTENING
, "WriteFile to not-yet-connected pipe\n");
1331 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
) == 0
1332 && GetLastError() == ERROR_PIPE_LISTENING
, "ReadFile from not-yet-connected pipe\n");
1334 hFile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1335 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFile failed\n");
1337 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1338 if (hFile
!= INVALID_HANDLE_VALUE
) {
1340 /* see what happens if server calls DisconnectNamedPipe
1341 * when there are bytes in the pipe
1344 ok(WriteFile(hFile
, obuf
, sizeof(obuf
), &written
, NULL
), "WriteFile\n");
1345 ok(written
== sizeof(obuf
), "write file len\n");
1346 ok(DisconnectNamedPipe(hnp
), "DisconnectNamedPipe while messages waiting\n");
1347 ok(WriteFile(hFile
, obuf
, sizeof(obuf
), &written
, NULL
) == 0
1348 && GetLastError() == ERROR_PIPE_NOT_CONNECTED
, "WriteFile to disconnected pipe\n");
1349 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
) == 0
1350 && GetLastError() == ERROR_PIPE_NOT_CONNECTED
,
1351 "ReadFile from disconnected pipe with bytes waiting\n");
1352 ok(!DisconnectNamedPipe(hnp
) && GetLastError() == ERROR_PIPE_NOT_CONNECTED
,
1353 "DisconnectNamedPipe worked twice\n");
1354 ret
= WaitForSingleObject(hFile
, 0);
1355 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %X\n", ret
);
1356 ok(CloseHandle(hFile
), "CloseHandle\n");
1359 ok(CloseHandle(hnp
), "CloseHandle\n");
1363 static void test_CreatePipe(void)
1365 SECURITY_ATTRIBUTES pipe_attr
;
1366 HANDLE piperead
, pipewrite
;
1373 user_apc_ran
= FALSE
;
1375 ok(pQueueUserAPC(user_apc
, GetCurrentThread(), 0), "couldn't create user apc\n");
1377 pipe_attr
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
1378 pipe_attr
.bInheritHandle
= TRUE
;
1379 pipe_attr
.lpSecurityDescriptor
= NULL
;
1380 ok(CreatePipe(&piperead
, &pipewrite
, &pipe_attr
, 0) != 0, "CreatePipe failed\n");
1381 test_pipe_info(piperead
, FILE_PIPE_SERVER_END
, 4096, 4096, 1);
1382 test_pipe_info(pipewrite
, 0, 4096, 4096, 1);
1384 ok(WriteFile(pipewrite
,PIPENAME
,sizeof(PIPENAME
), &written
, NULL
), "Write to anonymous pipe failed\n");
1385 ok(written
== sizeof(PIPENAME
), "Write to anonymous pipe wrote %d bytes\n", written
);
1386 ok(ReadFile(piperead
,readbuf
,sizeof(readbuf
),&read
, NULL
), "Read from non empty pipe failed\n");
1387 ok(read
== sizeof(PIPENAME
), "Read from anonymous pipe got %d bytes\n", read
);
1388 ok(CloseHandle(pipewrite
), "CloseHandle for the write pipe failed\n");
1389 ok(CloseHandle(piperead
), "CloseHandle for the read pipe failed\n");
1391 /* Now write another chunk*/
1392 ok(CreatePipe(&piperead
, &pipewrite
, &pipe_attr
, 0) != 0, "CreatePipe failed\n");
1393 ok(WriteFile(pipewrite
,PIPENAME
,sizeof(PIPENAME
), &written
, NULL
), "Write to anonymous pipe failed\n");
1394 ok(written
== sizeof(PIPENAME
), "Write to anonymous pipe wrote %d bytes\n", written
);
1395 /* and close the write end, read should still succeed*/
1396 ok(CloseHandle(pipewrite
), "CloseHandle for the Write Pipe failed\n");
1397 ok(ReadFile(piperead
,readbuf
,sizeof(readbuf
),&read
, NULL
), "Read from broken pipe with pending data failed\n");
1398 ok(read
== sizeof(PIPENAME
), "Read from anonymous pipe got %d bytes\n", read
);
1399 /* But now we need to get informed that the pipe is closed */
1400 ok(ReadFile(piperead
,readbuf
,sizeof(readbuf
),&read
, NULL
) == 0, "Broken pipe not detected\n");
1401 ok(CloseHandle(piperead
), "CloseHandle for the read pipe failed\n");
1403 /* Try bigger chunks */
1405 buffer
= HeapAlloc( GetProcessHeap(), 0, size
);
1406 for (i
= 0; i
< size
; i
++) buffer
[i
] = i
;
1407 ok(CreatePipe(&piperead
, &pipewrite
, &pipe_attr
, (size
+ 24)) != 0, "CreatePipe failed\n");
1408 ok(WriteFile(pipewrite
, buffer
, size
, &written
, NULL
), "Write to anonymous pipe failed\n");
1409 ok(written
== size
, "Write to anonymous pipe wrote %d bytes\n", written
);
1410 /* and close the write end, read should still succeed*/
1411 ok(CloseHandle(pipewrite
), "CloseHandle for the Write Pipe failed\n");
1412 memset( buffer
, 0, size
);
1413 ok(ReadFile(piperead
, buffer
, size
, &read
, NULL
), "Read from broken pipe with pending data failed\n");
1414 ok(read
== size
, "Read from anonymous pipe got %d bytes\n", read
);
1415 for (i
= 0; i
< size
; i
++) ok( buffer
[i
] == (BYTE
)i
, "invalid data %x at %x\n", buffer
[i
], i
);
1416 /* But now we need to get informed that the pipe is closed */
1417 ok(ReadFile(piperead
,readbuf
,sizeof(readbuf
),&read
, NULL
) == 0, "Broken pipe not detected\n");
1418 ok(CloseHandle(piperead
), "CloseHandle for the read pipe failed\n");
1419 HeapFree(GetProcessHeap(), 0, buffer
);
1421 ok(user_apc_ran
== FALSE
, "user apc ran, pipe using alertable io mode\n");
1422 SleepEx(0, TRUE
); /* get rid of apc */
1424 ok(CreatePipe(&piperead
, &pipewrite
, &pipe_attr
, 1) != 0, "CreatePipe failed\n");
1425 test_pipe_info(piperead
, FILE_PIPE_SERVER_END
, 1, 1, 1);
1426 test_pipe_info(pipewrite
, 0, 1, 1, 1);
1427 ok(CloseHandle(pipewrite
), "CloseHandle for the Write Pipe failed\n");
1428 ok(CloseHandle(piperead
), "CloseHandle for the read pipe failed\n");
1431 static void test_CloseHandle(void)
1433 static const char testdata
[] = "Hello World";
1434 DWORD state
, numbytes
;
1435 HANDLE hpipe
, hfile
;
1439 hpipe
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
,
1440 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
1441 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1442 ok(hpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed with %u\n", GetLastError());
1444 hfile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1445 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile failed with %u\n", GetLastError());
1447 numbytes
= 0xdeadbeef;
1448 ret
= WriteFile(hpipe
, testdata
, sizeof(testdata
), &numbytes
, NULL
);
1449 ok(ret
, "WriteFile failed with %u\n", GetLastError());
1450 ok(numbytes
== sizeof(testdata
), "expected sizeof(testdata), got %u\n", numbytes
);
1452 numbytes
= 0xdeadbeef;
1453 ret
= PeekNamedPipe(hfile
, NULL
, 0, NULL
, &numbytes
, NULL
);
1454 ok(ret
, "PeekNamedPipe failed with %u\n", GetLastError());
1455 ok(numbytes
== sizeof(testdata
), "expected sizeof(testdata), got %u\n", numbytes
);
1457 ret
= CloseHandle(hpipe
);
1458 ok(ret
, "CloseHandle failed with %u\n", GetLastError());
1460 numbytes
= 0xdeadbeef;
1461 memset(buffer
, 0, sizeof(buffer
));
1462 ret
= ReadFile(hfile
, buffer
, 0, &numbytes
, NULL
);
1463 ok(ret
, "ReadFile failed with %u\n", GetLastError());
1464 ok(numbytes
== 0, "expected 0, got %u\n", numbytes
);
1466 numbytes
= 0xdeadbeef;
1467 memset(buffer
, 0, sizeof(buffer
));
1468 ret
= ReadFile(hfile
, buffer
, sizeof(buffer
), &numbytes
, NULL
);
1469 ok(ret
, "ReadFile failed with %u\n", GetLastError());
1470 ok(numbytes
== sizeof(testdata
), "expected sizeof(testdata), got %u\n", numbytes
);
1472 ret
= GetNamedPipeHandleStateA(hfile
, &state
, NULL
, NULL
, NULL
, NULL
, 0);
1473 ok(ret
, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1474 state
= PIPE_READMODE_MESSAGE
| PIPE_WAIT
;
1475 ret
= SetNamedPipeHandleState(hfile
, &state
, NULL
, NULL
);
1476 ok(ret
, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1478 SetLastError(0xdeadbeef);
1479 ret
= ReadFile(hfile
, buffer
, 0, &numbytes
, NULL
);
1480 ok(!ret
, "ReadFile unexpectedly succeeded\n");
1481 ok(GetLastError() == ERROR_BROKEN_PIPE
, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1483 SetLastError(0xdeadbeef);
1484 ret
= WriteFile(hfile
, testdata
, sizeof(testdata
), &numbytes
, NULL
);
1485 ok(!ret
, "WriteFile unexpectedly succeeded\n");
1486 todo_wine
ok(GetLastError() == ERROR_NO_DATA
, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1490 hpipe
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
,
1491 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
1492 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1493 ok(hpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed with %u\n", GetLastError());
1495 hfile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1496 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile failed with %u\n", GetLastError());
1498 numbytes
= 0xdeadbeef;
1499 ret
= WriteFile(hpipe
, testdata
, 0, &numbytes
, NULL
);
1500 ok(ret
, "WriteFile failed with %u\n", GetLastError());
1501 ok(numbytes
== 0, "expected 0, got %u\n", numbytes
);
1503 ret
= CloseHandle(hpipe
);
1504 ok(ret
, "CloseHandle failed with %u\n", GetLastError());
1506 numbytes
= 0xdeadbeef;
1507 memset(buffer
, 0, sizeof(buffer
));
1508 ret
= ReadFile(hfile
, buffer
, sizeof(buffer
), &numbytes
, NULL
);
1509 ok(ret
, "ReadFile failed with %u\n", GetLastError());
1510 ok(numbytes
== 0, "expected 0, got %u\n", numbytes
);
1512 SetLastError(0xdeadbeef);
1513 ret
= ReadFile(hfile
, buffer
, 0, &numbytes
, NULL
);
1514 ok(!ret
, "ReadFile unexpectedly succeeded\n");
1515 ok(GetLastError() == ERROR_BROKEN_PIPE
, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1517 ret
= GetNamedPipeHandleStateA(hfile
, &state
, NULL
, NULL
, NULL
, NULL
, 0);
1518 ok(ret
, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1519 state
= PIPE_READMODE_MESSAGE
| PIPE_WAIT
;
1520 ret
= SetNamedPipeHandleState(hfile
, &state
, NULL
, NULL
);
1521 ok(ret
, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1523 SetLastError(0xdeadbeef);
1524 ret
= ReadFile(hfile
, buffer
, 0, &numbytes
, NULL
);
1525 ok(!ret
, "ReadFile unexpectedly succeeded\n");
1526 ok(GetLastError() == ERROR_BROKEN_PIPE
, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1528 SetLastError(0xdeadbeef);
1529 ret
= WriteFile(hfile
, testdata
, sizeof(testdata
), &numbytes
, NULL
);
1530 ok(!ret
, "WriteFile unexpectedly succeeded\n");
1531 todo_wine
ok(GetLastError() == ERROR_NO_DATA
, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1535 /* repeat test with hpipe <-> hfile swapped */
1537 hpipe
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
,
1538 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
1539 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1540 ok(hpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed with %u\n", GetLastError());
1542 hfile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1543 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile failed with %u\n", GetLastError());
1545 numbytes
= 0xdeadbeef;
1546 ret
= WriteFile(hfile
, testdata
, sizeof(testdata
), &numbytes
, NULL
);
1547 ok(ret
, "WriteFile failed with %u\n", GetLastError());
1548 ok(numbytes
== sizeof(testdata
), "expected sizeof(testdata), got %u\n", numbytes
);
1550 numbytes
= 0xdeadbeef;
1551 ret
= PeekNamedPipe(hpipe
, NULL
, 0, NULL
, &numbytes
, NULL
);
1552 ok(ret
, "PeekNamedPipe failed with %u\n", GetLastError());
1553 ok(numbytes
== sizeof(testdata
), "expected sizeof(testdata), got %u\n", numbytes
);
1555 ret
= CloseHandle(hfile
);
1556 ok(ret
, "CloseHandle failed with %u\n", GetLastError());
1558 numbytes
= 0xdeadbeef;
1559 memset(buffer
, 0, sizeof(buffer
));
1560 ret
= ReadFile(hpipe
, buffer
, 0, &numbytes
, NULL
);
1561 ok(ret
|| GetLastError() == ERROR_MORE_DATA
/* >= Win 8 */,
1562 "ReadFile failed with %u\n", GetLastError());
1563 ok(numbytes
== 0, "expected 0, got %u\n", numbytes
);
1565 numbytes
= 0xdeadbeef;
1566 memset(buffer
, 0, sizeof(buffer
));
1567 ret
= ReadFile(hpipe
, buffer
, sizeof(buffer
), &numbytes
, NULL
);
1568 ok(ret
, "ReadFile failed with %u\n", GetLastError());
1569 ok(numbytes
== sizeof(testdata
), "expected sizeof(testdata), got %u\n", numbytes
);
1571 ret
= GetNamedPipeHandleStateA(hpipe
, &state
, NULL
, NULL
, NULL
, NULL
, 0);
1572 ok(ret
, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1573 state
= PIPE_READMODE_MESSAGE
| PIPE_WAIT
;
1574 ret
= SetNamedPipeHandleState(hpipe
, &state
, NULL
, NULL
);
1575 ok(ret
, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1577 SetLastError(0xdeadbeef);
1578 ret
= ReadFile(hpipe
, buffer
, 0, &numbytes
, NULL
);
1579 ok(!ret
, "ReadFile unexpectedly succeeded\n");
1580 ok(GetLastError() == ERROR_BROKEN_PIPE
, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1582 SetLastError(0xdeadbeef);
1583 ret
= WriteFile(hpipe
, testdata
, sizeof(testdata
), &numbytes
, NULL
);
1584 ok(!ret
, "WriteFile unexpectedly succeeded\n");
1585 todo_wine
ok(GetLastError() == ERROR_NO_DATA
, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1589 hpipe
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
,
1590 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
1591 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1592 ok(hpipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed with %u\n", GetLastError());
1594 hfile
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1595 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile failed with %u\n", GetLastError());
1597 numbytes
= 0xdeadbeef;
1598 ret
= WriteFile(hfile
, testdata
, 0, &numbytes
, NULL
);
1599 ok(ret
, "WriteFile failed with %u\n", GetLastError());
1600 ok(numbytes
== 0, "expected 0, got %u\n", numbytes
);
1602 ret
= CloseHandle(hfile
);
1603 ok(ret
, "CloseHandle failed with %u\n", GetLastError());
1605 numbytes
= 0xdeadbeef;
1606 memset(buffer
, 0, sizeof(buffer
));
1607 ret
= ReadFile(hpipe
, buffer
, sizeof(buffer
), &numbytes
, NULL
);
1608 ok(ret
, "ReadFile failed with %u\n", GetLastError());
1609 ok(numbytes
== 0, "expected 0, got %u\n", numbytes
);
1611 SetLastError(0xdeadbeef);
1612 ret
= ReadFile(hpipe
, buffer
, 0, &numbytes
, NULL
);
1613 ok(!ret
, "ReadFile unexpectedly succeeded\n");
1614 ok(GetLastError() == ERROR_BROKEN_PIPE
, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1616 ret
= GetNamedPipeHandleStateA(hpipe
, &state
, NULL
, NULL
, NULL
, NULL
, 0);
1617 ok(ret
, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1618 state
= PIPE_READMODE_MESSAGE
| PIPE_WAIT
;
1619 ret
= SetNamedPipeHandleState(hpipe
, &state
, NULL
, NULL
);
1620 ok(ret
, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1622 SetLastError(0xdeadbeef);
1623 ret
= ReadFile(hpipe
, buffer
, 0, &numbytes
, NULL
);
1624 ok(!ret
, "ReadFile unexpectedly succeeded\n");
1625 ok(GetLastError() == ERROR_BROKEN_PIPE
, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1627 SetLastError(0xdeadbeef);
1628 ret
= WriteFile(hpipe
, testdata
, sizeof(testdata
), &numbytes
, NULL
);
1629 ok(!ret
, "WriteFile unexpectedly succeeded\n");
1630 todo_wine
ok(GetLastError() == ERROR_NO_DATA
, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1635 struct named_pipe_client_params
1637 DWORD security_flags
;
1642 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1644 static DWORD CALLBACK
named_pipe_client_func(LPVOID p
)
1646 struct named_pipe_client_params
*params
= p
;
1649 const char message
[] = "Test";
1650 DWORD bytes_read
, bytes_written
;
1652 TOKEN_PRIVILEGES
*Privileges
= NULL
;
1658 /* modify the token so we can tell if the pipe impersonation
1659 * token reverts to the process token */
1660 ret
= AdjustTokenPrivileges(params
->token
, TRUE
, NULL
, 0, NULL
, NULL
);
1661 ok(ret
, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1663 ret
= SetThreadToken(NULL
, params
->token
);
1664 ok(ret
, "SetThreadToken failed with error %d\n", GetLastError());
1669 HANDLE process_token
;
1671 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
|TOKEN_ADJUST_PRIVILEGES
, &process_token
);
1672 ok(ret
, "OpenProcessToken failed with error %d\n", GetLastError());
1674 ret
= GetTokenInformation(process_token
, TokenPrivileges
, NULL
, 0, &Size
);
1675 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1676 Privileges
= HeapAlloc(GetProcessHeap(), 0, Size
);
1677 ret
= GetTokenInformation(process_token
, TokenPrivileges
, Privileges
, Size
, &Size
);
1678 ok(ret
, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1680 ret
= AdjustTokenPrivileges(process_token
, TRUE
, NULL
, 0, NULL
, NULL
);
1681 ok(ret
, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1683 CloseHandle(process_token
);
1686 pipe
= CreateFileA(PIPE_NAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, params
->security_flags
, NULL
);
1687 ok(pipe
!= INVALID_HANDLE_VALUE
, "CreateFile for pipe failed with error %d\n", GetLastError());
1689 ret
= WriteFile(pipe
, message
, sizeof(message
), &bytes_written
, NULL
);
1690 ok(ret
, "WriteFile failed with error %d\n", GetLastError());
1692 ret
= ReadFile(pipe
, &dummy
, sizeof(dummy
), &bytes_read
, NULL
);
1693 ok(ret
, "ReadFile failed with error %d\n", GetLastError());
1699 ret
= RevertToSelf();
1700 ok(ret
, "RevertToSelf failed with error %d\n", GetLastError());
1704 ret
= AdjustTokenPrivileges(params
->token
, TRUE
, NULL
, 0, NULL
, NULL
);
1705 ok(ret
, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1710 HANDLE process_token
;
1712 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &process_token
);
1713 ok(ret
, "OpenProcessToken failed with error %d\n", GetLastError());
1715 ret
= AdjustTokenPrivileges(process_token
, FALSE
, Privileges
, 0, NULL
, NULL
);
1716 ok(ret
, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1718 HeapFree(GetProcessHeap(), 0, Privileges
);
1720 CloseHandle(process_token
);
1723 ret
= WriteFile(pipe
, message
, sizeof(message
), &bytes_written
, NULL
);
1724 ok(ret
, "WriteFile failed with error %d\n", GetLastError());
1726 ret
= ReadFile(pipe
, &dummy
, sizeof(dummy
), &bytes_read
, NULL
);
1727 ok(ret
, "ReadFile failed with error %d\n", GetLastError());
1734 static HANDLE
make_impersonation_token(DWORD Access
, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
1736 HANDLE ProcessToken
;
1737 HANDLE Token
= NULL
;
1740 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE
, &ProcessToken
);
1741 ok(ret
, "OpenProcessToken failed with error %d\n", GetLastError());
1743 ret
= pDuplicateTokenEx(ProcessToken
, Access
, NULL
, ImpersonationLevel
, TokenImpersonation
, &Token
);
1744 ok(ret
, "DuplicateToken failed with error %d\n", GetLastError());
1746 CloseHandle(ProcessToken
);
1751 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken
, DWORD security_flags
, BOOL revert
, void (*test_func
)(int, HANDLE
))
1760 struct named_pipe_client_params params
;
1762 DWORD dwBytesWritten
;
1763 HANDLE hToken
= NULL
;
1764 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
1767 hPipeServer
= CreateNamedPipeA(PIPE_NAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
| PIPE_READMODE_BYTE
| PIPE_WAIT
, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1768 ok(hPipeServer
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed with error %d\n", GetLastError());
1770 params
.security_flags
= security_flags
;
1771 params
.token
= hClientToken
;
1772 params
.revert
= revert
;
1773 hThread
= CreateThread(NULL
, 0, named_pipe_client_func
, ¶ms
, 0, &dwTid
);
1774 ok(hThread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
1776 SetLastError(0xdeadbeef);
1777 ret
= ImpersonateNamedPipeClient(hPipeServer
);
1778 error
= GetLastError();
1779 ok(ret
/* win2k3 */ || (error
== ERROR_CANNOT_IMPERSONATE
),
1780 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1782 ret
= ConnectNamedPipe(hPipeServer
, NULL
);
1783 ok(ret
|| (GetLastError() == ERROR_PIPE_CONNECTED
), "ConnectNamedPipe failed with error %d\n", GetLastError());
1785 ret
= ReadFile(hPipeServer
, buffer
, sizeof(buffer
), &dwBytesRead
, NULL
);
1786 ok(ret
, "ReadFile failed with error %d\n", GetLastError());
1788 ret
= ImpersonateNamedPipeClient(hPipeServer
);
1789 ok(ret
, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1791 ret
= OpenThreadToken(GetCurrentThread(), TOKEN_QUERY
, FALSE
, &hToken
);
1792 ok(ret
, "OpenThreadToken failed with error %d\n", GetLastError());
1794 (*test_func
)(0, hToken
);
1796 ImpersonationLevel
= 0xdeadbeef; /* to avoid false positives */
1797 ret
= GetTokenInformation(hToken
, TokenImpersonationLevel
, &ImpersonationLevel
, sizeof(ImpersonationLevel
), &size
);
1798 ok(ret
, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1799 ok(ImpersonationLevel
== SecurityImpersonation
, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation
, ImpersonationLevel
);
1801 CloseHandle(hToken
);
1805 ret
= WriteFile(hPipeServer
, &dummy
, sizeof(dummy
), &dwBytesWritten
, NULL
);
1806 ok(ret
, "WriteFile failed with error %d\n", GetLastError());
1808 ret
= ReadFile(hPipeServer
, buffer
, sizeof(buffer
), &dwBytesRead
, NULL
);
1809 ok(ret
, "ReadFile failed with error %d\n", GetLastError());
1811 ret
= ImpersonateNamedPipeClient(hPipeServer
);
1812 ok(ret
, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1814 ret
= OpenThreadToken(GetCurrentThread(), TOKEN_QUERY
, FALSE
, &hToken
);
1815 ok(ret
, "OpenThreadToken failed with error %d\n", GetLastError());
1817 (*test_func
)(1, hToken
);
1819 CloseHandle(hToken
);
1823 ret
= WriteFile(hPipeServer
, &dummy
, sizeof(dummy
), &dwBytesWritten
, NULL
);
1824 ok(ret
, "WriteFile failed with error %d\n", GetLastError());
1826 WaitForSingleObject(hThread
, INFINITE
);
1828 ret
= ImpersonateNamedPipeClient(hPipeServer
);
1829 ok(ret
, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1833 CloseHandle(hThread
);
1834 CloseHandle(hPipeServer
);
1837 static BOOL
are_all_privileges_disabled(HANDLE hToken
)
1840 TOKEN_PRIVILEGES
*Privileges
= NULL
;
1842 BOOL all_privs_disabled
= TRUE
;
1845 ret
= GetTokenInformation(hToken
, TokenPrivileges
, NULL
, 0, &Size
);
1846 if (!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
1848 Privileges
= HeapAlloc(GetProcessHeap(), 0, Size
);
1849 ret
= GetTokenInformation(hToken
, TokenPrivileges
, Privileges
, Size
, &Size
);
1852 HeapFree(GetProcessHeap(), 0, Privileges
);
1859 for (i
= 0; i
< Privileges
->PrivilegeCount
; i
++)
1861 if (Privileges
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
1863 all_privs_disabled
= FALSE
;
1868 HeapFree(GetProcessHeap(), 0, Privileges
);
1870 return all_privs_disabled
;
1873 static DWORD
get_privilege_count(HANDLE hToken
)
1875 TOKEN_STATISTICS Statistics
;
1876 DWORD Size
= sizeof(Statistics
);
1879 ret
= GetTokenInformation(hToken
, TokenStatistics
, &Statistics
, Size
, &Size
);
1880 ok(ret
, "GetTokenInformation(TokenStatistics)\n");
1881 if (!ret
) return -1;
1883 return Statistics
.PrivilegeCount
;
1886 static void test_no_sqos_no_token(int call_index
, HANDLE hToken
)
1893 priv_count
= get_privilege_count(hToken
);
1895 ok(priv_count
== 0, "privilege count should have been 0 instead of %d\n", priv_count
);
1898 priv_count
= get_privilege_count(hToken
);
1899 ok(priv_count
> 0, "privilege count should now be > 0 instead of 0\n");
1900 ok(!are_all_privileges_disabled(hToken
), "impersonated token should not have been modified\n");
1903 ok(0, "shouldn't happen\n");
1907 static void test_no_sqos(int call_index
, HANDLE hToken
)
1912 ok(!are_all_privileges_disabled(hToken
), "token should be a copy of the process one\n");
1916 ok(are_all_privileges_disabled(hToken
), "impersonated token should have been modified\n");
1919 ok(0, "shouldn't happen\n");
1923 static void test_static_context(int call_index
, HANDLE hToken
)
1928 ok(!are_all_privileges_disabled(hToken
), "token should be a copy of the process one\n");
1931 ok(!are_all_privileges_disabled(hToken
), "impersonated token should not have been modified\n");
1934 ok(0, "shouldn't happen\n");
1938 static void test_dynamic_context(int call_index
, HANDLE hToken
)
1943 ok(!are_all_privileges_disabled(hToken
), "token should be a copy of the process one\n");
1947 ok(are_all_privileges_disabled(hToken
), "impersonated token should have been modified\n");
1950 ok(0, "shouldn't happen\n");
1954 static void test_dynamic_context_no_token(int call_index
, HANDLE hToken
)
1959 ok(are_all_privileges_disabled(hToken
), "token should be a copy of the process one\n");
1962 ok(!are_all_privileges_disabled(hToken
), "process token modification should have been detected and impersonation token updated\n");
1965 ok(0, "shouldn't happen\n");
1969 static void test_no_sqos_revert(int call_index
, HANDLE hToken
)
1975 priv_count
= get_privilege_count(hToken
);
1977 ok(priv_count
== 0, "privilege count should have been 0 instead of %d\n", priv_count
);
1980 priv_count
= get_privilege_count(hToken
);
1981 ok(priv_count
> 0, "privilege count should now be > 0 instead of 0\n");
1982 ok(!are_all_privileges_disabled(hToken
), "impersonated token should not have been modified\n");
1985 ok(0, "shouldn't happen\n");
1989 static void test_static_context_revert(int call_index
, HANDLE hToken
)
1995 ok(are_all_privileges_disabled(hToken
), "privileges should have been disabled\n");
1999 ok(are_all_privileges_disabled(hToken
), "impersonated token should not have been modified\n");
2002 ok(0, "shouldn't happen\n");
2006 static void test_dynamic_context_revert(int call_index
, HANDLE hToken
)
2012 ok(are_all_privileges_disabled(hToken
), "privileges should have been disabled\n");
2015 ok(!are_all_privileges_disabled(hToken
), "impersonated token should now be process token\n");
2018 ok(0, "shouldn't happen\n");
2022 static void test_impersonation(void)
2024 HANDLE hClientToken
;
2025 HANDLE hProcessToken
;
2028 if( !pDuplicateTokenEx
) {
2029 skip("DuplicateTokenEx not found\n");
2033 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hProcessToken
);
2036 skip("couldn't open process token, skipping impersonation tests\n");
2040 if (!get_privilege_count(hProcessToken
) || are_all_privileges_disabled(hProcessToken
))
2042 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
2043 CloseHandle(hProcessToken
);
2046 CloseHandle(hProcessToken
);
2048 test_ImpersonateNamedPipeClient(NULL
, 0, FALSE
, test_no_sqos_no_token
);
2049 hClientToken
= make_impersonation_token(TOKEN_IMPERSONATE
| TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, SecurityImpersonation
);
2050 test_ImpersonateNamedPipeClient(hClientToken
, 0, FALSE
, test_no_sqos
);
2051 CloseHandle(hClientToken
);
2052 hClientToken
= make_impersonation_token(TOKEN_IMPERSONATE
| TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, SecurityImpersonation
);
2053 test_ImpersonateNamedPipeClient(hClientToken
,
2054 SECURITY_SQOS_PRESENT
| SECURITY_IMPERSONATION
, FALSE
,
2055 test_static_context
);
2056 CloseHandle(hClientToken
);
2057 hClientToken
= make_impersonation_token(TOKEN_IMPERSONATE
| TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, SecurityImpersonation
);
2058 test_ImpersonateNamedPipeClient(hClientToken
,
2059 SECURITY_SQOS_PRESENT
| SECURITY_CONTEXT_TRACKING
| SECURITY_IMPERSONATION
,
2060 FALSE
, test_dynamic_context
);
2061 CloseHandle(hClientToken
);
2062 test_ImpersonateNamedPipeClient(NULL
,
2063 SECURITY_SQOS_PRESENT
| SECURITY_CONTEXT_TRACKING
| SECURITY_IMPERSONATION
,
2064 FALSE
, test_dynamic_context_no_token
);
2066 hClientToken
= make_impersonation_token(TOKEN_IMPERSONATE
| TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, SecurityImpersonation
);
2067 test_ImpersonateNamedPipeClient(hClientToken
, 0, TRUE
, test_no_sqos_revert
);
2068 CloseHandle(hClientToken
);
2069 hClientToken
= make_impersonation_token(TOKEN_IMPERSONATE
| TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, SecurityImpersonation
);
2070 test_ImpersonateNamedPipeClient(hClientToken
,
2071 SECURITY_SQOS_PRESENT
| SECURITY_IMPERSONATION
, TRUE
,
2072 test_static_context_revert
);
2073 CloseHandle(hClientToken
);
2074 hClientToken
= make_impersonation_token(TOKEN_IMPERSONATE
| TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, SecurityImpersonation
);
2075 test_ImpersonateNamedPipeClient(hClientToken
,
2076 SECURITY_SQOS_PRESENT
| SECURITY_CONTEXT_TRACKING
| SECURITY_IMPERSONATION
,
2077 TRUE
, test_dynamic_context_revert
);
2078 CloseHandle(hClientToken
);
2081 struct overlapped_server_args
2083 HANDLE pipe_created
;
2086 static DWORD CALLBACK
overlapped_server(LPVOID arg
)
2091 struct overlapped_server_args
*a
= arg
;
2095 pipe
= CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 1, 0, 0, 100000, NULL
);
2096 ok(pipe
!= NULL
, "pipe NULL\n");
2098 ol
.hEvent
= CreateEventA(0, 1, 0, 0);
2099 ok(ol
.hEvent
!= NULL
, "event NULL\n");
2100 ret
= ConnectNamedPipe(pipe
, &ol
);
2101 err
= GetLastError();
2102 ok(ret
== 0, "ret %d\n", ret
);
2103 ok(err
== ERROR_IO_PENDING
, "gle %d\n", err
);
2104 SetEvent(a
->pipe_created
);
2106 ret
= WaitForSingleObjectEx(ol
.hEvent
, INFINITE
, 1);
2107 ok(ret
== WAIT_OBJECT_0
, "ret %x\n", ret
);
2109 ret
= GetOverlappedResult(pipe
, &ol
, &num
, 1);
2110 ok(ret
== 1, "ret %d\n", ret
);
2112 /* This should block */
2113 ret
= ReadFile(pipe
, buf
, sizeof(buf
), &num
, NULL
);
2114 ok(ret
== 1, "ret %d\n", ret
);
2116 DisconnectNamedPipe(pipe
);
2118 ret
= ConnectNamedPipe(pipe
, &ol
);
2119 err
= GetLastError();
2120 ok(ret
== 0, "ret %d\n", ret
);
2121 ok(err
== ERROR_IO_PENDING
, "gle %d\n", err
);
2123 ret
= WaitForSingleObjectEx(ol
.hEvent
, INFINITE
, 1);
2124 ok(ret
== WAIT_OBJECT_0
, "ret %x\n", ret
);
2126 ret
= GetOverlappedResult(pipe
, &ol
, &num
, 1);
2127 err
= GetLastError();
2128 ok(ret
== 0, "ret %d\n", ret
);
2129 ok(err
== ERROR_OPERATION_ABORTED
, "gle %d\n", err
);
2131 CloseHandle(ol
.hEvent
);
2136 static void test_overlapped(void)
2139 HANDLE thread
, pipe
;
2141 struct overlapped_server_args args
;
2143 args
.pipe_created
= CreateEventA(0, 1, 0, 0);
2144 thread
= CreateThread(NULL
, 0, overlapped_server
, &args
, 0, &tid
);
2146 WaitForSingleObject(args
.pipe_created
, INFINITE
);
2147 pipe
= CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2148 ok(pipe
!= INVALID_HANDLE_VALUE
, "cf failed\n");
2150 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
2153 ret
= WriteFile(pipe
, "x", 1, &num
, NULL
);
2154 ok(ret
, "WriteFile failed with error %d\n", GetLastError());
2156 WaitForSingleObject(thread
, INFINITE
);
2158 CloseHandle(args
.pipe_created
);
2159 CloseHandle(thread
);
2162 static void test_overlapped_error(void)
2164 HANDLE pipe
, file
, event
;
2165 DWORD err
, numbytes
;
2166 OVERLAPPED overlapped
;
2169 event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
2170 ok(event
!= NULL
, "CreateEventA failed with %u\n", GetLastError());
2172 pipe
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
2173 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
2174 1, 1024, 1024, NMPWAIT_WAIT_FOREVER
, NULL
);
2175 ok(pipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed with %u\n", GetLastError());
2177 memset(&overlapped
, 0, sizeof(overlapped
));
2178 overlapped
.hEvent
= event
;
2179 ret
= ConnectNamedPipe(pipe
, &overlapped
);
2180 err
= GetLastError();
2181 ok(ret
== FALSE
, "ConnectNamedPipe succeeded\n");
2182 ok(err
== ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %u\n", err
);
2184 file
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
2185 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
2186 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed with %u\n", GetLastError());
2188 numbytes
= 0xdeadbeef;
2189 ret
= GetOverlappedResult(pipe
, &overlapped
, &numbytes
, TRUE
);
2190 ok(ret
== TRUE
, "GetOverlappedResult failed\n");
2191 ok(numbytes
== 0, "expected 0, got %u\n", numbytes
);
2192 ok(overlapped
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", overlapped
.Internal
);
2197 pipe
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
2198 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
| PIPE_WAIT
,
2199 1, 1024, 1024, NMPWAIT_WAIT_FOREVER
, NULL
);
2200 ok(pipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed with %u\n", GetLastError());
2202 file
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
2203 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
2204 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed with %u\n", GetLastError());
2206 memset(&overlapped
, 0, sizeof(overlapped
));
2207 overlapped
.hEvent
= event
;
2208 ret
= ConnectNamedPipe(pipe
, &overlapped
);
2209 err
= GetLastError();
2210 ok(ret
== FALSE
, "ConnectNamedPipe succeeded\n");
2211 ok(err
== ERROR_PIPE_CONNECTED
, "expected ERROR_PIPE_CONNECTED, got %u\n", err
);
2212 ok(overlapped
.Internal
== STATUS_PENDING
, "expected STATUS_PENDING, got %08lx\n", overlapped
.Internal
);
2220 static void test_NamedPipeHandleState(void)
2222 HANDLE server
, client
;
2224 DWORD state
, instances
, maxCollectionCount
, collectDataTimeout
;
2225 char userName
[MAX_PATH
];
2227 server
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
,
2228 /* dwOpenMode */ PIPE_TYPE_BYTE
| PIPE_WAIT
,
2229 /* nMaxInstances */ 1,
2230 /* nOutBufSize */ 1024,
2231 /* nInBufSize */ 1024,
2232 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
2233 /* lpSecurityAttrib */ NULL
);
2234 ok(server
!= INVALID_HANDLE_VALUE
, "cf failed\n");
2235 ret
= GetNamedPipeHandleStateA(server
, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
2236 ok(ret
, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2237 ret
= GetNamedPipeHandleStateA(server
, &state
, &instances
, NULL
, NULL
, NULL
,
2239 ok(ret
, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2242 ok(state
== 0, "unexpected state %08x\n", state
);
2243 ok(instances
== 1, "expected 1 instances, got %d\n", instances
);
2245 /* Some parameters have no meaning, and therefore can't be retrieved,
2248 SetLastError(0xdeadbeef);
2249 ret
= GetNamedPipeHandleStateA(server
, &state
, &instances
,
2250 &maxCollectionCount
, &collectDataTimeout
, userName
,
2251 sizeof(userName
) / sizeof(userName
[0]));
2253 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2254 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2255 /* A byte-mode pipe server can't be changed to message mode. */
2256 state
= PIPE_READMODE_MESSAGE
;
2257 SetLastError(0xdeadbeef);
2258 ret
= SetNamedPipeHandleState(server
, &state
, NULL
, NULL
);
2259 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2260 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2262 client
= CreateFileA(PIPENAME
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
2263 OPEN_EXISTING
, 0, NULL
);
2264 ok(client
!= INVALID_HANDLE_VALUE
, "cf failed\n");
2266 state
= PIPE_READMODE_BYTE
;
2267 ret
= SetNamedPipeHandleState(client
, &state
, NULL
, NULL
);
2268 ok(ret
, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2269 /* A byte-mode pipe client can't be changed to message mode, either. */
2270 state
= PIPE_READMODE_MESSAGE
;
2271 SetLastError(0xdeadbeef);
2272 ret
= SetNamedPipeHandleState(server
, &state
, NULL
, NULL
);
2273 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2274 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2276 CloseHandle(client
);
2277 CloseHandle(server
);
2279 server
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
,
2280 /* dwOpenMode */ PIPE_TYPE_MESSAGE
| PIPE_WAIT
,
2281 /* nMaxInstances */ 1,
2282 /* nOutBufSize */ 1024,
2283 /* nInBufSize */ 1024,
2284 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
2285 /* lpSecurityAttrib */ NULL
);
2286 ok(server
!= INVALID_HANDLE_VALUE
, "cf failed\n");
2287 ret
= GetNamedPipeHandleStateA(server
, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
2288 ok(ret
, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2289 ret
= GetNamedPipeHandleStateA(server
, &state
, &instances
, NULL
, NULL
, NULL
,
2291 ok(ret
, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2294 ok(state
== 0, "unexpected state %08x\n", state
);
2295 ok(instances
== 1, "expected 1 instances, got %d\n", instances
);
2297 /* In contrast to byte-mode pipes, a message-mode pipe server can be
2298 * changed to byte mode.
2300 state
= PIPE_READMODE_BYTE
;
2301 ret
= SetNamedPipeHandleState(server
, &state
, NULL
, NULL
);
2302 ok(ret
, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2304 client
= CreateFileA(PIPENAME
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
2305 OPEN_EXISTING
, 0, NULL
);
2306 ok(client
!= INVALID_HANDLE_VALUE
, "cf failed\n");
2308 state
= PIPE_READMODE_MESSAGE
;
2309 ret
= SetNamedPipeHandleState(client
, &state
, NULL
, NULL
);
2310 ok(ret
, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2311 /* A message-mode pipe client can also be changed to byte mode.
2313 state
= PIPE_READMODE_BYTE
;
2314 ret
= SetNamedPipeHandleState(client
, &state
, NULL
, NULL
);
2315 ok(ret
, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2317 CloseHandle(client
);
2318 CloseHandle(server
);
2321 static void test_GetNamedPipeInfo(void)
2325 server
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
,
2326 /* dwOpenMode */ PIPE_TYPE_BYTE
| PIPE_WAIT
,
2327 /* nMaxInstances */ 1,
2328 /* nOutBufSize */ 1024,
2329 /* nInBufSize */ 1024,
2330 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
2331 /* lpSecurityAttrib */ NULL
);
2332 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
2334 test_pipe_info(server
, PIPE_SERVER_END
| PIPE_TYPE_BYTE
, 1024, 1024, 1);
2336 CloseHandle(server
);
2338 server
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
,
2339 /* dwOpenMode */ PIPE_TYPE_MESSAGE
| PIPE_NOWAIT
,
2340 /* nMaxInstances */ 3,
2341 /* nOutBufSize */ 1024,
2342 /* nInBufSize */ 1024,
2343 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
2344 /* lpSecurityAttrib */ NULL
);
2345 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
2347 test_pipe_info(server
, PIPE_SERVER_END
| PIPE_TYPE_MESSAGE
, 1024, 1024, 3);
2349 CloseHandle(server
);
2351 server
= CreateNamedPipeA(PIPENAME
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
2352 /* dwOpenMode */ PIPE_TYPE_MESSAGE
| PIPE_WAIT
,
2353 /* nMaxInstances */ 1,
2354 /* nOutBufSize */ 0,
2356 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
2357 /* lpSecurityAttrib */ NULL
);
2358 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
2360 test_pipe_info(server
, PIPE_SERVER_END
| PIPE_TYPE_MESSAGE
, 0, 0, 1);
2362 CloseHandle(server
);
2364 server
= CreateNamedPipeA(PIPENAME
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
2365 /* dwOpenMode */ PIPE_TYPE_MESSAGE
| PIPE_WAIT
,
2366 /* nMaxInstances */ 1,
2367 /* nOutBufSize */ 0xf000,
2368 /* nInBufSize */ 0xf000,
2369 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
2370 /* lpSecurityAttrib */ NULL
);
2371 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
2373 test_pipe_info(server
, PIPE_SERVER_END
| PIPE_TYPE_MESSAGE
, 0xf000, 0xf000, 1);
2375 CloseHandle(server
);
2378 static void test_readfileex_pending(void)
2380 HANDLE server
, client
, event
;
2382 DWORD err
, wait
, num_bytes
;
2383 OVERLAPPED overlapped
;
2384 char read_buf
[1024];
2385 char write_buf
[1024];
2386 const char test_string
[] = "test";
2389 server
= CreateNamedPipeA(PIPENAME
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
2390 /* dwOpenMode */ PIPE_TYPE_BYTE
| PIPE_WAIT
,
2391 /* nMaxInstances */ 1,
2392 /* nOutBufSize */ 1024,
2393 /* nInBufSize */ 1024,
2394 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT
,
2395 /* lpSecurityAttrib */ NULL
);
2396 ok(server
!= INVALID_HANDLE_VALUE
, "cf failed\n");
2398 event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
2399 ok(event
!= NULL
, "CreateEventA failed\n");
2401 memset(&overlapped
, 0, sizeof(overlapped
));
2402 overlapped
.hEvent
= event
;
2404 ret
= ConnectNamedPipe(server
, &overlapped
);
2405 err
= GetLastError();
2406 ok(ret
== FALSE
, "ConnectNamedPipe succeeded\n");
2407 ok(err
== ERROR_IO_PENDING
, "ConnectNamedPipe set error %i\n", err
);
2409 wait
= WaitForSingleObject(event
, 0);
2410 ok(wait
== WAIT_TIMEOUT
, "WaitForSingleObject returned %x\n", wait
);
2412 client
= CreateFileA(PIPENAME
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
2413 OPEN_EXISTING
, 0, NULL
);
2414 ok(client
!= INVALID_HANDLE_VALUE
, "cf failed\n");
2416 wait
= WaitForSingleObject(event
, 0);
2417 ok(wait
== WAIT_OBJECT_0
, "WaitForSingleObject returned %x\n", wait
);
2419 /* Start a read that can't complete immediately. */
2420 completion_called
= 0;
2422 ret
= ReadFileEx(server
, read_buf
, sizeof(read_buf
), &overlapped
, completion_routine
);
2423 ok(ret
== TRUE
, "ReadFileEx failed, err=%i\n", GetLastError());
2424 ok(completion_called
== 0, "completion routine called before ReadFileEx returned\n");
2426 ret
= WriteFile(client
, test_string
, strlen(test_string
), &num_bytes
, NULL
);
2427 ok(ret
== TRUE
, "WriteFile failed\n");
2428 ok(num_bytes
== strlen(test_string
), "only %i bytes written\n", num_bytes
);
2430 ok(completion_called
== 0, "completion routine called during WriteFile\n");
2432 wait
= WaitForSingleObjectEx(event
, 0, TRUE
);
2433 ok(wait
== WAIT_IO_COMPLETION
|| wait
== WAIT_OBJECT_0
, "WaitForSingleObjectEx returned %x\n", wait
);
2435 ok(completion_called
== 1, "completion not called after writing pipe\n");
2436 ok(completion_errorcode
== 0, "completion called with error %x\n", completion_errorcode
);
2437 ok(completion_num_bytes
== strlen(test_string
), "ReadFileEx returned only %d bytes\n", completion_num_bytes
);
2438 ok(completion_lpoverlapped
== &overlapped
, "completion called with wrong overlapped pointer\n");
2439 ok(!memcmp(test_string
, read_buf
, strlen(test_string
)), "ReadFileEx read wrong bytes\n");
2441 /* Make writes until the pipe is full and the write fails */
2442 memset(write_buf
, 0xaa, sizeof(write_buf
));
2443 for (i
=0; i
<256; i
++)
2445 completion_called
= 0;
2447 ret
= WriteFileEx(server
, write_buf
, sizeof(write_buf
), &overlapped
, completion_routine
);
2448 err
= GetLastError();
2450 ok(completion_called
== 0, "completion routine called during WriteFileEx\n");
2452 wait
= WaitForSingleObjectEx(event
, 0, TRUE
);
2454 if (wait
== WAIT_TIMEOUT
)
2455 /* write couldn't complete immediately, presumably the pipe is full */
2458 ok(wait
== WAIT_IO_COMPLETION
|| wait
== WAIT_OBJECT_0
, "WaitForSingleObject returned %x\n", wait
);
2460 ok(ret
== TRUE
, "WriteFileEx failed, err=%i\n", err
);
2461 ok(completion_errorcode
== 0, "completion called with error %x\n", completion_errorcode
);
2462 ok(completion_lpoverlapped
== &overlapped
, "completion called with wrong overlapped pointer\n");
2465 ok(ret
== TRUE
, "WriteFileEx failed, err=%i\n", err
);
2466 ok(completion_called
== 0, "completion routine called but wait timed out\n");
2467 ok(completion_errorcode
== 0, "completion called with error %x\n", completion_errorcode
);
2468 ok(completion_lpoverlapped
== &overlapped
, "completion called with wrong overlapped pointer\n");
2470 /* free up some space in the pipe */
2471 for (i
=0; i
<256; i
++)
2473 ret
= ReadFile(client
, read_buf
, sizeof(read_buf
), &num_bytes
, NULL
);
2474 ok(ret
== TRUE
, "ReadFile failed\n");
2476 ok(completion_called
== 0, "completion routine called during ReadFile\n");
2478 wait
= WaitForSingleObjectEx(event
, 0, TRUE
);
2479 ok(wait
== WAIT_IO_COMPLETION
|| wait
== WAIT_OBJECT_0
|| wait
== WAIT_TIMEOUT
,
2480 "WaitForSingleObject returned %x\n", wait
);
2481 if (wait
!= WAIT_TIMEOUT
) break;
2484 ok(completion_called
== 1, "completion routine not called\n");
2485 ok(completion_errorcode
== 0, "completion called with error %x\n", completion_errorcode
);
2486 ok(completion_lpoverlapped
== &overlapped
, "completion called with wrong overlapped pointer\n");
2488 num_bytes
= 0xdeadbeef;
2489 SetLastError(0xdeadbeef);
2490 ret
= ReadFile(INVALID_HANDLE_VALUE
, read_buf
, 0, &num_bytes
, NULL
);
2491 ok(!ret
, "ReadFile should fail\n");
2492 ok(GetLastError() == ERROR_INVALID_HANDLE
, "wrong error %u\n", GetLastError());
2493 ok(num_bytes
== 0, "expected 0, got %u\n", num_bytes
);
2495 S(U(overlapped
)).Offset
= 0;
2496 S(U(overlapped
)).OffsetHigh
= 0;
2497 overlapped
.Internal
= -1;
2498 overlapped
.InternalHigh
= -1;
2499 overlapped
.hEvent
= event
;
2500 num_bytes
= 0xdeadbeef;
2501 SetLastError(0xdeadbeef);
2502 ret
= ReadFile(server
, read_buf
, 0, &num_bytes
, &overlapped
);
2503 ok(!ret
, "ReadFile should fail\n");
2505 ok(GetLastError() == ERROR_IO_PENDING
, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2506 ok(num_bytes
== 0, "bytes %u\n", num_bytes
);
2507 ok((NTSTATUS
)overlapped
.Internal
== STATUS_PENDING
, "expected STATUS_PENDING, got %#lx\n", overlapped
.Internal
);
2509 ok(overlapped
.InternalHigh
== -1, "expected -1, got %lu\n", overlapped
.InternalHigh
);
2511 wait
= WaitForSingleObject(event
, 100);
2512 ok(wait
== WAIT_TIMEOUT
, "WaitForSingleObject returned %x\n", wait
);
2514 num_bytes
= 0xdeadbeef;
2515 ret
= WriteFile(client
, test_string
, 1, &num_bytes
, NULL
);
2516 ok(ret
, "WriteFile failed\n");
2517 ok(num_bytes
== 1, "bytes %u\n", num_bytes
);
2519 wait
= WaitForSingleObject(event
, 100);
2521 ok(wait
== WAIT_OBJECT_0
, "WaitForSingleObject returned %x\n", wait
);
2523 ok(num_bytes
== 1, "bytes %u\n", num_bytes
);
2525 ok((NTSTATUS
)overlapped
.Internal
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %#lx\n", overlapped
.Internal
);
2526 ok(overlapped
.InternalHigh
== 0, "expected 0, got %lu\n", overlapped
.InternalHigh
);
2528 /* read the pending byte and clear the pipe */
2529 num_bytes
= 0xdeadbeef;
2530 ret
= ReadFile(server
, read_buf
, 1, &num_bytes
, &overlapped
);
2531 ok(ret
, "ReadFile failed\n");
2532 ok(num_bytes
== 1, "bytes %u\n", num_bytes
);
2534 CloseHandle(client
);
2535 CloseHandle(server
);
2539 #define test_peek_pipe(a,b,c,d) _test_peek_pipe(__LINE__,a,b,c,d)
2540 static void _test_peek_pipe(unsigned line
, HANDLE pipe
, DWORD expected_read
, DWORD expected_avail
, DWORD expected_message_length
)
2542 DWORD bytes_read
= 0xdeadbeed, avail
= 0xdeadbeef, left
= 0xdeadbeed;
2544 FILE_PIPE_PEEK_BUFFER
*peek_buf
= (void*)buf
;
2549 r
= PeekNamedPipe(pipe
, buf
, sizeof(buf
), &bytes_read
, &avail
, &left
);
2550 ok_(__FILE__
,line
)(r
, "PeekNamedPipe failed: %u\n", GetLastError());
2551 ok_(__FILE__
,line
)(bytes_read
== expected_read
, "bytes_read = %u, expected %u\n", bytes_read
, expected_read
);
2552 ok_(__FILE__
,line
)(avail
== expected_avail
, "avail = %u, expected %u\n", avail
, expected_avail
);
2553 ok_(__FILE__
,line
)(left
== expected_message_length
- expected_read
, "left = %d, expected %d\n",
2554 left
, expected_message_length
- expected_read
);
2556 status
= NtFsControlFile(pipe
, 0, NULL
, NULL
, &io
, FSCTL_PIPE_PEEK
, NULL
, 0, buf
, sizeof(buf
));
2557 ok_(__FILE__
,line
)(!status
|| status
== STATUS_PENDING
, "NtFsControlFile(FSCTL_PIPE_PEEK) failed: %x\n", status
);
2558 ok_(__FILE__
,line
)(io
.Information
== FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[expected_read
]),
2559 "io.Information = %lu\n", io
.Information
);
2560 ok_(__FILE__
,line
)(peek_buf
->ReadDataAvailable
== expected_avail
, "ReadDataAvailable = %u, expected %u\n",
2561 peek_buf
->ReadDataAvailable
, expected_avail
);
2562 ok_(__FILE__
,line
)(peek_buf
->MessageLength
== expected_message_length
, "MessageLength = %u, expected %u\n",
2563 peek_buf
->MessageLength
, expected_message_length
);
2567 r
= PeekNamedPipe(pipe
, buf
, 1, &bytes_read
, &avail
, &left
);
2568 ok_(__FILE__
,line
)(r
, "PeekNamedPipe failed: %u\n", GetLastError());
2569 ok_(__FILE__
,line
)(bytes_read
== 1, "bytes_read = %u, expected %u\n", bytes_read
, expected_read
);
2570 ok_(__FILE__
,line
)(avail
== expected_avail
, "avail = %u, expected %u\n", avail
, expected_avail
);
2571 ok_(__FILE__
,line
)(left
== expected_message_length
-1, "left = %d, expected %d\n", left
, expected_message_length
-1);
2575 #define overlapped_read_sync(a,b,c,d,e) _overlapped_read_sync(__LINE__,a,b,c,d,e)
2576 static void _overlapped_read_sync(unsigned line
, HANDLE reader
, void *buf
, DWORD buf_size
, DWORD expected_result
, BOOL partial_read
)
2578 DWORD read_bytes
= 0xdeadbeef;
2579 OVERLAPPED overlapped
;
2582 memset(&overlapped
, 0, sizeof(overlapped
));
2583 overlapped
.hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2584 res
= ReadFile(reader
, buf
, buf_size
, &read_bytes
, &overlapped
);
2586 ok_(__FILE__
,line
)(!res
&& GetLastError() == ERROR_MORE_DATA
, "ReadFile returned: %x (%u)\n", res
, GetLastError());
2588 ok_(__FILE__
,line
)(res
, "ReadFile failed: %u\n", GetLastError());
2590 todo_wine
ok_(__FILE__
,line
)(!read_bytes
, "read_bytes %u expected 0\n", read_bytes
);
2592 ok_(__FILE__
,line
)(read_bytes
== expected_result
, "read_bytes %u expected %u\n", read_bytes
, expected_result
);
2594 read_bytes
= 0xdeadbeef;
2595 res
= GetOverlappedResult(reader
, &overlapped
, &read_bytes
, FALSE
);
2597 ok_(__FILE__
,line
)(!res
&& GetLastError() == ERROR_MORE_DATA
,
2598 "GetOverlappedResult returned: %x (%u)\n", res
, GetLastError());
2600 ok_(__FILE__
,line
)(res
, "GetOverlappedResult failed: %u\n", GetLastError());
2601 ok_(__FILE__
,line
)(read_bytes
== expected_result
, "read_bytes %u expected %u\n", read_bytes
, expected_result
);
2602 CloseHandle(overlapped
.hEvent
);
2605 #define overlapped_read_async(a,b,c,d) _overlapped_read_async(__LINE__,a,b,c,d)
2606 static void _overlapped_read_async(unsigned line
, HANDLE reader
, void *buf
, DWORD buf_size
, OVERLAPPED
*overlapped
)
2608 DWORD read_bytes
= 0xdeadbeef;
2611 memset(overlapped
, 0, sizeof(*overlapped
));
2612 overlapped
->hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2613 res
= ReadFile(reader
, buf
, buf_size
, &read_bytes
, overlapped
);
2614 ok_(__FILE__
,line
)(!res
&& GetLastError() == ERROR_IO_PENDING
, "ReadFile returned %x(%u)\n", res
, GetLastError());
2615 ok_(__FILE__
,line
)(!read_bytes
, "read_bytes %u expected 0\n", read_bytes
);
2617 _test_not_signaled(line
, overlapped
->hEvent
);
2620 #define overlapped_write_sync(a,b,c) _overlapped_write_sync(__LINE__,a,b,c)
2621 static void _overlapped_write_sync(unsigned line
, HANDLE writer
, void *buf
, DWORD size
)
2623 DWORD written_bytes
= 0xdeadbeef;
2624 OVERLAPPED overlapped
;
2627 memset(&overlapped
, 0, sizeof(overlapped
));
2628 overlapped
.hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2629 res
= WriteFile(writer
, buf
, size
, &written_bytes
, &overlapped
);
2630 ok_(__FILE__
,line
)(res
, "WriteFile returned %x(%u)\n", res
, GetLastError());
2631 ok_(__FILE__
,line
)(written_bytes
== size
, "WriteFile returned written_bytes = %u\n", written_bytes
);
2633 written_bytes
= 0xdeadbeef;
2634 res
= GetOverlappedResult(writer
, &overlapped
, &written_bytes
, FALSE
);
2635 ok_(__FILE__
,line
)(res
, "GetOverlappedResult failed: %u\n", GetLastError());
2636 ok_(__FILE__
,line
)(written_bytes
== size
, "GetOverlappedResult returned written_bytes %u expected %u\n", written_bytes
, size
);
2638 CloseHandle(overlapped
.hEvent
);
2641 #define overlapped_write_async(a,b,c,d) _overlapped_write_async(__LINE__,a,b,c,d)
2642 static void _overlapped_write_async(unsigned line
, HANDLE writer
, void *buf
, DWORD size
, OVERLAPPED
*overlapped
)
2644 DWORD written_bytes
= 0xdeadbeef;
2647 memset(overlapped
, 0, sizeof(*overlapped
));
2648 overlapped
->hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2649 res
= WriteFile(writer
, buf
, size
, &written_bytes
, overlapped
);
2650 ok_(__FILE__
,line
)(!res
&& GetLastError() == ERROR_IO_PENDING
, "WriteFile returned %x(%u)\n", res
, GetLastError());
2651 todo_wine
ok_(__FILE__
,line
)(!written_bytes
, "written_bytes = %u\n", written_bytes
);
2653 _test_not_signaled(line
, overlapped
->hEvent
);
2656 #define test_flush_sync(a) _test_flush_sync(__LINE__,a)
2657 static void _test_flush_sync(unsigned line
, HANDLE pipe
)
2661 res
= FlushFileBuffers(pipe
);
2662 ok_(__FILE__
,line
)(res
, "FlushFileBuffers failed: %u\n", GetLastError());
2665 static DWORD expected_flush_error
;
2667 static DWORD CALLBACK
flush_proc(HANDLE pipe
)
2671 res
= FlushFileBuffers(pipe
);
2672 if (expected_flush_error
== ERROR_SUCCESS
)
2673 ok(res
, "FlushFileBuffers failed: %u\n", GetLastError());
2675 todo_wine
ok(!res
&& GetLastError() == expected_flush_error
, "FlushFileBuffers failed: %u\n", GetLastError());
2679 #define test_flush_async(a,b) _test_flush_async(__LINE__,a,b)
2680 static HANDLE
_test_flush_async(unsigned line
, HANDLE pipe
, DWORD error
)
2685 expected_flush_error
= error
;
2686 thread
= CreateThread(NULL
, 0, flush_proc
, pipe
, 0, &tid
);
2687 ok_(__FILE__
,line
)(thread
!= NULL
, "CreateThread failed: %u\n", GetLastError());
2690 _test_not_signaled(line
, thread
);
2694 #define test_flush_done(a) _test_flush_done(__LINE__,a)
2695 static void _test_flush_done(unsigned line
, HANDLE thread
)
2697 DWORD res
= WaitForSingleObject(thread
, 1000);
2698 ok_(__FILE__
,line
)(res
== WAIT_OBJECT_0
, "WaitForSingleObject returned %u (%u)\n", res
, GetLastError());
2699 CloseHandle(thread
);
2702 #define test_overlapped_result(a,b,c,d) _test_overlapped_result(__LINE__,a,b,c,d)
2703 static void _test_overlapped_result(unsigned line
, HANDLE handle
, OVERLAPPED
*overlapped
, DWORD expected_result
, BOOL partial_read
)
2705 DWORD result
= 0xdeadbeef;
2708 _test_signaled(line
, overlapped
->hEvent
);
2710 res
= GetOverlappedResult(handle
, overlapped
, &result
, FALSE
);
2712 ok_(__FILE__
,line
)(!res
&& GetLastError() == ERROR_MORE_DATA
, "GetOverlappedResult returned: %x (%u)\n", res
, GetLastError());
2714 ok_(__FILE__
,line
)(res
, "GetOverlappedResult failed: %u\n", GetLastError());
2715 ok_(__FILE__
,line
)(result
== expected_result
, "read_bytes = %u, expected %u\n", result
, expected_result
);
2716 CloseHandle(overlapped
->hEvent
);
2719 #define test_overlapped_failure(a,b,c) _test_overlapped_failure(__LINE__,a,b,c)
2720 static void _test_overlapped_failure(unsigned line
, HANDLE handle
, OVERLAPPED
*overlapped
, DWORD error
)
2725 _test_signaled(line
, overlapped
->hEvent
);
2727 res
= GetOverlappedResult(handle
, overlapped
, &result
, FALSE
);
2728 ok_(__FILE__
,line
)(!res
&& GetLastError() == error
, "GetOverlappedResult returned: %x (%u), expected error %u\n",
2729 res
, GetLastError(), error
);
2730 ok_(__FILE__
,line
)(!result
, "result = %u\n", result
);
2731 CloseHandle(overlapped
->hEvent
);
2734 #define cancel_overlapped(a,b) _cancel_overlapped(__LINE__,a,b)
2735 static void _cancel_overlapped(unsigned line
, HANDLE handle
, OVERLAPPED
*overlapped
)
2739 res
= pCancelIoEx(handle
, overlapped
);
2740 ok_(__FILE__
,line
)(res
, "CancelIoEx failed: %u\n", GetLastError());
2742 _test_overlapped_failure(line
, handle
, overlapped
, ERROR_OPERATION_ABORTED
);
2745 static void test_blocking_rw(HANDLE writer
, HANDLE reader
, DWORD buf_size
, BOOL msg_mode
, BOOL msg_read
)
2747 OVERLAPPED read_overlapped
, read_overlapped2
, write_overlapped
, write_overlapped2
;
2748 char buf
[10000], read_buf
[10000];
2749 HANDLE flush_thread
;
2751 memset(buf
, 0xaa, sizeof(buf
));
2753 /* test pending read with overlapped event */
2754 overlapped_read_async(reader
, read_buf
, 1000, &read_overlapped
);
2755 test_flush_sync(writer
);
2756 test_peek_pipe(reader
, 0, 0, 0);
2758 /* write more data than needed for read */
2759 overlapped_write_sync(writer
, buf
, 4000);
2760 test_overlapped_result(reader
, &read_overlapped
, 1000, msg_read
);
2762 /* test pending write with overlapped event */
2763 overlapped_write_async(writer
, buf
, buf_size
, &write_overlapped
);
2765 /* write one more byte */
2766 overlapped_write_async(writer
, buf
, 1, &write_overlapped2
);
2767 flush_thread
= test_flush_async(writer
, ERROR_SUCCESS
);
2768 test_not_signaled(write_overlapped
.hEvent
);
2770 /* empty write will not block */
2771 overlapped_write_sync(writer
, buf
, 0);
2772 test_not_signaled(write_overlapped
.hEvent
);
2773 test_not_signaled(write_overlapped2
.hEvent
);
2775 /* read remaining data from the first write */
2776 overlapped_read_sync(reader
, read_buf
, 3000, 3000, FALSE
);
2777 test_overlapped_result(writer
, &write_overlapped
, buf_size
, FALSE
);
2778 test_not_signaled(write_overlapped2
.hEvent
);
2779 test_not_signaled(flush_thread
);
2781 /* read one byte so that the next write fits the buffer */
2782 overlapped_read_sync(reader
, read_buf
, 1, 1, msg_read
);
2783 test_overlapped_result(writer
, &write_overlapped2
, 1, FALSE
);
2785 /* read the whole buffer */
2786 overlapped_read_sync(reader
, read_buf
, buf_size
, buf_size
-msg_read
, FALSE
);
2789 overlapped_read_sync(reader
, read_buf
, 1000, 1, FALSE
);
2792 /* we still have an empty message in queue */
2793 overlapped_read_sync(reader
, read_buf
, 1000, 0, FALSE
);
2795 test_flush_done(flush_thread
);
2797 /* pipe is empty, the next read will block */
2798 overlapped_read_async(reader
, read_buf
, 0, &read_overlapped
);
2799 overlapped_read_async(reader
, read_buf
, 1000, &read_overlapped2
);
2801 /* write one byte */
2802 overlapped_write_sync(writer
, buf
, 1);
2803 test_overlapped_result(reader
, &read_overlapped
, 0, msg_read
);
2804 test_overlapped_result(reader
, &read_overlapped2
, 1, FALSE
);
2806 /* write a message larger than buffer */
2807 overlapped_write_async(writer
, buf
, buf_size
+2000, &write_overlapped
);
2809 /* read so that pending write is still larger than the buffer */
2810 overlapped_read_sync(reader
, read_buf
, 1999, 1999, msg_read
);
2811 test_not_signaled(write_overlapped
.hEvent
);
2813 /* read one more byte */
2814 overlapped_read_sync(reader
, read_buf
, 1, 1, msg_read
);
2815 test_overlapped_result(writer
, &write_overlapped
, buf_size
+2000, FALSE
);
2817 /* read remaining data */
2818 overlapped_read_sync(reader
, read_buf
, buf_size
+1, buf_size
, FALSE
);
2820 /* simple pass of empty message */
2821 overlapped_write_sync(writer
, buf
, 0);
2823 overlapped_read_sync(reader
, read_buf
, 1, 0, FALSE
);
2825 /* pipe is empty, the next read will block */
2826 test_flush_sync(writer
);
2827 overlapped_read_async(reader
, read_buf
, 0, &read_overlapped
);
2828 overlapped_read_async(reader
, read_buf
, 1, &read_overlapped2
);
2830 /* 0 length write wakes one read in msg mode */
2831 overlapped_write_sync(writer
, buf
, 0);
2833 test_overlapped_result(reader
, &read_overlapped
, 0, FALSE
);
2835 test_not_signaled(read_overlapped
.hEvent
);
2836 test_not_signaled(read_overlapped2
.hEvent
);
2837 overlapped_write_sync(writer
, buf
, 1);
2838 test_overlapped_result(reader
, &read_overlapped2
, 1, FALSE
);
2840 overlapped_write_sync(writer
, buf
, 20);
2841 test_peek_pipe(reader
, 20, 20, msg_mode
? 20 : 0);
2842 overlapped_write_sync(writer
, buf
, 15);
2843 test_peek_pipe(reader
, msg_mode
? 20 : 35, 35, msg_mode
? 20 : 0);
2844 overlapped_read_sync(reader
, read_buf
, 10, 10, msg_read
);
2845 test_peek_pipe(reader
, msg_mode
? 10 : 25, 25, msg_mode
? 10 : 0);
2846 overlapped_read_sync(reader
, read_buf
, 10, 10, FALSE
);
2847 test_peek_pipe(reader
, 15, 15, msg_mode
? 15 : 0);
2848 overlapped_read_sync(reader
, read_buf
, 15, 15, FALSE
);
2851 win_skip("CancelIoEx not available\n");
2855 /* add one more pending read, then cancel the first one */
2856 overlapped_read_async(reader
, read_buf
, 1, &read_overlapped
);
2857 overlapped_read_async(reader
, read_buf
, 1, &read_overlapped2
);
2858 cancel_overlapped(reader
, &read_overlapped2
);
2859 test_not_signaled(read_overlapped
.hEvent
);
2860 overlapped_write_sync(writer
, buf
, 1);
2861 test_overlapped_result(reader
, &read_overlapped
, 1, FALSE
);
2863 /* make two async writes, cancel the first one and make sure that we read from the second one */
2864 overlapped_write_async(writer
, buf
, buf_size
+2000, &write_overlapped
);
2865 overlapped_write_async(writer
, buf
, 1, &write_overlapped2
);
2866 cancel_overlapped(writer
, &write_overlapped
);
2867 overlapped_read_sync(reader
, read_buf
, 1000, 1, FALSE
);
2868 test_overlapped_result(writer
, &write_overlapped2
, 1, FALSE
);
2870 /* same as above, but parially read written data before canceling */
2871 overlapped_write_async(writer
, buf
, buf_size
+2000, &write_overlapped
);
2872 overlapped_write_async(writer
, buf
, 1, &write_overlapped2
);
2873 overlapped_read_sync(reader
, read_buf
, 10, 10, msg_read
);
2874 test_not_signaled(write_overlapped
.hEvent
);
2875 cancel_overlapped(writer
, &write_overlapped
);
2876 overlapped_read_sync(reader
, read_buf
, 1000, 1, FALSE
);
2877 test_overlapped_result(writer
, &write_overlapped2
, 1, FALSE
);
2879 /* empty queue by canceling write and make sure that flush is signaled */
2880 overlapped_write_async(writer
, buf
, buf_size
+2000, &write_overlapped
);
2881 flush_thread
= test_flush_async(writer
, ERROR_SUCCESS
);
2882 test_not_signaled(flush_thread
);
2883 cancel_overlapped(writer
, &write_overlapped
);
2884 test_flush_done(flush_thread
);
2887 static void child_process_write_pipe(HANDLE pipe
)
2889 OVERLAPPED overlapped
;
2892 memset(buf
, 'x', sizeof(buf
));
2893 overlapped_write_async(pipe
, buf
, sizeof(buf
), &overlapped
);
2895 /* sleep until parent process terminates this process */
2899 static HANDLE
create_writepipe_process(HANDLE pipe
)
2901 STARTUPINFOA si
= { sizeof(si
) };
2902 PROCESS_INFORMATION info
;
2903 char **argv
, buf
[MAX_PATH
];
2906 winetest_get_mainargs(&argv
);
2907 sprintf(buf
, "\"%s\" pipe writepipe %lx", argv
[0], (UINT_PTR
)pipe
);
2908 res
= CreateProcessA(NULL
, buf
, NULL
, NULL
, TRUE
, 0L, NULL
, NULL
, &si
, &info
);
2909 ok(res
, "CreateProcess failed: %u\n", GetLastError());
2910 CloseHandle(info
.hThread
);
2912 return info
.hProcess
;
2915 static void create_overlapped_pipe(DWORD mode
, HANDLE
*client
, HANDLE
*server
)
2917 SECURITY_ATTRIBUTES sec_attr
= { sizeof(sec_attr
), NULL
, TRUE
};
2918 DWORD read_mode
= mode
& (PIPE_READMODE_BYTE
| PIPE_READMODE_MESSAGE
);
2919 OVERLAPPED overlapped
;
2922 *server
= CreateNamedPipeA(PIPENAME
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
2923 PIPE_WAIT
| mode
, 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
2924 ok(&server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %u\n", GetLastError());
2925 test_signaled(*server
);
2927 memset(&overlapped
, 0, sizeof(overlapped
));
2928 overlapped
.hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2929 res
= ConnectNamedPipe(*server
, &overlapped
);
2930 ok(!res
&& GetLastError() == ERROR_IO_PENDING
, "WriteFile returned %x(%u)\n", res
, GetLastError());
2931 test_not_signaled(*server
);
2932 test_not_signaled(overlapped
.hEvent
);
2934 *client
= CreateFileA(PIPENAME
, GENERIC_READ
| GENERIC_WRITE
, 0, &sec_attr
, OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, NULL
);
2935 ok(*server
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
2937 res
= SetNamedPipeHandleState(*client
, &read_mode
, NULL
, NULL
);
2938 ok(res
, "SetNamedPipeHandleState failed: %u\n", GetLastError());
2940 test_signaled(*client
);
2941 test_not_signaled(*server
);
2942 test_overlapped_result(*server
, &overlapped
, 0, FALSE
);
2945 static void test_overlapped_transport(BOOL msg_mode
, BOOL msg_read_mode
)
2947 OVERLAPPED overlapped
, overlapped2
;
2948 HANDLE server
, client
, flush
;
2954 DWORD create_flags
=
2955 (msg_mode
? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
) |
2956 (msg_read_mode
? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
2958 create_overlapped_pipe(create_flags
, &client
, &server
);
2960 trace("testing %s, %s server->client writes...\n",
2961 msg_mode
? "message mode" : "byte mode", msg_read_mode
? "message read" : "byte read");
2962 test_blocking_rw(server
, client
, 5000, msg_mode
, msg_read_mode
);
2963 trace("testing %s, %s client->server writes...\n",
2964 msg_mode
? "message mode" : "byte mode", msg_read_mode
? "message read" : "byte read");
2965 test_blocking_rw(client
, server
, 6000, msg_mode
, msg_read_mode
);
2967 CloseHandle(client
);
2968 CloseHandle(server
);
2970 /* close client with pending writes */
2971 create_overlapped_pipe(create_flags
, &client
, &server
);
2972 overlapped_write_async(server
, buf
, 7000, &overlapped
);
2973 flush
= test_flush_async(server
, ERROR_BROKEN_PIPE
);
2974 CloseHandle(client
);
2975 test_overlapped_failure(server
, &overlapped
, ERROR_BROKEN_PIPE
);
2976 test_flush_done(flush
);
2977 CloseHandle(server
);
2979 /* close server with pending writes */
2980 create_overlapped_pipe(create_flags
, &client
, &server
);
2981 overlapped_write_async(client
, buf
, 7000, &overlapped
);
2982 flush
= test_flush_async(client
, ERROR_BROKEN_PIPE
);
2983 CloseHandle(server
);
2984 test_overlapped_failure(client
, &overlapped
, ERROR_BROKEN_PIPE
);
2985 test_flush_done(flush
);
2986 CloseHandle(client
);
2988 /* disconnect with pending writes */
2989 create_overlapped_pipe(create_flags
, &client
, &server
);
2990 overlapped_write_async(client
, buf
, 7000, &overlapped
);
2991 overlapped_write_async(server
, buf
, 7000, &overlapped2
);
2992 flush
= test_flush_async(client
, ERROR_PIPE_NOT_CONNECTED
);
2993 res
= DisconnectNamedPipe(server
);
2994 ok(res
, "DisconnectNamedPipe failed: %u\n", GetLastError());
2995 test_overlapped_failure(client
, &overlapped
, ERROR_PIPE_NOT_CONNECTED
);
2996 test_overlapped_failure(client
, &overlapped2
, ERROR_PIPE_NOT_CONNECTED
);
2997 test_flush_done(flush
);
2998 CloseHandle(server
);
2999 CloseHandle(client
);
3001 /* terminate process with pending write */
3002 create_overlapped_pipe(create_flags
, &client
, &server
);
3003 process
= create_writepipe_process(client
);
3004 /* successfully read part of write that is pending in child process */
3005 res
= ReadFile(server
, buf
, 10, &read_bytes
, NULL
);
3007 ok(res
, "ReadFile failed: %u\n", GetLastError());
3009 ok(!res
&& GetLastError() == ERROR_MORE_DATA
, "ReadFile returned: %x %u\n", res
, GetLastError());
3010 ok(read_bytes
== 10, "read_bytes = %u\n", read_bytes
);
3011 TerminateProcess(process
, 0);
3012 winetest_wait_child_process(process
);
3013 /* after terminating process, there is no pending write and pipe buffer is empty */
3014 overlapped_read_async(server
, buf
, 10, &overlapped
);
3015 overlapped_write_sync(client
, buf
, 1);
3016 test_overlapped_result(server
, &overlapped
, 1, FALSE
);
3017 CloseHandle(process
);
3018 CloseHandle(server
);
3019 CloseHandle(client
);
3028 hmod
= GetModuleHandleA("advapi32.dll");
3029 pDuplicateTokenEx
= (void *) GetProcAddress(hmod
, "DuplicateTokenEx");
3030 hmod
= GetModuleHandleA("kernel32.dll");
3031 pQueueUserAPC
= (void *) GetProcAddress(hmod
, "QueueUserAPC");
3032 pCancelIoEx
= (void *) GetProcAddress(hmod
, "CancelIoEx");
3034 argc
= winetest_get_mainargs(&argv
);
3036 if (argc
> 3 && !strcmp(argv
[2], "writepipe"))
3039 sscanf(argv
[3], "%lx", &handle
);
3040 child_process_write_pipe((HANDLE
)handle
);
3044 if (test_DisconnectNamedPipe())
3046 test_CreateNamedPipe_instances_must_match();
3048 test_CreateNamedPipe(PIPE_TYPE_BYTE
);
3049 test_CreateNamedPipe(PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);
3052 test_impersonation();
3054 test_overlapped_error();
3055 test_NamedPipeHandleState();
3056 test_GetNamedPipeInfo();
3057 test_readfileex_pending();
3058 test_overlapped_transport(TRUE
, FALSE
);
3059 test_overlapped_transport(TRUE
, TRUE
);
3060 if (broken(1)) /* FIXME: Remove once Wine is ready. */
3061 test_overlapped_transport(FALSE
, FALSE
);