kernel32/tests: Improved pipe CloseHandle tests.
[wine.git] / dlls / kernel32 / tests / pipe.c
blob33440bf84488c763104cef50271e2b97d1ab2ac0
1 /*
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "wine/test.h"
31 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
33 #define NB_SERVER_LOOPS 8
35 static HANDLE alarm_event;
36 static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
37 SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
38 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
40 static BOOL user_apc_ran;
41 static void CALLBACK user_apc(ULONG_PTR param)
43 user_apc_ran = TRUE;
47 enum rpcThreadOp
49 RPC_READFILE
52 struct rpcThreadArgs
54 ULONG_PTR returnValue;
55 DWORD lastError;
56 enum rpcThreadOp op;
57 ULONG_PTR args[5];
60 static DWORD CALLBACK rpcThreadMain(LPVOID arg)
62 struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
63 trace("rpcThreadMain starting\n");
64 SetLastError( rpcargs->lastError );
66 switch (rpcargs->op)
68 case RPC_READFILE:
69 rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */
70 (LPVOID)rpcargs->args[1], /* buffer */
71 (DWORD)rpcargs->args[2], /* bytesToRead */
72 (LPDWORD)rpcargs->args[3], /* bytesRead */
73 (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
74 break;
76 default:
77 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
78 rpcargs->returnValue = 0;
79 break;
82 rpcargs->lastError = GetLastError();
83 trace("rpcThreadMain returning\n");
84 return 0;
87 /* Runs ReadFile(...) from a different thread */
88 static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
90 struct rpcThreadArgs rpcargs;
91 HANDLE thread;
92 DWORD threadId, ret;
94 rpcargs.returnValue = 0;
95 rpcargs.lastError = GetLastError();
96 rpcargs.op = RPC_READFILE;
97 rpcargs.args[0] = (ULONG_PTR)hFile;
98 rpcargs.args[1] = (ULONG_PTR)buffer;
99 rpcargs.args[2] = (ULONG_PTR)bytesToRead;
100 rpcargs.args[3] = (ULONG_PTR)bytesRead;
101 rpcargs.args[4] = (ULONG_PTR)overlapped;
103 thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
104 ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
105 ret = WaitForSingleObject(thread, INFINITE);
106 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
107 CloseHandle(thread);
109 SetLastError(rpcargs.lastError);
110 return (BOOL)rpcargs.returnValue;
113 #define test_signaled(h) _test_signaled(__LINE__,h)
114 static void _test_signaled(unsigned line, HANDLE handle)
116 DWORD res = WaitForSingleObject(handle, 0);
117 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
120 static void test_CreateNamedPipe(int pipemode)
122 HANDLE hnp;
123 HANDLE hFile;
124 static const char obuf[] = "Bit Bucket";
125 static const char obuf2[] = "More bits";
126 char ibuf[32], *pbuf;
127 DWORD written;
128 DWORD readden;
129 DWORD avail;
130 DWORD lpmode;
131 BOOL ret;
133 if (pipemode == PIPE_TYPE_BYTE)
134 trace("test_CreateNamedPipe starting in byte mode\n");
135 else
136 trace("test_CreateNamedPipe starting in message mode\n");
138 /* Wait for nonexistent pipe */
139 ret = WaitNamedPipeA(PIPENAME, 2000);
140 ok(ret == 0, "WaitNamedPipe returned %d for nonexistent pipe\n", ret);
141 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
143 /* Bad parameter checks */
144 hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
145 /* nMaxInstances */ 1,
146 /* nOutBufSize */ 1024,
147 /* nInBufSize */ 1024,
148 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
149 /* lpSecurityAttrib */ NULL);
150 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
151 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
153 if (pipemode == PIPE_TYPE_BYTE)
155 /* Bad parameter checks */
156 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
157 /* nMaxInstances */ 1,
158 /* nOutBufSize */ 1024,
159 /* nInBufSize */ 1024,
160 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
161 /* lpSecurityAttrib */ NULL);
162 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
163 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
166 hnp = CreateNamedPipeA(NULL,
167 PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
168 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
169 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
170 "CreateNamedPipe should fail if name is NULL\n");
172 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
173 ok(hFile == INVALID_HANDLE_VALUE
174 && GetLastError() == ERROR_FILE_NOT_FOUND,
175 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
177 /* Functional checks */
179 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
180 /* nMaxInstances */ 1,
181 /* nOutBufSize */ 1024,
182 /* nInBufSize */ 1024,
183 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
184 /* lpSecurityAttrib */ NULL);
185 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
186 test_signaled(hnp);
188 ret = WaitNamedPipeA(PIPENAME, 2000);
189 ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
191 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
192 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
194 ok(!WaitNamedPipeA(PIPENAME, 1000), "WaitNamedPipe succeeded\n");
196 ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
198 /* don't try to do i/o if one side couldn't be opened, as it hangs */
199 if (hFile != INVALID_HANDLE_VALUE) {
200 HANDLE hFile2;
202 /* Make sure we can read and write a few bytes in both directions */
203 memset(ibuf, 0, sizeof(ibuf));
204 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
205 ok(written == sizeof(obuf), "write file len\n");
206 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
207 ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
208 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
210 memset(ibuf, 0, sizeof(ibuf));
211 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
212 ok(written == sizeof(obuf2), "write file len\n");
213 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
214 ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
215 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
217 /* Now the same again, but with an additional call to PeekNamedPipe */
218 memset(ibuf, 0, sizeof(ibuf));
219 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
220 ok(written == sizeof(obuf), "write file len 1\n");
221 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
222 ok(readden == sizeof(obuf), "peek 1 got %d bytes\n", readden);
223 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
224 ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
225 ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
227 memset(ibuf, 0, sizeof(ibuf));
228 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
229 ok(written == sizeof(obuf2), "write file len 2\n");
230 ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
231 ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
232 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &readden, NULL), "Peek\n");
233 ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
234 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
235 ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
236 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
238 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
239 memset(ibuf, 0, sizeof(ibuf));
240 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
241 ok(written == sizeof(obuf2), "write file len\n");
242 ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
243 ok(readden == 4, "read got %d bytes\n", readden);
244 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
245 ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
246 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
248 memset(ibuf, 0, sizeof(ibuf));
249 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
250 ok(written == sizeof(obuf), "write file len\n");
251 if (pipemode == PIPE_TYPE_BYTE)
253 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
255 else
257 SetLastError(0xdeadbeef);
258 todo_wine
259 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
260 todo_wine
261 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
263 ok(readden == 4, "read got %d bytes\n", readden);
264 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
265 ok(readden == sizeof(obuf) - 4, "read got %d bytes\n", readden);
266 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
268 /* Similar to above, but use a read buffer size small enough to read in three parts */
269 memset(ibuf, 0, sizeof(ibuf));
270 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
271 ok(written == sizeof(obuf2), "write file len\n");
272 if (pipemode == PIPE_TYPE_BYTE)
274 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
275 ok(readden == 4, "read got %d bytes\n", readden);
276 ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
278 else
280 SetLastError(0xdeadbeef);
281 todo_wine
282 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
283 todo_wine
284 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
285 ok(readden == 4, "read got %d bytes\n", readden);
286 SetLastError(0xdeadbeef);
287 todo_wine
288 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
289 todo_wine
290 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
292 ok(readden == 4, "read got %d bytes\n", readden);
293 ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n");
294 ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden);
295 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
297 /* Test reading of multiple writes */
298 memset(ibuf, 0, sizeof(ibuf));
299 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
300 ok(written == sizeof(obuf), "write file len 3a\n");
301 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
302 ok(written == sizeof(obuf2), "write file len 3b\n");
303 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
304 if (pipemode == PIPE_TYPE_BYTE) {
305 /* currently the Wine behavior depends on the kernel version */
306 /* ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden); */
307 if (readden != sizeof(obuf) + sizeof(obuf2)) todo_wine ok(0, "peek3 got %d bytes\n", readden);
309 else
311 /* ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden); */
312 if (readden != sizeof(obuf)) todo_wine ok(0, "peek3 got %d bytes\n", readden);
314 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
315 pbuf = ibuf;
316 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
317 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
318 pbuf += sizeof(obuf);
319 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
321 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
322 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
323 pbuf = ibuf;
324 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
325 pbuf += sizeof(obuf);
326 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
328 /* Multiple writes in the reverse direction */
329 memset(ibuf, 0, sizeof(ibuf));
330 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
331 ok(written == sizeof(obuf), "write file len 4a\n");
332 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
333 ok(written == sizeof(obuf2), "write file len 4b\n");
334 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
335 if (pipemode == PIPE_TYPE_BYTE) {
336 /* currently the Wine behavior depends on the kernel version */
337 /* ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden); */
338 if (readden != sizeof(obuf) + sizeof(obuf2)) todo_wine ok(0, "peek4 got %d bytes\n", readden);
340 else
342 /* ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden); */
343 if (readden != sizeof(obuf)) todo_wine ok(0, "peek4 got %d bytes\n", readden);
345 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
346 pbuf = ibuf;
347 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
348 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
349 pbuf += sizeof(obuf);
350 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
352 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
353 if (pipemode == PIPE_TYPE_BYTE) {
354 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
356 else {
357 todo_wine {
358 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
361 pbuf = ibuf;
362 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
363 if (pipemode == PIPE_TYPE_BYTE) {
364 pbuf += sizeof(obuf);
365 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
368 /* Test reading of multiple writes after a mode change
369 (CreateFile always creates a byte mode pipe) */
370 lpmode = PIPE_READMODE_MESSAGE;
371 if (pipemode == PIPE_TYPE_BYTE) {
372 /* trying to change the client end of a byte pipe to message mode should fail */
373 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
375 else {
376 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
378 memset(ibuf, 0, sizeof(ibuf));
379 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
380 ok(written == sizeof(obuf), "write file len 3a\n");
381 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
382 ok(written == sizeof(obuf2), "write file len 3b\n");
383 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
384 /* currently the Wine behavior depends on the kernel version */
385 /* ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden); */
386 if (readden != sizeof(obuf)) todo_wine ok(0, "peek5 got %d bytes\n", readden);
388 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
389 pbuf = ibuf;
390 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
391 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
392 todo_wine {
393 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
395 pbuf = ibuf;
396 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
397 if (readden <= sizeof(obuf))
398 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
400 /* Multiple writes in the reverse direction */
401 /* the write of obuf2 from write4 should still be in the buffer */
402 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
403 todo_wine {
404 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
405 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
407 if (avail > 0) {
408 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
409 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
410 pbuf = ibuf;
411 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
413 memset(ibuf, 0, sizeof(ibuf));
414 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
415 ok(written == sizeof(obuf), "write file len 6a\n");
416 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
417 ok(written == sizeof(obuf2), "write file len 6b\n");
418 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
419 /* currently the Wine behavior depends on the kernel version */
420 /* ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden); */
421 if (readden != sizeof(obuf)) todo_wine ok(0, "peek6 got %d bytes\n", readden);
423 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
424 pbuf = ibuf;
425 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
426 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
427 todo_wine {
428 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
430 pbuf = ibuf;
431 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
432 if (readden <= sizeof(obuf))
433 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
435 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
436 memset(ibuf, 0, sizeof(ibuf));
437 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
438 ok(written == sizeof(obuf2), "write file len 7\n");
439 SetLastError(0xdeadbeef);
440 todo_wine
441 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
442 todo_wine
443 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
444 ok(readden == 4, "read got %d bytes 7\n", readden);
445 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
446 ok(readden == sizeof(obuf2) - 4, "read got %d bytes 7\n", readden);
447 ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n");
449 memset(ibuf, 0, sizeof(ibuf));
450 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
451 ok(written == sizeof(obuf), "write file len 8\n");
452 SetLastError(0xdeadbeef);
453 todo_wine
454 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
455 todo_wine
456 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
457 ok(readden == 4, "read got %d bytes 8\n", readden);
458 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
459 ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden);
460 ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
462 /* The following test shows that when doing a partial read of a message, the rest
463 * is still in the pipe, and can be received from a second thread. This shows
464 * especially that the content is _not_ stored in thread-local-storage until it is
465 * completely transmitted. The same method works even across multiple processes. */
466 memset(ibuf, 0, sizeof(ibuf));
467 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
468 ok(written == sizeof(obuf), "write file len 9\n");
469 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
470 ok(written == sizeof(obuf2), "write file len 9\n");
471 SetLastError(0xdeadbeef);
472 todo_wine
473 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
474 todo_wine
475 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
476 ok(readden == 4, "read got %d bytes 9\n", readden);
477 SetLastError(0xdeadbeef);
478 ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
479 todo_wine
480 ok(!ret, "RpcReadFile 9\n");
481 todo_wine
482 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
483 ok(readden == 4, "read got %d bytes 9\n", readden);
484 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
485 ok(ret, "RpcReadFile 9\n");
486 todo_wine
487 ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
488 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
489 if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
491 memset(ibuf, 0, sizeof(ibuf));
492 SetLastError(0xdeadbeef);
493 ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
494 ok(!ret, "RpcReadFile 9\n");
495 todo_wine
496 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
497 ok(readden == 4, "read got %d bytes 9\n", readden);
498 SetLastError(0xdeadbeef);
499 todo_wine
500 ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
501 todo_wine
502 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
503 ok(readden == 4, "read got %d bytes 9\n", readden);
504 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
505 ok(ret, "RpcReadFile 9\n");
506 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
507 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
510 /* Now the reverse direction */
511 memset(ibuf, 0, sizeof(ibuf));
512 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
513 ok(written == sizeof(obuf2), "write file len 10\n");
514 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
515 ok(written == sizeof(obuf), "write file len 10\n");
516 SetLastError(0xdeadbeef);
517 todo_wine
518 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
519 todo_wine
520 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
521 ok(readden == 4, "read got %d bytes 10\n", readden);
522 SetLastError(0xdeadbeef);
523 ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
524 todo_wine
525 ok(!ret, "RpcReadFile 10\n");
526 todo_wine
527 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
528 ok(readden == 4, "read got %d bytes 10\n", readden);
529 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
530 ok(ret, "RpcReadFile 10\n");
531 todo_wine
532 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
533 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
534 if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
536 memset(ibuf, 0, sizeof(ibuf));
537 SetLastError(0xdeadbeef);
538 ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
539 ok(!ret, "RpcReadFile 10\n");
540 todo_wine
541 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
542 ok(readden == 4, "read got %d bytes 10\n", readden);
543 SetLastError(0xdeadbeef);
544 todo_wine
545 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
546 todo_wine
547 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
548 ok(readden == 4, "read got %d bytes 10\n", readden);
549 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
550 ok(ret, "RpcReadFile 10\n");
551 ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
552 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
557 /* Picky conformance tests */
559 /* Verify that you can't connect to pipe again
560 * until server calls DisconnectNamedPipe+ConnectNamedPipe
561 * or creates a new pipe
562 * case 1: other client not yet closed
564 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
565 ok(hFile2 == INVALID_HANDLE_VALUE,
566 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
567 ok(GetLastError() == ERROR_PIPE_BUSY,
568 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
570 ok(CloseHandle(hFile), "CloseHandle\n");
572 /* case 2: other client already closed */
573 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
574 ok(hFile == INVALID_HANDLE_VALUE,
575 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
576 ok(GetLastError() == ERROR_PIPE_BUSY,
577 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
579 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
581 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
582 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
583 ok(hFile == 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 after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
588 /* to be complete, we'd call ConnectNamedPipe here and loop,
589 * but by default that's blocking, so we'd either have
590 * to turn on the uncommon nonblocking mode, or
591 * use another thread.
595 ok(CloseHandle(hnp), "CloseHandle\n");
597 trace("test_CreateNamedPipe returning\n");
600 static void test_CreateNamedPipe_instances_must_match(void)
602 HANDLE hnp, hnp2;
604 /* Check no mismatch */
605 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
606 /* nMaxInstances */ 2,
607 /* nOutBufSize */ 1024,
608 /* nInBufSize */ 1024,
609 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
610 /* lpSecurityAttrib */ NULL);
611 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
613 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
614 /* nMaxInstances */ 2,
615 /* nOutBufSize */ 1024,
616 /* nInBufSize */ 1024,
617 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
618 /* lpSecurityAttrib */ NULL);
619 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
621 ok(CloseHandle(hnp), "CloseHandle\n");
622 ok(CloseHandle(hnp2), "CloseHandle\n");
624 /* Check nMaxInstances */
625 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
626 /* nMaxInstances */ 1,
627 /* nOutBufSize */ 1024,
628 /* nInBufSize */ 1024,
629 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
630 /* lpSecurityAttrib */ NULL);
631 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
633 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
634 /* nMaxInstances */ 1,
635 /* nOutBufSize */ 1024,
636 /* nInBufSize */ 1024,
637 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
638 /* lpSecurityAttrib */ NULL);
639 ok(hnp2 == INVALID_HANDLE_VALUE
640 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
642 ok(CloseHandle(hnp), "CloseHandle\n");
644 /* Check PIPE_ACCESS_* */
645 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
646 /* nMaxInstances */ 2,
647 /* nOutBufSize */ 1024,
648 /* nInBufSize */ 1024,
649 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
650 /* lpSecurityAttrib */ NULL);
651 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
653 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
654 /* nMaxInstances */ 2,
655 /* nOutBufSize */ 1024,
656 /* nInBufSize */ 1024,
657 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
658 /* lpSecurityAttrib */ NULL);
659 ok(hnp2 == INVALID_HANDLE_VALUE
660 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
662 ok(CloseHandle(hnp), "CloseHandle\n");
664 /* check everything else */
665 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
666 /* nMaxInstances */ 4,
667 /* nOutBufSize */ 1024,
668 /* nInBufSize */ 1024,
669 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
670 /* lpSecurityAttrib */ NULL);
671 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
673 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
674 /* nMaxInstances */ 3,
675 /* nOutBufSize */ 102,
676 /* nInBufSize */ 24,
677 /* nDefaultWait */ 1234,
678 /* lpSecurityAttrib */ NULL);
679 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
681 ok(CloseHandle(hnp), "CloseHandle\n");
682 ok(CloseHandle(hnp2), "CloseHandle\n");
685 /** implementation of alarm() */
686 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
688 DWORD_PTR timeout = (DWORD_PTR) arg;
689 trace("alarmThreadMain\n");
690 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
692 ok(FALSE, "alarm\n");
693 ExitProcess(1);
695 return 1;
698 static HANDLE hnp = INVALID_HANDLE_VALUE;
700 /** Trivial byte echo server - disconnects after each session */
701 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
703 int i;
705 trace("serverThreadMain1 start\n");
706 /* Set up a simple echo server */
707 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
708 PIPE_TYPE_BYTE | PIPE_WAIT,
709 /* nMaxInstances */ 1,
710 /* nOutBufSize */ 1024,
711 /* nInBufSize */ 1024,
712 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
713 /* lpSecurityAttrib */ NULL);
715 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
716 for (i = 0; i < NB_SERVER_LOOPS; i++) {
717 char buf[512];
718 DWORD written;
719 DWORD readden;
720 BOOL success;
722 /* Wait for client to connect */
723 trace("Server calling ConnectNamedPipe...\n");
724 ok(ConnectNamedPipe(hnp, NULL)
725 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
726 trace("ConnectNamedPipe returned.\n");
728 /* Echo bytes once */
729 memset(buf, 0, sizeof(buf));
731 trace("Server reading...\n");
732 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
733 trace("Server done reading.\n");
734 ok(success, "ReadFile\n");
735 ok(readden, "short read\n");
737 trace("Server writing...\n");
738 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
739 trace("Server done writing.\n");
740 ok(written == readden, "write file len\n");
742 /* finish this connection, wait for next one */
743 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
744 trace("Server done flushing.\n");
745 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
746 trace("Server done disconnecting.\n");
748 return 0;
751 /** Trivial byte echo server - closes after each connection */
752 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
754 int i;
755 HANDLE hnpNext = 0;
757 trace("serverThreadMain2\n");
758 /* Set up a simple echo server */
759 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
760 PIPE_TYPE_BYTE | PIPE_WAIT,
761 /* nMaxInstances */ 2,
762 /* nOutBufSize */ 1024,
763 /* nInBufSize */ 1024,
764 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
765 /* lpSecurityAttrib */ NULL);
766 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
768 for (i = 0; i < NB_SERVER_LOOPS; i++) {
769 char buf[512];
770 DWORD written;
771 DWORD readden;
772 DWORD ret;
773 BOOL success;
776 user_apc_ran = FALSE;
777 if (i == 0 && pQueueUserAPC) {
778 trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
779 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
780 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
783 /* Wait for client to connect */
784 trace("Server calling ConnectNamedPipe...\n");
785 ok(ConnectNamedPipe(hnp, NULL)
786 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
787 trace("ConnectNamedPipe returned.\n");
789 /* Echo bytes once */
790 memset(buf, 0, sizeof(buf));
792 trace("Server reading...\n");
793 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
794 trace("Server done reading.\n");
795 ok(success, "ReadFile\n");
797 trace("Server writing...\n");
798 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
799 trace("Server done writing.\n");
800 ok(written == readden, "write file len\n");
802 /* finish this connection, wait for next one */
803 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
804 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
806 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
808 if (i == 0 && pQueueUserAPC)
809 SleepEx(0, TRUE); /* get rid of apc */
811 /* Set up next echo server */
812 hnpNext =
813 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
814 PIPE_TYPE_BYTE | PIPE_WAIT,
815 /* nMaxInstances */ 2,
816 /* nOutBufSize */ 1024,
817 /* nInBufSize */ 1024,
818 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
819 /* lpSecurityAttrib */ NULL);
821 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
823 ok(CloseHandle(hnp), "CloseHandle\n");
824 hnp = hnpNext;
826 return 0;
829 /** Trivial byte echo server - uses overlapped named pipe calls */
830 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
832 int i;
833 HANDLE hEvent;
835 trace("serverThreadMain3\n");
836 /* Set up a simple echo server */
837 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
838 PIPE_TYPE_BYTE | PIPE_WAIT,
839 /* nMaxInstances */ 1,
840 /* nOutBufSize */ 1024,
841 /* nInBufSize */ 1024,
842 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
843 /* lpSecurityAttrib */ NULL);
844 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
846 hEvent = CreateEventW(NULL, /* security attribute */
847 TRUE, /* manual reset event */
848 FALSE, /* initial state */
849 NULL); /* name */
850 ok(hEvent != NULL, "CreateEvent\n");
852 for (i = 0; i < NB_SERVER_LOOPS; i++) {
853 char buf[512];
854 DWORD written;
855 DWORD readden;
856 DWORD dummy;
857 BOOL success;
858 OVERLAPPED oOverlap;
859 int letWFSOEwait = (i & 2);
860 int letGORwait = (i & 1);
861 DWORD err;
863 memset(&oOverlap, 0, sizeof(oOverlap));
864 oOverlap.hEvent = hEvent;
866 /* Wait for client to connect */
867 if (i == 0) {
868 trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
869 success = ConnectNamedPipe(hnp, NULL);
870 err = GetLastError();
871 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
872 trace("ConnectNamedPipe operation complete.\n");
873 } else {
874 trace("Server calling overlapped ConnectNamedPipe...\n");
875 success = ConnectNamedPipe(hnp, &oOverlap);
876 err = GetLastError();
877 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
878 trace("overlapped ConnectNamedPipe returned.\n");
879 if (!success && (err == ERROR_IO_PENDING)) {
880 if (letWFSOEwait)
882 DWORD ret;
883 do {
884 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
885 } while (ret == WAIT_IO_COMPLETION);
886 ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
888 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
889 if (!letGORwait && !letWFSOEwait && !success) {
890 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
891 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
894 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
895 trace("overlapped ConnectNamedPipe operation complete.\n");
898 /* Echo bytes once */
899 memset(buf, 0, sizeof(buf));
901 trace("Server reading...\n");
902 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
903 trace("Server ReadFile returned...\n");
904 err = GetLastError();
905 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
906 trace("overlapped ReadFile returned.\n");
907 if (!success && (err == ERROR_IO_PENDING)) {
908 if (letWFSOEwait)
910 DWORD ret;
911 do {
912 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
913 } while (ret == WAIT_IO_COMPLETION);
914 ok(ret == 0, "wait ReadFile returned %x\n", ret);
916 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
917 if (!letGORwait && !letWFSOEwait && !success) {
918 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
919 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
922 trace("Server done reading.\n");
923 ok(success, "overlapped ReadFile\n");
925 trace("Server writing...\n");
926 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
927 trace("Server WriteFile returned...\n");
928 err = GetLastError();
929 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
930 trace("overlapped WriteFile returned.\n");
931 if (!success && (err == ERROR_IO_PENDING)) {
932 if (letWFSOEwait)
934 DWORD ret;
935 do {
936 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
937 } while (ret == WAIT_IO_COMPLETION);
938 ok(ret == 0, "wait WriteFile returned %x\n", ret);
940 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
941 if (!letGORwait && !letWFSOEwait && !success) {
942 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
943 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
946 trace("Server done writing.\n");
947 ok(success, "overlapped WriteFile\n");
948 ok(written == readden, "write file len\n");
950 /* finish this connection, wait for next one */
951 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
952 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
954 return 0;
957 /** Trivial byte echo server - uses i/o completion ports */
958 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
960 int i;
961 HANDLE hcompletion;
962 BOOL ret;
964 trace("serverThreadMain4\n");
965 /* Set up a simple echo server */
966 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
967 PIPE_TYPE_BYTE | PIPE_WAIT,
968 /* nMaxInstances */ 1,
969 /* nOutBufSize */ 1024,
970 /* nInBufSize */ 1024,
971 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
972 /* lpSecurityAttrib */ NULL);
973 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
975 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
976 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
978 for (i = 0; i < NB_SERVER_LOOPS; i++) {
979 char buf[512];
980 DWORD written;
981 DWORD readden;
982 DWORD dummy;
983 BOOL success;
984 OVERLAPPED oConnect;
985 OVERLAPPED oRead;
986 OVERLAPPED oWrite;
987 OVERLAPPED *oResult;
988 DWORD err;
989 ULONG_PTR compkey;
991 memset(&oConnect, 0, sizeof(oConnect));
992 memset(&oRead, 0, sizeof(oRead));
993 memset(&oWrite, 0, sizeof(oWrite));
995 /* Wait for client to connect */
996 trace("Server calling overlapped ConnectNamedPipe...\n");
997 success = ConnectNamedPipe(hnp, &oConnect);
998 err = GetLastError();
999 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
1000 "overlapped ConnectNamedPipe got %u err %u\n", success, err );
1001 if (!success && err == ERROR_IO_PENDING) {
1002 trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
1003 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
1004 if (!success)
1006 ok( GetLastError() == WAIT_TIMEOUT,
1007 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
1008 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
1010 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1011 if (success)
1013 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1014 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
1017 trace("overlapped ConnectNamedPipe operation complete.\n");
1019 /* Echo bytes once */
1020 memset(buf, 0, sizeof(buf));
1022 trace("Server reading...\n");
1023 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1024 trace("Server ReadFile returned...\n");
1025 err = GetLastError();
1026 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
1027 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1028 &oResult, 10000);
1029 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1030 if (success)
1032 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1033 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
1035 trace("Server done reading.\n");
1037 trace("Server writing...\n");
1038 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1039 trace("Server WriteFile returned...\n");
1040 err = GetLastError();
1041 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
1042 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1043 &oResult, 10000);
1044 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1045 if (success)
1047 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1048 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
1049 ok(written == readden, "write file len\n");
1051 trace("Server done writing.\n");
1053 /* finish this connection, wait for next one */
1054 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1055 success = DisconnectNamedPipe(hnp);
1056 ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
1059 ret = CloseHandle(hnp);
1060 ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
1061 ret = CloseHandle(hcompletion);
1062 ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
1064 return 0;
1067 static int completion_called;
1068 static DWORD completion_errorcode;
1069 static DWORD completion_num_bytes;
1070 static LPOVERLAPPED completion_lpoverlapped;
1072 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
1074 completion_called++;
1075 completion_errorcode = errorcode;
1076 completion_num_bytes = num_bytes;
1077 completion_lpoverlapped = lpoverlapped;
1078 SetEvent(lpoverlapped->hEvent);
1081 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
1082 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
1084 int i;
1085 HANDLE hEvent;
1087 trace("serverThreadMain5\n");
1088 /* Set up a simple echo server */
1089 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1090 PIPE_TYPE_BYTE | PIPE_WAIT,
1091 /* nMaxInstances */ 1,
1092 /* nOutBufSize */ 1024,
1093 /* nInBufSize */ 1024,
1094 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1095 /* lpSecurityAttrib */ NULL);
1096 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1098 hEvent = CreateEventW(NULL, /* security attribute */
1099 TRUE, /* manual reset event */
1100 FALSE, /* initial state */
1101 NULL); /* name */
1102 ok(hEvent != NULL, "CreateEvent\n");
1104 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1105 char buf[512];
1106 DWORD readden;
1107 BOOL success;
1108 OVERLAPPED oOverlap;
1109 DWORD err;
1111 memset(&oOverlap, 0, sizeof(oOverlap));
1112 oOverlap.hEvent = hEvent;
1114 /* Wait for client to connect */
1115 trace("Server calling ConnectNamedPipe...\n");
1116 success = ConnectNamedPipe(hnp, NULL);
1117 err = GetLastError();
1118 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
1119 trace("ConnectNamedPipe operation complete.\n");
1121 /* Echo bytes once */
1122 memset(buf, 0, sizeof(buf));
1124 trace("Server reading...\n");
1125 completion_called = 0;
1126 ResetEvent(hEvent);
1127 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
1128 trace("Server ReadFileEx returned...\n");
1129 ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
1130 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1131 trace("ReadFileEx returned.\n");
1132 if (success) {
1133 DWORD ret;
1134 do {
1135 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1136 } while (ret == WAIT_IO_COMPLETION);
1137 ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
1139 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1140 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1141 ok(completion_num_bytes != 0, "read 0 bytes\n");
1142 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1143 readden = completion_num_bytes;
1144 trace("Server done reading.\n");
1146 trace("Server writing...\n");
1147 completion_called = 0;
1148 ResetEvent(hEvent);
1149 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
1150 trace("Server WriteFileEx returned...\n");
1151 ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
1152 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1153 trace("overlapped WriteFile returned.\n");
1154 if (success) {
1155 DWORD ret;
1156 do {
1157 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1158 } while (ret == WAIT_IO_COMPLETION);
1159 ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
1161 trace("Server done writing.\n");
1162 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1163 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1164 ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
1165 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1167 /* finish this connection, wait for next one */
1168 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1169 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1171 return 0;
1174 static void exercizeServer(const char *pipename, HANDLE serverThread)
1176 int i;
1178 trace("exercizeServer starting\n");
1179 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1180 HANDLE hFile=INVALID_HANDLE_VALUE;
1181 static const char obuf[] = "Bit Bucket";
1182 char ibuf[32];
1183 DWORD written;
1184 DWORD readden;
1185 int loop;
1187 for (loop = 0; loop < 3; loop++) {
1188 DWORD err;
1189 trace("Client connecting...\n");
1190 /* Connect to the server */
1191 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
1192 NULL, OPEN_EXISTING, 0, 0);
1193 if (hFile != INVALID_HANDLE_VALUE)
1194 break;
1195 err = GetLastError();
1196 if (loop == 0)
1197 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
1198 else
1199 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
1200 trace("connect failed, retrying\n");
1201 Sleep(200);
1203 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
1205 /* Make sure it can echo */
1206 memset(ibuf, 0, sizeof(ibuf));
1207 trace("Client writing...\n");
1208 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1209 ok(written == sizeof(obuf), "write file len\n");
1210 trace("Client reading...\n");
1211 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1212 ok(readden == sizeof(obuf), "read file len\n");
1213 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1215 trace("Client closing...\n");
1216 ok(CloseHandle(hFile), "CloseHandle\n");
1219 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1220 CloseHandle(hnp);
1221 trace("exercizeServer returning\n");
1224 static void test_NamedPipe_2(void)
1226 HANDLE serverThread;
1227 DWORD serverThreadId;
1228 HANDLE alarmThread;
1229 DWORD alarmThreadId;
1231 trace("test_NamedPipe_2 starting\n");
1232 /* Set up a twenty second timeout */
1233 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1234 SetLastError(0xdeadbeef);
1235 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1236 ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
1238 /* The servers we're about to exercise do try to clean up carefully,
1239 * but to reduce the chance of a test failure due to a pipe handle
1240 * leak in the test code, we'll use a different pipe name for each server.
1243 /* Try server #1 */
1244 SetLastError(0xdeadbeef);
1245 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1246 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1247 exercizeServer(PIPENAME "serverThreadMain1", serverThread);
1249 /* Try server #2 */
1250 SetLastError(0xdeadbeef);
1251 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1252 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1253 exercizeServer(PIPENAME "serverThreadMain2", serverThread);
1255 /* Try server #3 */
1256 SetLastError(0xdeadbeef);
1257 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1258 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1259 exercizeServer(PIPENAME "serverThreadMain3", serverThread);
1261 /* Try server #4 */
1262 SetLastError(0xdeadbeef);
1263 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1264 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1265 exercizeServer(PIPENAME "serverThreadMain4", serverThread);
1267 /* Try server #5 */
1268 SetLastError(0xdeadbeef);
1269 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1270 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1271 exercizeServer(PIPENAME "serverThreadMain5", serverThread);
1273 ok(SetEvent( alarm_event ), "SetEvent\n");
1274 CloseHandle( alarm_event );
1275 trace("test_NamedPipe_2 returning\n");
1278 static int test_DisconnectNamedPipe(void)
1280 HANDLE hnp;
1281 HANDLE hFile;
1282 static const char obuf[] = "Bit Bucket";
1283 char ibuf[32];
1284 DWORD written;
1285 DWORD readden;
1286 DWORD ret;
1288 SetLastError(0xdeadbeef);
1289 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1290 /* nMaxInstances */ 1,
1291 /* nOutBufSize */ 1024,
1292 /* nInBufSize */ 1024,
1293 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1294 /* lpSecurityAttrib */ NULL);
1295 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1296 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1298 win_skip("Named pipes are not implemented\n");
1299 return 1;
1302 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1303 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1304 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1305 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1307 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1308 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1310 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1311 if (hFile != INVALID_HANDLE_VALUE) {
1313 /* see what happens if server calls DisconnectNamedPipe
1314 * when there are bytes in the pipe
1317 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1318 ok(written == sizeof(obuf), "write file len\n");
1319 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1320 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1321 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1322 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1323 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1324 "ReadFile from disconnected pipe with bytes waiting\n");
1325 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1326 "DisconnectNamedPipe worked twice\n");
1327 ret = WaitForSingleObject(hFile, 0);
1328 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1329 ok(CloseHandle(hFile), "CloseHandle\n");
1332 ok(CloseHandle(hnp), "CloseHandle\n");
1334 return 0;
1336 static void test_CreatePipe(void)
1338 SECURITY_ATTRIBUTES pipe_attr;
1339 HANDLE piperead, pipewrite;
1340 DWORD written;
1341 DWORD read;
1342 DWORD i, size;
1343 BYTE *buffer;
1344 char readbuf[32];
1346 user_apc_ran = FALSE;
1347 if (pQueueUserAPC)
1348 ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1350 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1351 pipe_attr.bInheritHandle = TRUE;
1352 pipe_attr.lpSecurityDescriptor = NULL;
1353 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1354 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1355 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1356 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1357 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1358 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1359 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1361 /* Now write another chunk*/
1362 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1363 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1364 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1365 /* and close the write end, read should still succeed*/
1366 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1367 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe with pending data failed\n");
1368 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1369 /* But now we need to get informed that the pipe is closed */
1370 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1371 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1373 /* Try bigger chunks */
1374 size = 32768;
1375 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1376 for (i = 0; i < size; i++) buffer[i] = i;
1377 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1378 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1379 ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1380 /* and close the write end, read should still succeed*/
1381 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1382 memset( buffer, 0, size );
1383 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe with pending data failed\n");
1384 ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
1385 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1386 /* But now we need to get informed that the pipe is closed */
1387 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1388 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1389 HeapFree(GetProcessHeap(), 0, buffer);
1391 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1392 SleepEx(0, TRUE); /* get rid of apc */
1395 static void test_CloseHandle(void)
1397 static const char testdata[] = "Hello World";
1398 DWORD state, numbytes;
1399 HANDLE hpipe, hfile;
1400 char buffer[32];
1401 BOOL ret;
1403 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1404 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1405 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1406 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1408 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1409 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1411 numbytes = 0xdeadbeef;
1412 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1413 ok(ret, "WriteFile failed with %u\n", GetLastError());
1414 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1416 numbytes = 0xdeadbeef;
1417 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1418 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1419 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1421 ret = CloseHandle(hpipe);
1422 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1424 numbytes = 0xdeadbeef;
1425 memset(buffer, 0, sizeof(buffer));
1426 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1427 todo_wine ok(ret, "ReadFile failed with %u\n", GetLastError());
1428 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1430 numbytes = 0xdeadbeef;
1431 memset(buffer, 0, sizeof(buffer));
1432 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1433 ok(ret, "ReadFile failed with %u\n", GetLastError());
1434 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1436 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1437 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1438 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1439 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1440 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1442 SetLastError(0xdeadbeef);
1443 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1444 ok(!ret, "ReadFile unexpectedly succeeded\n");
1445 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1447 SetLastError(0xdeadbeef);
1448 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1449 ok(!ret, "WriteFile unexpectedly succeeded\n");
1450 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1452 CloseHandle(hfile);
1454 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1455 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1456 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1457 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1459 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1460 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1462 numbytes = 0xdeadbeef;
1463 ret = WriteFile(hpipe, testdata, 0, &numbytes, NULL);
1464 ok(ret, "WriteFile failed with %u\n", GetLastError());
1465 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1467 ret = CloseHandle(hpipe);
1468 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1470 numbytes = 0xdeadbeef;
1471 memset(buffer, 0, sizeof(buffer));
1472 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1473 todo_wine ok(ret, "ReadFile failed with %u\n", GetLastError());
1474 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1476 SetLastError(0xdeadbeef);
1477 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1478 ok(!ret, "ReadFile unexpectedly succeeded\n");
1479 todo_wine ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1481 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1482 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1483 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1484 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1485 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1487 SetLastError(0xdeadbeef);
1488 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1489 ok(!ret, "ReadFile unexpectedly succeeded\n");
1490 todo_wine ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1492 SetLastError(0xdeadbeef);
1493 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1494 ok(!ret, "WriteFile unexpectedly succeeded\n");
1495 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1497 CloseHandle(hfile);
1499 /* repeat test with hpipe <-> hfile swapped */
1501 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1502 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1503 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1504 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1506 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1507 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1509 numbytes = 0xdeadbeef;
1510 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1511 ok(ret, "WriteFile failed with %u\n", GetLastError());
1512 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1514 numbytes = 0xdeadbeef;
1515 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1516 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1517 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1519 ret = CloseHandle(hfile);
1520 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1522 numbytes = 0xdeadbeef;
1523 memset(buffer, 0, sizeof(buffer));
1524 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1525 todo_wine ok(ret || broken(GetLastError() == ERROR_MORE_DATA) /* >= Win 8 */,
1526 "ReadFile failed with %u\n", GetLastError());
1527 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1529 numbytes = 0xdeadbeef;
1530 memset(buffer, 0, sizeof(buffer));
1531 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1532 ok(ret, "ReadFile failed with %u\n", GetLastError());
1533 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1535 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1536 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1537 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1538 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1539 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1541 SetLastError(0xdeadbeef);
1542 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1543 ok(!ret, "ReadFile unexpectedly succeeded\n");
1544 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1546 SetLastError(0xdeadbeef);
1547 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1548 ok(!ret, "WriteFile unexpectedly succeeded\n");
1549 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1551 CloseHandle(hpipe);
1553 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1554 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1555 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1556 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1558 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1559 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1561 numbytes = 0xdeadbeef;
1562 ret = WriteFile(hfile, testdata, 0, &numbytes, NULL);
1563 ok(ret, "WriteFile failed with %u\n", GetLastError());
1564 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1566 ret = CloseHandle(hfile);
1567 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1569 numbytes = 0xdeadbeef;
1570 memset(buffer, 0, sizeof(buffer));
1571 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1572 todo_wine ok(ret, "ReadFile failed with %u\n", GetLastError());
1573 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1575 SetLastError(0xdeadbeef);
1576 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1577 ok(!ret, "ReadFile unexpectedly succeeded\n");
1578 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1580 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1581 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1582 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1583 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1584 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1586 SetLastError(0xdeadbeef);
1587 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1588 ok(!ret, "ReadFile unexpectedly succeeded\n");
1589 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1591 SetLastError(0xdeadbeef);
1592 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1593 ok(!ret, "WriteFile unexpectedly succeeded\n");
1594 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1596 CloseHandle(hpipe);
1599 struct named_pipe_client_params
1601 DWORD security_flags;
1602 HANDLE token;
1603 BOOL revert;
1606 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1608 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1610 struct named_pipe_client_params *params = p;
1611 HANDLE pipe;
1612 BOOL ret;
1613 const char message[] = "Test";
1614 DWORD bytes_read, bytes_written;
1615 char dummy;
1616 TOKEN_PRIVILEGES *Privileges = NULL;
1618 if (params->token)
1620 if (params->revert)
1622 /* modify the token so we can tell if the pipe impersonation
1623 * token reverts to the process token */
1624 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1625 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1627 ret = SetThreadToken(NULL, params->token);
1628 ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1630 else
1632 DWORD Size = 0;
1633 HANDLE process_token;
1635 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1636 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1638 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1639 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1640 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1641 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1642 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1644 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1645 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1647 CloseHandle(process_token);
1650 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1651 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1653 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1654 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1656 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1657 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1659 if (params->token)
1661 if (params->revert)
1663 ret = RevertToSelf();
1664 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1666 else
1668 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1669 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1672 else
1674 HANDLE process_token;
1676 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1677 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1679 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1680 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1682 HeapFree(GetProcessHeap(), 0, Privileges);
1684 CloseHandle(process_token);
1687 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1688 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1690 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1691 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1693 CloseHandle(pipe);
1695 return 0;
1698 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1700 HANDLE ProcessToken;
1701 HANDLE Token = NULL;
1702 BOOL ret;
1704 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1705 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1707 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1708 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1710 CloseHandle(ProcessToken);
1712 return Token;
1715 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1717 HANDLE hPipeServer;
1718 BOOL ret;
1719 DWORD dwTid;
1720 HANDLE hThread;
1721 char buffer[256];
1722 DWORD dwBytesRead;
1723 DWORD error;
1724 struct named_pipe_client_params params;
1725 char dummy = 0;
1726 DWORD dwBytesWritten;
1727 HANDLE hToken = NULL;
1728 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1729 DWORD size;
1731 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1732 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1734 params.security_flags = security_flags;
1735 params.token = hClientToken;
1736 params.revert = revert;
1737 hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1738 ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1740 SetLastError(0xdeadbeef);
1741 ret = ImpersonateNamedPipeClient(hPipeServer);
1742 error = GetLastError();
1743 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1744 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1746 ret = ConnectNamedPipe(hPipeServer, NULL);
1747 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1749 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1750 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1752 ret = ImpersonateNamedPipeClient(hPipeServer);
1753 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1755 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1756 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1758 (*test_func)(0, hToken);
1760 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1761 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1762 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1763 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1765 CloseHandle(hToken);
1767 RevertToSelf();
1769 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1770 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1772 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1773 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1775 ret = ImpersonateNamedPipeClient(hPipeServer);
1776 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1778 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1779 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1781 (*test_func)(1, hToken);
1783 CloseHandle(hToken);
1785 RevertToSelf();
1787 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1788 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1790 WaitForSingleObject(hThread, INFINITE);
1792 ret = ImpersonateNamedPipeClient(hPipeServer);
1793 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1795 RevertToSelf();
1797 CloseHandle(hThread);
1798 CloseHandle(hPipeServer);
1801 static BOOL are_all_privileges_disabled(HANDLE hToken)
1803 BOOL ret;
1804 TOKEN_PRIVILEGES *Privileges = NULL;
1805 DWORD Size = 0;
1806 BOOL all_privs_disabled = TRUE;
1807 DWORD i;
1809 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1810 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1812 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1813 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1814 if (!ret)
1816 HeapFree(GetProcessHeap(), 0, Privileges);
1817 return FALSE;
1820 else
1821 return FALSE;
1823 for (i = 0; i < Privileges->PrivilegeCount; i++)
1825 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
1827 all_privs_disabled = FALSE;
1828 break;
1832 HeapFree(GetProcessHeap(), 0, Privileges);
1834 return all_privs_disabled;
1837 static DWORD get_privilege_count(HANDLE hToken)
1839 TOKEN_STATISTICS Statistics;
1840 DWORD Size = sizeof(Statistics);
1841 BOOL ret;
1843 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
1844 ok(ret, "GetTokenInformation(TokenStatistics)\n");
1845 if (!ret) return -1;
1847 return Statistics.PrivilegeCount;
1850 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
1852 DWORD priv_count;
1854 switch (call_index)
1856 case 0:
1857 priv_count = get_privilege_count(hToken);
1858 todo_wine
1859 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1860 break;
1861 case 1:
1862 priv_count = get_privilege_count(hToken);
1863 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1864 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1865 break;
1866 default:
1867 ok(0, "shouldn't happen\n");
1871 static void test_no_sqos(int call_index, HANDLE hToken)
1873 switch (call_index)
1875 case 0:
1876 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1877 break;
1878 case 1:
1879 todo_wine
1880 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1881 break;
1882 default:
1883 ok(0, "shouldn't happen\n");
1887 static void test_static_context(int call_index, HANDLE hToken)
1889 switch (call_index)
1891 case 0:
1892 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1893 break;
1894 case 1:
1895 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1896 break;
1897 default:
1898 ok(0, "shouldn't happen\n");
1902 static void test_dynamic_context(int call_index, HANDLE hToken)
1904 switch (call_index)
1906 case 0:
1907 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1908 break;
1909 case 1:
1910 todo_wine
1911 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1912 break;
1913 default:
1914 ok(0, "shouldn't happen\n");
1918 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
1920 switch (call_index)
1922 case 0:
1923 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1924 break;
1925 case 1:
1926 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
1927 break;
1928 default:
1929 ok(0, "shouldn't happen\n");
1933 static void test_no_sqos_revert(int call_index, HANDLE hToken)
1935 DWORD priv_count;
1936 switch (call_index)
1938 case 0:
1939 priv_count = get_privilege_count(hToken);
1940 todo_wine
1941 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1942 break;
1943 case 1:
1944 priv_count = get_privilege_count(hToken);
1945 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1946 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1947 break;
1948 default:
1949 ok(0, "shouldn't happen\n");
1953 static void test_static_context_revert(int call_index, HANDLE hToken)
1955 switch (call_index)
1957 case 0:
1958 todo_wine
1959 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1960 break;
1961 case 1:
1962 todo_wine
1963 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1964 break;
1965 default:
1966 ok(0, "shouldn't happen\n");
1970 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
1972 switch (call_index)
1974 case 0:
1975 todo_wine
1976 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1977 break;
1978 case 1:
1979 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
1980 break;
1981 default:
1982 ok(0, "shouldn't happen\n");
1986 static void test_impersonation(void)
1988 HANDLE hClientToken;
1989 HANDLE hProcessToken;
1990 BOOL ret;
1992 if( !pDuplicateTokenEx ) {
1993 skip("DuplicateTokenEx not found\n");
1994 return;
1997 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
1998 if (!ret)
2000 skip("couldn't open process token, skipping impersonation tests\n");
2001 return;
2004 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
2006 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
2007 CloseHandle(hProcessToken);
2008 return;
2010 CloseHandle(hProcessToken);
2012 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
2013 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2014 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
2015 CloseHandle(hClientToken);
2016 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2017 test_ImpersonateNamedPipeClient(hClientToken,
2018 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
2019 test_static_context);
2020 CloseHandle(hClientToken);
2021 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2022 test_ImpersonateNamedPipeClient(hClientToken,
2023 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2024 FALSE, test_dynamic_context);
2025 CloseHandle(hClientToken);
2026 test_ImpersonateNamedPipeClient(NULL,
2027 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2028 FALSE, test_dynamic_context_no_token);
2030 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2031 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
2032 CloseHandle(hClientToken);
2033 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2034 test_ImpersonateNamedPipeClient(hClientToken,
2035 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
2036 test_static_context_revert);
2037 CloseHandle(hClientToken);
2038 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2039 test_ImpersonateNamedPipeClient(hClientToken,
2040 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2041 TRUE, test_dynamic_context_revert);
2042 CloseHandle(hClientToken);
2045 struct overlapped_server_args
2047 HANDLE pipe_created;
2050 static DWORD CALLBACK overlapped_server(LPVOID arg)
2052 OVERLAPPED ol;
2053 HANDLE pipe;
2054 int ret, err;
2055 struct overlapped_server_args *a = arg;
2056 DWORD num;
2057 char buf[100];
2059 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
2060 ok(pipe != NULL, "pipe NULL\n");
2062 ol.hEvent = CreateEventA(0, 1, 0, 0);
2063 ok(ol.hEvent != NULL, "event NULL\n");
2064 ret = ConnectNamedPipe(pipe, &ol);
2065 err = GetLastError();
2066 ok(ret == 0, "ret %d\n", ret);
2067 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2068 SetEvent(a->pipe_created);
2070 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2071 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2073 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2074 ok(ret == 1, "ret %d\n", ret);
2076 /* This should block */
2077 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
2078 ok(ret == 1, "ret %d\n", ret);
2080 DisconnectNamedPipe(pipe);
2082 ret = ConnectNamedPipe(pipe, &ol);
2083 err = GetLastError();
2084 ok(ret == 0, "ret %d\n", ret);
2085 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2086 CancelIo(pipe);
2087 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2088 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2090 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2091 err = GetLastError();
2092 ok(ret == 0, "ret %d\n", ret);
2093 ok(err == ERROR_OPERATION_ABORTED, "gle %d\n", err);
2095 CloseHandle(ol.hEvent);
2096 CloseHandle(pipe);
2097 return 1;
2100 static void test_overlapped(void)
2102 DWORD tid, num;
2103 HANDLE thread, pipe;
2104 BOOL ret;
2105 struct overlapped_server_args args;
2107 args.pipe_created = CreateEventA(0, 1, 0, 0);
2108 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
2110 WaitForSingleObject(args.pipe_created, INFINITE);
2111 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
2112 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
2114 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
2115 Sleep(1);
2117 ret = WriteFile(pipe, "x", 1, &num, NULL);
2118 ok(ret, "WriteFile failed with error %d\n", GetLastError());
2120 WaitForSingleObject(thread, INFINITE);
2121 CloseHandle(pipe);
2122 CloseHandle(args.pipe_created);
2123 CloseHandle(thread);
2126 static void test_overlapped_error(void)
2128 HANDLE pipe, file, event;
2129 DWORD err, numbytes;
2130 OVERLAPPED overlapped;
2131 BOOL ret;
2133 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2134 ok(event != NULL, "CreateEventA failed with %u\n", GetLastError());
2136 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2137 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2138 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2139 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2141 memset(&overlapped, 0, sizeof(overlapped));
2142 overlapped.hEvent = event;
2143 ret = ConnectNamedPipe(pipe, &overlapped);
2144 err = GetLastError();
2145 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2146 ok(err == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", err);
2148 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2149 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2150 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2152 numbytes = 0xdeadbeef;
2153 ret = GetOverlappedResult(pipe, &overlapped, &numbytes, TRUE);
2154 ok(ret == TRUE, "GetOverlappedResult failed\n");
2155 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
2156 ok(overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", overlapped.Internal);
2158 CloseHandle(file);
2159 CloseHandle(pipe);
2161 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2162 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2163 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2164 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2166 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2167 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2168 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2170 memset(&overlapped, 0, sizeof(overlapped));
2171 overlapped.hEvent = event;
2172 ret = ConnectNamedPipe(pipe, &overlapped);
2173 err = GetLastError();
2174 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2175 ok(err == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", err);
2176 ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", overlapped.Internal);
2178 CloseHandle(file);
2179 CloseHandle(pipe);
2181 CloseHandle(event);
2184 static void test_NamedPipeHandleState(void)
2186 HANDLE server, client;
2187 BOOL ret;
2188 DWORD state, instances, maxCollectionCount, collectDataTimeout;
2189 char userName[MAX_PATH];
2191 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2192 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2193 /* nMaxInstances */ 1,
2194 /* nOutBufSize */ 1024,
2195 /* nInBufSize */ 1024,
2196 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2197 /* lpSecurityAttrib */ NULL);
2198 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2199 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2200 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2201 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2203 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2204 if (ret)
2206 ok(state == 0, "unexpected state %08x\n", state);
2207 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2209 /* Some parameters have no meaning, and therefore can't be retrieved,
2210 * on a local pipe.
2212 SetLastError(0xdeadbeef);
2213 ret = GetNamedPipeHandleStateA(server, &state, &instances,
2214 &maxCollectionCount, &collectDataTimeout, userName,
2215 sizeof(userName) / sizeof(userName[0]));
2216 todo_wine
2217 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2218 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2219 /* A byte-mode pipe server can't be changed to message mode. */
2220 state = PIPE_READMODE_MESSAGE;
2221 SetLastError(0xdeadbeef);
2222 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2223 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2224 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2226 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2227 OPEN_EXISTING, 0, NULL);
2228 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2230 state = PIPE_READMODE_BYTE;
2231 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2232 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2233 /* A byte-mode pipe client can't be changed to message mode, either. */
2234 state = PIPE_READMODE_MESSAGE;
2235 SetLastError(0xdeadbeef);
2236 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2237 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2238 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2240 CloseHandle(client);
2241 CloseHandle(server);
2243 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2244 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2245 /* nMaxInstances */ 1,
2246 /* nOutBufSize */ 1024,
2247 /* nInBufSize */ 1024,
2248 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2249 /* lpSecurityAttrib */ NULL);
2250 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2251 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2252 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2253 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2255 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2256 if (ret)
2258 ok(state == 0, "unexpected state %08x\n", state);
2259 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2261 /* In contrast to byte-mode pipes, a message-mode pipe server can be
2262 * changed to byte mode.
2264 state = PIPE_READMODE_BYTE;
2265 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2266 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2268 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2269 OPEN_EXISTING, 0, NULL);
2270 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2272 state = PIPE_READMODE_MESSAGE;
2273 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2274 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2275 /* A message-mode pipe client can also be changed to byte mode.
2277 state = PIPE_READMODE_BYTE;
2278 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2279 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2281 CloseHandle(client);
2282 CloseHandle(server);
2285 #define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
2286 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)
2288 DWORD flags = 0xdeadbeef, out_buf_size = 0xdeadbeef, in_buf_size = 0xdeadbeef, max_instances = 0xdeadbeef;
2289 BOOL res;
2291 res = GetNamedPipeInfo(pipe, &flags, &out_buf_size, &in_buf_size, &max_instances);
2292 ok_(__FILE__,line)(res, "GetNamedPipeInfo failed: %x\n", res);
2293 ok_(__FILE__,line)(flags == ex_flags, "flags = %x, expected %x\n", flags, ex_flags);
2294 ok_(__FILE__,line)(out_buf_size == ex_out_buf_size, "out_buf_size = %x, expected %u\n", out_buf_size, ex_out_buf_size);
2295 ok_(__FILE__,line)(in_buf_size == ex_in_buf_size, "in_buf_size = %x, expected %u\n", in_buf_size, ex_in_buf_size);
2296 ok_(__FILE__,line)(max_instances == ex_max_instances, "max_instances = %x, expected %u\n", max_instances, ex_max_instances);
2299 static void test_GetNamedPipeInfo(void)
2301 HANDLE server;
2303 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2304 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2305 /* nMaxInstances */ 1,
2306 /* nOutBufSize */ 1024,
2307 /* nInBufSize */ 1024,
2308 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2309 /* lpSecurityAttrib */ NULL);
2310 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2312 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_BYTE, 1024, 1024, 1);
2314 CloseHandle(server);
2316 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2317 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
2318 /* nMaxInstances */ 3,
2319 /* nOutBufSize */ 1024,
2320 /* nInBufSize */ 1024,
2321 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2322 /* lpSecurityAttrib */ NULL);
2323 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2325 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 1024, 1024, 3);
2327 CloseHandle(server);
2329 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2330 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2331 /* nMaxInstances */ 1,
2332 /* nOutBufSize */ 0,
2333 /* nInBufSize */ 0,
2334 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2335 /* lpSecurityAttrib */ NULL);
2336 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2338 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0, 0, 1);
2340 CloseHandle(server);
2342 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2343 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2344 /* nMaxInstances */ 1,
2345 /* nOutBufSize */ 0xf000,
2346 /* nInBufSize */ 0xf000,
2347 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2348 /* lpSecurityAttrib */ NULL);
2349 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2351 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0xf000, 0xf000, 1);
2353 CloseHandle(server);
2356 static void test_readfileex_pending(void)
2358 HANDLE server, client, event;
2359 BOOL ret;
2360 DWORD err, wait, num_bytes;
2361 OVERLAPPED overlapped;
2362 char read_buf[1024];
2363 char write_buf[1024];
2364 const char test_string[] = "test";
2365 int i;
2367 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2368 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2369 /* nMaxInstances */ 1,
2370 /* nOutBufSize */ 1024,
2371 /* nInBufSize */ 1024,
2372 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2373 /* lpSecurityAttrib */ NULL);
2374 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2376 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2377 ok(event != NULL, "CreateEventA failed\n");
2379 memset(&overlapped, 0, sizeof(overlapped));
2380 overlapped.hEvent = event;
2382 ret = ConnectNamedPipe(server, &overlapped);
2383 err = GetLastError();
2384 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2385 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
2387 wait = WaitForSingleObject(event, 0);
2388 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
2390 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2391 OPEN_EXISTING, 0, NULL);
2392 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2394 wait = WaitForSingleObject(event, 0);
2395 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2397 /* Start a read that can't complete immediately. */
2398 completion_called = 0;
2399 ResetEvent(event);
2400 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
2401 ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
2402 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
2404 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
2405 ok(ret == TRUE, "WriteFile failed\n");
2406 ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
2408 ok(completion_called == 0, "completion routine called during WriteFile\n");
2410 wait = WaitForSingleObjectEx(event, 0, TRUE);
2411 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
2413 ok(completion_called == 1, "completion not called after writing pipe\n");
2414 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2415 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
2416 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2417 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
2419 /* Make writes until the pipe is full and the write fails */
2420 memset(write_buf, 0xaa, sizeof(write_buf));
2421 for (i=0; i<256; i++)
2423 completion_called = 0;
2424 ResetEvent(event);
2425 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
2426 err = GetLastError();
2428 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
2430 wait = WaitForSingleObjectEx(event, 0, TRUE);
2432 if (wait == WAIT_TIMEOUT)
2433 /* write couldn't complete immediately, presumably the pipe is full */
2434 break;
2436 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2438 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
2439 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2440 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2443 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
2444 ok(completion_called == 0, "completion routine called but wait timed out\n");
2445 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2446 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2448 /* free up some space in the pipe */
2449 for (i=0; i<256; i++)
2451 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
2452 ok(ret == TRUE, "ReadFile failed\n");
2454 ok(completion_called == 0, "completion routine called during ReadFile\n");
2456 wait = WaitForSingleObjectEx(event, 0, TRUE);
2457 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0 || wait == WAIT_TIMEOUT,
2458 "WaitForSingleObject returned %x\n", wait);
2459 if (wait != WAIT_TIMEOUT) break;
2462 ok(completion_called == 1, "completion routine not called\n");
2463 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2464 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2466 num_bytes = 0xdeadbeef;
2467 SetLastError(0xdeadbeef);
2468 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
2469 ok(!ret, "ReadFile should fail\n");
2470 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
2471 ok(num_bytes == 0, "expected 0, got %u\n", num_bytes);
2473 S(U(overlapped)).Offset = 0;
2474 S(U(overlapped)).OffsetHigh = 0;
2475 overlapped.Internal = -1;
2476 overlapped.InternalHigh = -1;
2477 overlapped.hEvent = event;
2478 num_bytes = 0xdeadbeef;
2479 SetLastError(0xdeadbeef);
2480 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
2481 ok(!ret, "ReadFile should fail\n");
2482 todo_wine
2483 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2484 ok(num_bytes == 0, "bytes %u\n", num_bytes);
2485 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
2486 todo_wine
2487 ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
2489 wait = WaitForSingleObject(event, 100);
2490 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
2492 num_bytes = 0xdeadbeef;
2493 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
2494 ok(ret, "WriteFile failed\n");
2495 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2497 wait = WaitForSingleObject(event, 100);
2498 todo_wine
2499 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2501 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2502 todo_wine
2503 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
2504 ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
2506 /* read the pending byte and clear the pipe */
2507 num_bytes = 0xdeadbeef;
2508 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
2509 ok(ret, "ReadFile failed\n");
2510 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2512 CloseHandle(client);
2513 CloseHandle(server);
2514 CloseHandle(event);
2517 START_TEST(pipe)
2519 HMODULE hmod;
2521 hmod = GetModuleHandleA("advapi32.dll");
2522 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
2523 hmod = GetModuleHandleA("kernel32.dll");
2524 pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
2526 if (test_DisconnectNamedPipe())
2527 return;
2528 test_CreateNamedPipe_instances_must_match();
2529 test_NamedPipe_2();
2530 test_CreateNamedPipe(PIPE_TYPE_BYTE);
2531 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
2532 test_CreatePipe();
2533 test_CloseHandle();
2534 test_impersonation();
2535 test_overlapped();
2536 test_overlapped_error();
2537 test_NamedPipeHandleState();
2538 test_GetNamedPipeInfo();
2539 test_readfileex_pending();