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
25 #define WIN32_NO_STATUS
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
)
54 ULONG_PTR returnValue
;
60 static DWORD CALLBACK
rpcThreadMain(LPVOID arg
)
62 struct rpcThreadArgs
*rpcargs
= (struct rpcThreadArgs
*)arg
;
63 trace("rpcThreadMain starting\n");
64 SetLastError( rpcargs
->lastError
);
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 */
77 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
78 rpcargs
->returnValue
= 0;
82 rpcargs
->lastError
= GetLastError();
83 trace("rpcThreadMain returning\n");
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
;
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());
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
)
124 static const char obuf
[] = "Bit Bucket";
125 static const char obuf2
[] = "More bits";
126 char ibuf
[32], *pbuf
;
133 if (pipemode
== PIPE_TYPE_BYTE
)
134 trace("test_CreateNamedPipe starting in byte mode\n");
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");
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
) {
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");
257 SetLastError(0xdeadbeef);
259 ok(!ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile\n");
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");
280 SetLastError(0xdeadbeef);
282 ok(!ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile\n");
284 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error\n");
285 ok(readden
== 4, "read got %d bytes\n", readden
);
286 SetLastError(0xdeadbeef);
288 ok(!ReadFile(hnp
, ibuf
+ 4, 4, &readden
, NULL
), "ReadFile\n");
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
);
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
);
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
);
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
);
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
);
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
);
358 ok(readden
== sizeof(obuf
), "read 4 got %d bytes\n", readden
);
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");
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
);
390 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "content 5a check\n");
391 ok(ReadFile(hFile
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
393 ok(readden
== sizeof(obuf
), "read 5 got %d bytes\n", readden
);
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");
404 ok(readden
== sizeof(obuf2
), "peek6a got %d bytes\n", readden
);
405 ok(avail
== sizeof(obuf2
), "peek6a got %d bytes available\n", avail
);
408 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
409 ok(readden
== sizeof(obuf2
), "read 6a got %d bytes\n", readden
);
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
);
425 ok(memcmp(obuf
, pbuf
, sizeof(obuf
)) == 0, "content 6a check\n");
426 ok(ReadFile(hnp
, ibuf
, sizeof(ibuf
), &readden
, NULL
), "ReadFile\n");
428 ok(readden
== sizeof(obuf
), "read 6b got %d bytes\n", readden
);
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);
441 ok(!ReadFile(hFile
, ibuf
, 4, &readden
, NULL
), "ReadFile 7\n");
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);
454 ok(!ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile 8\n");
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);
473 ok(!ReadFile(hFile
, ibuf
, 4, &readden
, NULL
), "ReadFile 9\n");
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
);
480 ok(!ret
, "RpcReadFile 9\n");
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");
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");
496 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 9\n");
497 ok(readden
== 4, "read got %d bytes 9\n", readden
);
498 SetLastError(0xdeadbeef);
500 ok(!ReadFile(hFile
, ibuf
+ 4, 4, &readden
, NULL
), "ReadFile 9\n");
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);
518 ok(!ReadFile(hnp
, ibuf
, 4, &readden
, NULL
), "ReadFile 10\n");
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
);
525 ok(!ret
, "RpcReadFile 10\n");
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");
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");
541 ok(GetLastError() == ERROR_MORE_DATA
, "wrong error 10\n");
542 ok(readden
== 4, "read got %d bytes 10\n", readden
);
543 SetLastError(0xdeadbeef);
545 ok(!ReadFile(hnp
, ibuf
+ 4, 4, &readden
, NULL
), "ReadFile 10\n");
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)
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,
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");
698 static HANDLE hnp
= INVALID_HANDLE_VALUE
;
700 /** Trivial byte echo server - disconnects after each session */
701 static DWORD CALLBACK
serverThreadMain1(LPVOID arg
)
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
++) {
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");
751 /** Trivial byte echo server - closes after each connection */
752 static DWORD CALLBACK
serverThreadMain2(LPVOID arg
)
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
++) {
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 */
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");
829 /** Trivial byte echo server - uses overlapped named pipe calls */
830 static DWORD CALLBACK
serverThreadMain3(LPVOID arg
)
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 */
850 ok(hEvent
!= NULL
, "CreateEvent\n");
852 for (i
= 0; i
< NB_SERVER_LOOPS
; i
++) {
859 int letWFSOEwait
= (i
& 2);
860 int letGORwait
= (i
& 1);
863 memset(&oOverlap
, 0, sizeof(oOverlap
));
864 oOverlap
.hEvent
= hEvent
;
866 /* Wait for client to connect */
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");
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
)) {
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
)) {
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
)) {
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");
957 /** Trivial byte echo server - uses i/o completion ports */
958 static DWORD CALLBACK
serverThreadMain4(LPVOID arg
)
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
++) {
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);
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());
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
,
1029 ok(success
, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
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
,
1044 ok(success
, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
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());
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
)
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 */
1102 ok(hEvent
!= NULL
, "CreateEvent\n");
1104 for (i
= 0; i
< NB_SERVER_LOOPS
; i
++) {
1108 OVERLAPPED oOverlap
;
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;
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");
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;
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");
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");
1174 static void exercizeServer(const char *pipename
, HANDLE serverThread
)
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";
1187 for (loop
= 0; loop
< 3; loop
++) {
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
)
1195 err
= GetLastError();
1197 ok(err
== ERROR_PIPE_BUSY
|| err
== ERROR_FILE_NOT_FOUND
, "connecting to pipe\n");
1199 ok(err
== ERROR_PIPE_BUSY
, "connecting to pipe\n");
1200 trace("connect failed, retrying\n");
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");
1221 trace("exercizeServer returning\n");
1224 static void test_NamedPipe_2(void)
1226 HANDLE serverThread
;
1227 DWORD serverThreadId
;
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.
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
);
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
);
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
);
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
);
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)
1282 static const char obuf
[] = "Bit Bucket";
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");
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");
1336 static void test_CreatePipe(void)
1338 SECURITY_ATTRIBUTES pipe_attr
;
1339 HANDLE piperead
, pipewrite
;
1346 user_apc_ran
= FALSE
;
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 */
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
;
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());
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());
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());
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());
1599 struct named_pipe_client_params
1601 DWORD security_flags
;
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
;
1613 const char message
[] = "Test";
1614 DWORD bytes_read
, bytes_written
;
1616 TOKEN_PRIVILEGES
*Privileges
= NULL
;
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());
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());
1663 ret
= RevertToSelf();
1664 ok(ret
, "RevertToSelf failed with error %d\n", GetLastError());
1668 ret
= AdjustTokenPrivileges(params
->token
, TRUE
, NULL
, 0, NULL
, NULL
);
1669 ok(ret
, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
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());
1698 static HANDLE
make_impersonation_token(DWORD Access
, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
1700 HANDLE ProcessToken
;
1701 HANDLE Token
= NULL
;
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
);
1715 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken
, DWORD security_flags
, BOOL revert
, void (*test_func
)(int, HANDLE
))
1724 struct named_pipe_client_params params
;
1726 DWORD dwBytesWritten
;
1727 HANDLE hToken
= NULL
;
1728 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
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
, ¶ms
, 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
);
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
);
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());
1797 CloseHandle(hThread
);
1798 CloseHandle(hPipeServer
);
1801 static BOOL
are_all_privileges_disabled(HANDLE hToken
)
1804 TOKEN_PRIVILEGES
*Privileges
= NULL
;
1806 BOOL all_privs_disabled
= TRUE
;
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
);
1816 HeapFree(GetProcessHeap(), 0, Privileges
);
1823 for (i
= 0; i
< Privileges
->PrivilegeCount
; i
++)
1825 if (Privileges
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
1827 all_privs_disabled
= FALSE
;
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
);
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
)
1857 priv_count
= get_privilege_count(hToken
);
1859 ok(priv_count
== 0, "privilege count should have been 0 instead of %d\n", priv_count
);
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");
1867 ok(0, "shouldn't happen\n");
1871 static void test_no_sqos(int call_index
, HANDLE hToken
)
1876 ok(!are_all_privileges_disabled(hToken
), "token should be a copy of the process one\n");
1880 ok(are_all_privileges_disabled(hToken
), "impersonated token should have been modified\n");
1883 ok(0, "shouldn't happen\n");
1887 static void test_static_context(int call_index
, HANDLE hToken
)
1892 ok(!are_all_privileges_disabled(hToken
), "token should be a copy of the process one\n");
1895 ok(!are_all_privileges_disabled(hToken
), "impersonated token should not have been modified\n");
1898 ok(0, "shouldn't happen\n");
1902 static void test_dynamic_context(int call_index
, HANDLE hToken
)
1907 ok(!are_all_privileges_disabled(hToken
), "token should be a copy of the process one\n");
1911 ok(are_all_privileges_disabled(hToken
), "impersonated token should have been modified\n");
1914 ok(0, "shouldn't happen\n");
1918 static void test_dynamic_context_no_token(int call_index
, HANDLE hToken
)
1923 ok(are_all_privileges_disabled(hToken
), "token should be a copy of the process one\n");
1926 ok(!are_all_privileges_disabled(hToken
), "process token modification should have been detected and impersonation token updated\n");
1929 ok(0, "shouldn't happen\n");
1933 static void test_no_sqos_revert(int call_index
, HANDLE hToken
)
1939 priv_count
= get_privilege_count(hToken
);
1941 ok(priv_count
== 0, "privilege count should have been 0 instead of %d\n", priv_count
);
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");
1949 ok(0, "shouldn't happen\n");
1953 static void test_static_context_revert(int call_index
, HANDLE hToken
)
1959 ok(are_all_privileges_disabled(hToken
), "privileges should have been disabled\n");
1963 ok(are_all_privileges_disabled(hToken
), "impersonated token should not have been modified\n");
1966 ok(0, "shouldn't happen\n");
1970 static void test_dynamic_context_revert(int call_index
, HANDLE hToken
)
1976 ok(are_all_privileges_disabled(hToken
), "privileges should have been disabled\n");
1979 ok(!are_all_privileges_disabled(hToken
), "impersonated token should now be process token\n");
1982 ok(0, "shouldn't happen\n");
1986 static void test_impersonation(void)
1988 HANDLE hClientToken
;
1989 HANDLE hProcessToken
;
1992 if( !pDuplicateTokenEx
) {
1993 skip("DuplicateTokenEx not found\n");
1997 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hProcessToken
);
2000 skip("couldn't open process token, skipping impersonation tests\n");
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
);
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
)
2055 struct overlapped_server_args
*a
= arg
;
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
);
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
);
2100 static void test_overlapped(void)
2103 HANDLE thread
, pipe
;
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 */
2117 ret
= WriteFile(pipe
, "x", 1, &num
, NULL
);
2118 ok(ret
, "WriteFile failed with error %d\n", GetLastError());
2120 WaitForSingleObject(thread
, INFINITE
);
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
;
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
);
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
);
2184 static void test_NamedPipeHandleState(void)
2186 HANDLE server
, client
;
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());
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,
2212 SetLastError(0xdeadbeef);
2213 ret
= GetNamedPipeHandleStateA(server
, &state
, &instances
,
2214 &maxCollectionCount
, &collectDataTimeout
, userName
,
2215 sizeof(userName
) / sizeof(userName
[0]));
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());
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;
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)
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,
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
;
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";
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;
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;
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 */
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");
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
);
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);
2499 ok(wait
== WAIT_OBJECT_0
, "WaitForSingleObject returned %x\n", wait
);
2501 ok(num_bytes
== 1, "bytes %u\n", num_bytes
);
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
);
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())
2528 test_CreateNamedPipe_instances_must_match();
2530 test_CreateNamedPipe(PIPE_TYPE_BYTE
);
2531 test_CreateNamedPipe(PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);
2534 test_impersonation();
2536 test_overlapped_error();
2537 test_NamedPipeHandleState();
2538 test_GetNamedPipeInfo();
2539 test_readfileex_pending();