1 /*
2 * Unit tests for named pipe functions in Wine
3 *
4 * Copyright (c) 2002 Dan Kegel
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "winioctl.h"
30 #include "wine/test.h"
31
32 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
33 #define PIPENAME_SPECIAL "\\\\.\\PiPe\\tests->pipe.c"
34
35 #define NB_SERVER_LOOPS 8
36
37 static HANDLE alarm_event;
38 static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
39 SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
40 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
41 static BOOL (WINAPI *pCancelIoEx)(HANDLE handle, LPOVERLAPPED lpOverlapped);
42
43 static BOOL user_apc_ran;
user_apc(ULONG_PTR param)44 static void CALLBACK user_apc(ULONG_PTR param)
45 {
46 user_apc_ran = TRUE;
47 }
48
49
50 enum rpcThreadOp
51 {
52 RPC_READFILE
53 };
54
55 struct rpcThreadArgs
56 {
57 ULONG_PTR returnValue;
58 DWORD lastError;
59 enum rpcThreadOp op;
60 ULONG_PTR args[5];
61 };
62
rpcThreadMain(LPVOID arg)63 static DWORD CALLBACK rpcThreadMain(LPVOID arg)
64 {
65 struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
66 if (winetest_debug > 1) trace("rpcThreadMain starting\n");
67 SetLastError( rpcargs->lastError );
68
69 switch (rpcargs->op)
70 {
71 case RPC_READFILE:
72 rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */
73 (LPVOID)rpcargs->args[1], /* buffer */
74 (DWORD)rpcargs->args[2], /* bytesToRead */
75 (LPDWORD)rpcargs->args[3], /* bytesRead */
76 (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
77 break;
78
79 default:
80 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
81 rpcargs->returnValue = 0;
82 break;
83 }
84
85 rpcargs->lastError = GetLastError();
86 if (winetest_debug > 1) trace("rpcThreadMain returning\n");
87 return 0;
88 }
89
90 /* Runs ReadFile(...) from a different thread */
RpcReadFile(HANDLE hFile,LPVOID buffer,DWORD bytesToRead,LPDWORD bytesRead,LPOVERLAPPED overlapped)91 static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
92 {
93 struct rpcThreadArgs rpcargs;
94 HANDLE thread;
95 DWORD threadId, ret;
96
97 rpcargs.returnValue = 0;
98 rpcargs.lastError = GetLastError();
99 rpcargs.op = RPC_READFILE;
100 rpcargs.args[0] = (ULONG_PTR)hFile;
101 rpcargs.args[1] = (ULONG_PTR)buffer;
102 rpcargs.args[2] = (ULONG_PTR)bytesToRead;
103 rpcargs.args[3] = (ULONG_PTR)bytesRead;
104 rpcargs.args[4] = (ULONG_PTR)overlapped;
105
106 thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
107 ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
108 ret = WaitForSingleObject(thread, INFINITE);
109 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
110 CloseHandle(thread);
111
112 SetLastError(rpcargs.lastError);
113 return (BOOL)rpcargs.returnValue;
114 }
115
116 #define test_not_signaled(h) _test_not_signaled(__LINE__,h)
_test_not_signaled(unsigned line,HANDLE handle)117 static void _test_not_signaled(unsigned line, HANDLE handle)
118 {
119 DWORD res = WaitForSingleObject(handle, 0);
120 disable_success_count
121 ok_(__FILE__,line)(res == WAIT_TIMEOUT, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
122 }
123
124 #define test_signaled(h) _test_signaled(__LINE__,h)
_test_signaled(unsigned line,HANDLE handle)125 static void _test_signaled(unsigned line, HANDLE handle)
126 {
127 DWORD res = WaitForSingleObject(handle, 0);
128 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
129 }
130
131 #define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
_test_pipe_info(unsigned line,HANDLE pipe,DWORD ex_flags,DWORD ex_out_buf_size,DWORD ex_in_buf_size,DWORD ex_max_instances)132 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)
133 {
134 DWORD flags = 0xdeadbeef, out_buf_size = 0xdeadbeef, in_buf_size = 0xdeadbeef, max_instances = 0xdeadbeef;
135 BOOL res;
136
137 res = GetNamedPipeInfo(pipe, &flags, &out_buf_size, &in_buf_size, &max_instances);
138 ok_(__FILE__,line)(res, "GetNamedPipeInfo failed: %x\n", res);
139 ok_(__FILE__,line)(flags == ex_flags, "flags = %x, expected %x\n", flags, ex_flags);
140 ok_(__FILE__,line)(out_buf_size == ex_out_buf_size, "out_buf_size = %x, expected %u\n", out_buf_size, ex_out_buf_size);
141 ok_(__FILE__,line)(in_buf_size == ex_in_buf_size, "in_buf_size = %x, expected %u\n", in_buf_size, ex_in_buf_size);
142 ok_(__FILE__,line)(max_instances == ex_max_instances, "max_instances = %x, expected %u\n", max_instances, ex_max_instances);
143 }
144
test_CreateNamedPipe(int pipemode)145 static void test_CreateNamedPipe(int pipemode)
146 {
147 HANDLE hnp;
148 HANDLE hFile;
149 static const char obuf[] = "Bit Bucket";
150 static const char obuf2[] = "More bits";
151 char ibuf[32], *pbuf;
152 DWORD written;
153 DWORD readden;
154 DWORD avail;
155 DWORD left;
156 DWORD lpmode;
157 BOOL ret;
158
159 if (pipemode == PIPE_TYPE_BYTE)
160 trace("test_CreateNamedPipe starting in byte mode\n");
161 else
162 trace("test_CreateNamedPipe starting in message mode\n");
163
164 /* Wait for nonexistent pipe */
165 ret = WaitNamedPipeA(PIPENAME, 2000);
166 ok(ret == 0, "WaitNamedPipe returned %d for nonexistent pipe\n", ret);
167 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
168
169 /* Bad parameter checks */
170 hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
171 /* nMaxInstances */ 1,
172 /* nOutBufSize */ 1024,
173 /* nInBufSize */ 1024,
174 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
175 /* lpSecurityAttrib */ NULL);
176 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
177 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
178
179 if (pipemode == PIPE_TYPE_BYTE)
180 {
181 /* Bad parameter checks */
182 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
183 /* nMaxInstances */ 1,
184 /* nOutBufSize */ 1024,
185 /* nInBufSize */ 1024,
186 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
187 /* lpSecurityAttrib */ NULL);
188 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
189 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
190 }
191
192 hnp = CreateNamedPipeA(NULL,
193 PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
194 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
195 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
196 "CreateNamedPipe should fail if name is NULL\n");
197
198 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
199 ok(hFile == INVALID_HANDLE_VALUE
200 && GetLastError() == ERROR_FILE_NOT_FOUND,
201 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
202
203 /* Functional checks */
204
205 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
206 /* nMaxInstances */ 1,
207 /* nOutBufSize */ 1024,
208 /* nInBufSize */ 1024,
209 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
210 /* lpSecurityAttrib */ NULL);
211 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
212 test_signaled(hnp);
213
214 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
215 todo_wine
216 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%u)\n",
217 ret, GetLastError());
218
219 ret = WaitNamedPipeA(PIPENAME, 2000);
220 ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
221
222 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
223 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
224
225 ok(!WaitNamedPipeA(PIPENAME, 100), "WaitNamedPipe succeeded\n");
226
227 ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
228
229 /* Test ConnectNamedPipe() in both directions */
230 ok(!ConnectNamedPipe(hnp, NULL), "ConnectNamedPipe(server) succeeded\n");
231 ok(GetLastError() == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", GetLastError());
232 ok(!ConnectNamedPipe(hFile, NULL), "ConnectNamedPipe(client) succeeded\n");
233 ok(GetLastError() == ERROR_INVALID_FUNCTION, "expected ERROR_INVALID_FUNCTION, got %u\n", GetLastError());
234
235 /* don't try to do i/o if one side couldn't be opened, as it hangs */
236 if (hFile != INVALID_HANDLE_VALUE) {
237 HANDLE hFile2;
238
239 /* Make sure we can read and write a few bytes in both directions */
240 memset(ibuf, 0, sizeof(ibuf));
241 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
242 ok(written == sizeof(obuf), "write file len\n");
243 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
244 ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
245 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
246
247 memset(ibuf, 0, sizeof(ibuf));
248 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
249 ok(written == sizeof(obuf2), "write file len\n");
250 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
251 ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
252 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
253
254 /* Now the same again, but with an additional call to PeekNamedPipe */
255 memset(ibuf, 0, sizeof(ibuf));
256 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
257 ok(written == sizeof(obuf), "write file len 1\n");
258 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &avail, &left), "Peek\n");
259 ok(avail == sizeof(obuf), "peek 1 got %d bytes\n", avail);
260 if (pipemode == PIPE_TYPE_BYTE)
261 ok(left == 0, "peek 1 got %d bytes left\n", left);
262 else
263 ok(left == sizeof(obuf), "peek 1 got %d bytes left\n", left);
264 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
265 ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
266 ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
267
268 memset(ibuf, 0, sizeof(ibuf));
269 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
270 ok(written == sizeof(obuf2), "write file len 2\n");
271 ok(PeekNamedPipe(hnp, NULL, 0, NULL, &avail, &left), "Peek\n");
272 ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
273 if (pipemode == PIPE_TYPE_BYTE)
274 ok(left == 0, "peek 2 got %d bytes left\n", left);
275 else
276 ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
277 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &avail, &left), "Peek\n");
278 ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
279 if (pipemode == PIPE_TYPE_BYTE)
280 ok(left == 0, "peek 2 got %d bytes left\n", left);
281 else
282 ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
283 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
284 ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
285 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
286
287 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
288 memset(ibuf, 0, sizeof(ibuf));
289 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
290 ok(written == sizeof(obuf2), "write file len\n");
291 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek\n");
292 ok(readden == 4, "peek got %d bytes\n", readden);
293 ok(avail == sizeof(obuf2), "peek got %d bytes available\n", avail);
294 if (pipemode == PIPE_TYPE_BYTE)
295 ok(left == -4, "peek got %d bytes left\n", left);
296 else
297 ok(left == sizeof(obuf2)-4, "peek got %d bytes left\n", left);
298 ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
299 ok(readden == 4, "read got %d bytes\n", readden);
300 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
301 ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
302 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
303
304 memset(ibuf, 0, sizeof(ibuf));
305 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
306 ok(written == sizeof(obuf), "write file len\n");
307 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek\n");
308 ok(readden == 4, "peek got %d bytes\n", readden);
309 ok(avail == sizeof(obuf), "peek got %d bytes available\n", avail);
310 if (pipemode == PIPE_TYPE_BYTE)
311 {
312 ok(left == -4, "peek got %d bytes left\n", left);
313 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
314 }
315 else
316 {
317 ok(left == sizeof(obuf)-4, "peek got %d bytes left\n", left);
318 SetLastError(0xdeadbeef);
319 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
320 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
321 }
322 ok(readden == 4, "read got %d bytes\n", readden);
323 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
324 ok(readden == sizeof(obuf) - 4, "read got %d bytes\n", readden);
325 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
326
327 /* Similar to above, but use a read buffer size small enough to read in three parts */
328 memset(ibuf, 0, sizeof(ibuf));
329 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
330 ok(written == sizeof(obuf2), "write file len\n");
331 if (pipemode == PIPE_TYPE_BYTE)
332 {
333 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
334 ok(readden == 4, "read got %d bytes\n", readden);
335 ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
336 }
337 else
338 {
339 SetLastError(0xdeadbeef);
340 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
341 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
342 ok(readden == 4, "read got %d bytes\n", readden);
343 SetLastError(0xdeadbeef);
344 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
345 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
346 }
347 ok(readden == 4, "read got %d bytes\n", readden);
348 ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n");
349 ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden);
350 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
351
352 /* Test reading of multiple writes */
353 memset(ibuf, 0, sizeof(ibuf));
354 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
355 ok(written == sizeof(obuf), "write file len 3a\n");
356 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
357 ok(written == sizeof(obuf2), "write file len 3b\n");
358 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek3\n");
359 ok(readden == 4, "peek3 got %d bytes\n", readden);
360 if (pipemode == PIPE_TYPE_BYTE)
361 ok(left == -4, "peek3 got %d bytes left\n", left);
362 else
363 ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
364 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
365 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek3\n");
366 if (pipemode == PIPE_TYPE_BYTE) {
367 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
368 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek3 got %d bytes left\n", left);
369 }
370 else
371 {
372 ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
373 ok(left == 0, "peek3 got %d bytes left\n", left);
374 }
375 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
376 pbuf = ibuf;
377 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
378 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
379 pbuf += sizeof(obuf);
380 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
381 }
382 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
383 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
384 pbuf = ibuf;
385 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
386 pbuf += sizeof(obuf);
387 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
388
389 /* Multiple writes in the reverse direction */
390 memset(ibuf, 0, sizeof(ibuf));
391 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
392 ok(written == sizeof(obuf), "write file len 4a\n");
393 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
394 ok(written == sizeof(obuf2), "write file len 4b\n");
395 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek3\n");
396 ok(readden == 4, "peek3 got %d bytes\n", readden);
397 if (pipemode == PIPE_TYPE_BYTE)
398 ok(left == -4, "peek3 got %d bytes left\n", left);
399 else
400 ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
401 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
402 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek4\n");
403 if (pipemode == PIPE_TYPE_BYTE) {
404 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
405 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek4 got %d bytes left\n", left);
406 }
407 else
408 {
409 ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
410 ok(left == 0, "peek4 got %d bytes left\n", left);
411 }
412 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
413 pbuf = ibuf;
414 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
415 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
416 pbuf += sizeof(obuf);
417 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
418 }
419 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
420 if (pipemode == PIPE_TYPE_BYTE) {
421 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
422 }
423 else {
424 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
425 }
426 pbuf = ibuf;
427 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
428 if (pipemode == PIPE_TYPE_BYTE) {
429 pbuf += sizeof(obuf);
430 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
431 }
432
433 /* Test reading of multiple writes after a mode change
434 (CreateFile always creates a byte mode pipe) */
435 lpmode = PIPE_READMODE_MESSAGE;
436 if (pipemode == PIPE_TYPE_BYTE) {
437 /* trying to change the client end of a byte pipe to message mode should fail */
438 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
439 }
440 else {
441 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
442
443 memset(ibuf, 0, sizeof(ibuf));
444 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
445 ok(written == sizeof(obuf), "write file len 3a\n");
446 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
447 ok(written == sizeof(obuf2), "write file len 3b\n");
448 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek5\n");
449 ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
450 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
451 ok(left == 0, "peek5 got %d bytes left\n", left);
452 pbuf = ibuf;
453 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
454 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
455 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
456 pbuf = ibuf;
457 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
458 if (readden <= sizeof(obuf))
459 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
460
461 /* Multiple writes in the reverse direction */
462 /* the write of obuf2 from write4 should still be in the buffer */
463 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
464 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
465 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
466 if (avail > 0) {
467 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
468 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
469 pbuf = ibuf;
470 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
471 }
472 memset(ibuf, 0, sizeof(ibuf));
473 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
474 ok(written == sizeof(obuf), "write file len 6a\n");
475 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
476 ok(written == sizeof(obuf2), "write file len 6b\n");
477 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
478 ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
479
480 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
481 pbuf = ibuf;
482 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
483 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
484 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
485 pbuf = ibuf;
486 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
487 if (readden <= sizeof(obuf))
488 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
489
490 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
491 memset(ibuf, 0, sizeof(ibuf));
492 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
493 ok(written == sizeof(obuf2), "write file len 7\n");
494 SetLastError(0xdeadbeef);
495 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
496 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
497 ok(readden == 4, "read got %d bytes 7\n", readden);
498 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
499 ok(readden == sizeof(obuf2) - 4, "read got %d bytes 7\n", readden);
500 ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n");
501
502 memset(ibuf, 0, sizeof(ibuf));
503 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
504 ok(written == sizeof(obuf), "write file len 8\n");
505 SetLastError(0xdeadbeef);
506 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
507 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
508 ok(readden == 4, "read got %d bytes 8\n", readden);
509 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
510 ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden);
511 ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
512
513 /* The following test shows that when doing a partial read of a message, the rest
514 * is still in the pipe, and can be received from a second thread. This shows
515 * especially that the content is _not_ stored in thread-local-storage until it is
516 * completely transmitted. The same method works even across multiple processes. */
517 memset(ibuf, 0, sizeof(ibuf));
518 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
519 ok(written == sizeof(obuf), "write file len 9\n");
520 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
521 ok(written == sizeof(obuf2), "write file len 9\n");
522 SetLastError(0xdeadbeef);
523 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
524 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
525 ok(readden == 4, "read got %d bytes 9\n", readden);
526 SetLastError(0xdeadbeef);
527 ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
528 ok(!ret, "RpcReadFile 9\n");
529 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
530 ok(readden == 4, "read got %d bytes 9\n", readden);
531 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
532 ok(ret, "RpcReadFile 9\n");
533 ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
534 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
535 if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
536 {
537 memset(ibuf, 0, sizeof(ibuf));
538 SetLastError(0xdeadbeef);
539 ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
540 ok(!ret, "RpcReadFile 9\n");
541 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
542 ok(readden == 4, "read got %d bytes 9\n", readden);
543 SetLastError(0xdeadbeef);
544 ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
545 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
546 ok(readden == 4, "read got %d bytes 9\n", readden);
547 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
548 ok(ret, "RpcReadFile 9\n");
549 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
550 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
551 }
552
553 /* Now the reverse direction */
554 memset(ibuf, 0, sizeof(ibuf));
555 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
556 ok(written == sizeof(obuf2), "write file len 10\n");
557 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
558 ok(written == sizeof(obuf), "write file len 10\n");
559 SetLastError(0xdeadbeef);
560 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
561 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
562 ok(readden == 4, "read got %d bytes 10\n", readden);
563 SetLastError(0xdeadbeef);
564 ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
565 ok(!ret, "RpcReadFile 10\n");
566 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
567 ok(readden == 4, "read got %d bytes 10\n", readden);
568 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
569 ok(ret, "RpcReadFile 10\n");
570 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
571 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
572 if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
573 {
574 memset(ibuf, 0, sizeof(ibuf));
575 SetLastError(0xdeadbeef);
576 ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
577 ok(!ret, "RpcReadFile 10\n");
578 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
579 ok(readden == 4, "read got %d bytes 10\n", readden);
580 SetLastError(0xdeadbeef);
581 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
582 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
583 ok(readden == 4, "read got %d bytes 10\n", readden);
584 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
585 ok(ret, "RpcReadFile 10\n");
586 ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
587 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
588 }
589
590 }
591
592 /* Picky conformance tests */
593
594 /* Verify that you can't connect to pipe again
595 * until server calls DisconnectNamedPipe+ConnectNamedPipe
596 * or creates a new pipe
597 * case 1: other client not yet closed
598 */
599 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
600 ok(hFile2 == INVALID_HANDLE_VALUE,
601 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
602 ok(GetLastError() == ERROR_PIPE_BUSY,
603 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
604
605 ok(CloseHandle(hFile), "CloseHandle\n");
606
607 /* case 2: other client already closed */
608 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
609 ok(hFile == INVALID_HANDLE_VALUE,
610 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
611 ok(GetLastError() == ERROR_PIPE_BUSY,
612 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
613
614 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
615
616 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
617 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
618 ok(hFile == INVALID_HANDLE_VALUE,
619 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
620 ok(GetLastError() == ERROR_PIPE_BUSY,
621 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
622
623 /* to be complete, we'd call ConnectNamedPipe here and loop,
624 * but by default that's blocking, so we'd either have
625 * to turn on the uncommon nonblocking mode, or
626 * use another thread.
627 */
628 }
629
630 ok(CloseHandle(hnp), "CloseHandle\n");
631
632 hnp = CreateNamedPipeA(PIPENAME_SPECIAL, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
633 /* nMaxInstances */ 1,
634 /* nOutBufSize */ 1024,
635 /* nInBufSize */ 1024,
636 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
637 /* lpSecurityAttrib */ NULL);
638 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe with special characters failed\n");
639 ok(CloseHandle(hnp), "CloseHandle\n");
640
641 if (winetest_debug > 1) trace("test_CreateNamedPipe returning\n");
642 }
643
test_CreateNamedPipe_instances_must_match(void)644 static void test_CreateNamedPipe_instances_must_match(void)
645 {
646 HANDLE hnp, hnp2;
647
648 /* Check no mismatch */
649 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
650 /* nMaxInstances */ 2,
651 /* nOutBufSize */ 1024,
652 /* nInBufSize */ 1024,
653 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
654 /* lpSecurityAttrib */ NULL);
655 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
656
657 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
658 /* nMaxInstances */ 2,
659 /* nOutBufSize */ 1024,
660 /* nInBufSize */ 1024,
661 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
662 /* lpSecurityAttrib */ NULL);
663 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
664
665 ok(CloseHandle(hnp), "CloseHandle\n");
666 ok(CloseHandle(hnp2), "CloseHandle\n");
667
668 /* Check nMaxInstances */
669 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
670 /* nMaxInstances */ 1,
671 /* nOutBufSize */ 1024,
672 /* nInBufSize */ 1024,
673 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
674 /* lpSecurityAttrib */ NULL);
675 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
676
677 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
678 /* nMaxInstances */ 1,
679 /* nOutBufSize */ 1024,
680 /* nInBufSize */ 1024,
681 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
682 /* lpSecurityAttrib */ NULL);
683 ok(hnp2 == INVALID_HANDLE_VALUE
684 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
685
686 ok(CloseHandle(hnp), "CloseHandle\n");
687
688 /* Check PIPE_ACCESS_* */
689 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
690 /* nMaxInstances */ 2,
691 /* nOutBufSize */ 1024,
692 /* nInBufSize */ 1024,
693 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
694 /* lpSecurityAttrib */ NULL);
695 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
696
697 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
698 /* nMaxInstances */ 2,
699 /* nOutBufSize */ 1024,
700 /* nInBufSize */ 1024,
701 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
702 /* lpSecurityAttrib */ NULL);
703 ok(hnp2 == INVALID_HANDLE_VALUE
704 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
705
706 ok(CloseHandle(hnp), "CloseHandle\n");
707
708 /* check everything else */
709 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
710 /* nMaxInstances */ 4,
711 /* nOutBufSize */ 1024,
712 /* nInBufSize */ 1024,
713 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
714 /* lpSecurityAttrib */ NULL);
715 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
716
717 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
718 /* nMaxInstances */ 3,
719 /* nOutBufSize */ 102,
720 /* nInBufSize */ 24,
721 /* nDefaultWait */ 1234,
722 /* lpSecurityAttrib */ NULL);
723 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
724
725 ok(CloseHandle(hnp), "CloseHandle\n");
726 ok(CloseHandle(hnp2), "CloseHandle\n");
727 }
728
test_ReadFile(void)729 static void test_ReadFile(void)
730 {
731 HANDLE server, client;
732 OVERLAPPED overlapped;
733 DWORD size;
734 BOOL res;
735
736 static char buf[512];
737
738 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
739 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
740 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
741 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
742
743 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
744 OPEN_EXISTING, 0, 0);
745 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
746
747 ok(WriteFile(client, buf, sizeof(buf), &size, NULL), "WriteFile\n");
748
749 res = ReadFile(server, buf, 1, &size, NULL);
750 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%u)\n", res, GetLastError());
751 ok(size == 1, "size = %u\n", size);
752
753 /* pass both overlapped and ret read */
754 memset(&overlapped, 0, sizeof(overlapped));
755 res = ReadFile(server, buf, 1, &size, &overlapped);
756 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%u)\n", res, GetLastError());
757 ok(size == 0, "size = %u\n", size);
758 ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "Internal = %lx\n", overlapped.Internal);
759 ok(overlapped.InternalHigh == 1, "InternalHigh = %lx\n", overlapped.InternalHigh);
760
761 DisconnectNamedPipe(server);
762
763 memset(&overlapped, 0, sizeof(overlapped));
764 overlapped.InternalHigh = 0xdeadbeef;
765 res = ReadFile(server, buf, 1, &size, &overlapped);
766 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%u)\n", res, GetLastError());
767 ok(size == 0, "size = %u\n", size);
768 ok(overlapped.Internal == STATUS_PENDING, "Internal = %lx\n", overlapped.Internal);
769 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %lx\n", overlapped.InternalHigh);
770
771 memset(&overlapped, 0, sizeof(overlapped));
772 overlapped.InternalHigh = 0xdeadbeef;
773 res = WriteFile(server, buf, 1, &size, &overlapped);
774 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%u)\n", res, GetLastError());
775 ok(size == 0, "size = %u\n", size);
776 ok(overlapped.Internal == STATUS_PENDING, "Internal = %lx\n", overlapped.Internal);
777 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %lx\n", overlapped.InternalHigh);
778
779 CloseHandle(server);
780 CloseHandle(client);
781 }
782
783 /** implementation of alarm() */
alarmThreadMain(LPVOID arg)784 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
785 {
786 DWORD_PTR timeout = (DWORD_PTR) arg;
787 if (winetest_debug > 1) trace("alarmThreadMain\n");
788 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
789 {
790 ok(FALSE, "alarm\n");
791 ExitProcess(1);
792 }
793 return 1;
794 }
795
796 static HANDLE hnp = INVALID_HANDLE_VALUE;
797
798 /** Trivial byte echo server - disconnects after each session */
serverThreadMain1(LPVOID arg)799 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
800 {
801 int i;
802
803 if (winetest_debug > 1) trace("serverThreadMain1 start\n");
804 /* Set up a simple echo server */
805 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
806 PIPE_TYPE_BYTE | PIPE_WAIT,
807 /* nMaxInstances */ 1,
808 /* nOutBufSize */ 1024,
809 /* nInBufSize */ 1024,
810 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
811 /* lpSecurityAttrib */ NULL);
812
813 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
814 for (i = 0; i < NB_SERVER_LOOPS; i++) {
815 char buf[512];
816 DWORD written;
817 DWORD readden;
818 BOOL success;
819
820 /* Wait for client to connect */
821 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
822 ok(ConnectNamedPipe(hnp, NULL)
823 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
824 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
825
826 /* Echo bytes once */
827 memset(buf, 0, sizeof(buf));
828
829 if (winetest_debug > 1) trace("Server reading...\n");
830 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
831 if (winetest_debug > 1) trace("Server done reading.\n");
832 ok(success, "ReadFile\n");
833 ok(readden, "short read\n");
834
835 if (winetest_debug > 1) trace("Server writing...\n");
836 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
837 if (winetest_debug > 1) trace("Server done writing.\n");
838 ok(written == readden, "write file len\n");
839
840 /* finish this connection, wait for next one */
841 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
842 if (winetest_debug > 1) trace("Server done flushing.\n");
843 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
844 if (winetest_debug > 1) trace("Server done disconnecting.\n");
845 }
846 return 0;
847 }
848
849 /** Trivial byte echo server - closes after each connection */
serverThreadMain2(LPVOID arg)850 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
851 {
852 int i;
853 HANDLE hnpNext = 0;
854
855 trace("serverThreadMain2\n");
856 /* Set up a simple echo server */
857 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
858 PIPE_TYPE_BYTE | PIPE_WAIT,
859 /* nMaxInstances */ 2,
860 /* nOutBufSize */ 1024,
861 /* nInBufSize */ 1024,
862 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
863 /* lpSecurityAttrib */ NULL);
864 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
865
866 for (i = 0; i < NB_SERVER_LOOPS; i++) {
867 char buf[512];
868 DWORD written;
869 DWORD readden;
870 DWORD ret;
871 BOOL success;
872
873
874 user_apc_ran = FALSE;
875 if (i == 0 && pQueueUserAPC) {
876 if (winetest_debug > 1) trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
877 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
878 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
879 }
880
881 /* Wait for client to connect */
882 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
883 ok(ConnectNamedPipe(hnp, NULL)
884 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
885 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
886
887 /* Echo bytes once */
888 memset(buf, 0, sizeof(buf));
889
890 if (winetest_debug > 1) trace("Server reading...\n");
891 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
892 if (winetest_debug > 1) trace("Server done reading.\n");
893 ok(success, "ReadFile\n");
894
895 if (winetest_debug > 1) trace("Server writing...\n");
896 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
897 if (winetest_debug > 1) trace("Server done writing.\n");
898 ok(written == readden, "write file len\n");
899
900 /* finish this connection, wait for next one */
901 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
902 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
903
904 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
905
906 if (i == 0 && pQueueUserAPC)
907 SleepEx(0, TRUE); /* get rid of apc */
908
909 /* Set up next echo server */
910 hnpNext =
911 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
912 PIPE_TYPE_BYTE | PIPE_WAIT,
913 /* nMaxInstances */ 2,
914 /* nOutBufSize */ 1024,
915 /* nInBufSize */ 1024,
916 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
917 /* lpSecurityAttrib */ NULL);
918
919 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
920
921 ok(CloseHandle(hnp), "CloseHandle\n");
922 hnp = hnpNext;
923 }
924 return 0;
925 }
926
927 /** Trivial byte echo server - uses overlapped named pipe calls */
serverThreadMain3(LPVOID arg)928 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
929 {
930 int i;
931 HANDLE hEvent;
932
933 if (winetest_debug > 1) trace("serverThreadMain3\n");
934 /* Set up a simple echo server */
935 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
936 PIPE_TYPE_BYTE | PIPE_WAIT,
937 /* nMaxInstances */ 1,
938 /* nOutBufSize */ 1024,
939 /* nInBufSize */ 1024,
940 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
941 /* lpSecurityAttrib */ NULL);
942 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
943
944 hEvent = CreateEventW(NULL, /* security attribute */
945 TRUE, /* manual reset event */
946 FALSE, /* initial state */
947 NULL); /* name */
948 ok(hEvent != NULL, "CreateEvent\n");
949
950 for (i = 0; i < NB_SERVER_LOOPS; i++) {
951 char buf[512];
952 DWORD written;
953 DWORD readden;
954 DWORD dummy;
955 BOOL success;
956 OVERLAPPED oOverlap;
957 int letWFSOEwait = (i & 2);
958 int letGORwait = (i & 1);
959 DWORD err;
960
961 memset(&oOverlap, 0, sizeof(oOverlap));
962 oOverlap.hEvent = hEvent;
963
964 /* Wait for client to connect */
965 if (i == 0) {
966 if (winetest_debug > 1) trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
967 success = ConnectNamedPipe(hnp, NULL);
968 err = GetLastError();
969 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
970 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
971 } else {
972 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
973 success = ConnectNamedPipe(hnp, &oOverlap);
974 err = GetLastError();
975 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
976 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe returned.\n");
977 if (!success && (err == ERROR_IO_PENDING)) {
978 if (letWFSOEwait)
979 {
980 DWORD ret;
981 do {
982 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
983 } while (ret == WAIT_IO_COMPLETION);
984 ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
985 }
986 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
987 if (!letGORwait && !letWFSOEwait && !success) {
988 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
989 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
990 }
991 }
992 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
993 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
994 }
995
996 /* Echo bytes once */
997 memset(buf, 0, sizeof(buf));
998
999 if (winetest_debug > 1) trace("Server reading...\n");
1000 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
1001 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1002 err = GetLastError();
1003 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
1004 if (winetest_debug > 1) trace("overlapped ReadFile returned.\n");
1005 if (!success && (err == ERROR_IO_PENDING)) {
1006 if (letWFSOEwait)
1007 {
1008 DWORD ret;
1009 do {
1010 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1011 } while (ret == WAIT_IO_COMPLETION);
1012 ok(ret == 0, "wait ReadFile returned %x\n", ret);
1013 }
1014 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
1015 if (!letGORwait && !letWFSOEwait && !success) {
1016 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1017 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
1018 }
1019 }
1020 if (winetest_debug > 1) trace("Server done reading.\n");
1021 ok(success, "overlapped ReadFile\n");
1022
1023 if (winetest_debug > 1) trace("Server writing...\n");
1024 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
1025 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1026 err = GetLastError();
1027 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
1028 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1029 if (!success && (err == ERROR_IO_PENDING)) {
1030 if (letWFSOEwait)
1031 {
1032 DWORD ret;
1033 do {
1034 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1035 } while (ret == WAIT_IO_COMPLETION);
1036 ok(ret == 0, "wait WriteFile returned %x\n", ret);
1037 }
1038 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
1039 if (!letGORwait && !letWFSOEwait && !success) {
1040 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1041 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
1042 }
1043 }
1044 if (winetest_debug > 1) trace("Server done writing.\n");
1045 ok(success, "overlapped WriteFile\n");
1046 ok(written == readden, "write file len\n");
1047
1048 /* finish this connection, wait for next one */
1049 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1050 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1051 }
1052 return 0;
1053 }
1054
1055 /** Trivial byte echo server - uses i/o completion ports */
serverThreadMain4(LPVOID arg)1056 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
1057 {
1058 int i;
1059 HANDLE hcompletion;
1060 BOOL ret;
1061
1062 if (winetest_debug > 1) trace("serverThreadMain4\n");
1063 /* Set up a simple echo server */
1064 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1065 PIPE_TYPE_BYTE | PIPE_WAIT,
1066 /* nMaxInstances */ 1,
1067 /* nOutBufSize */ 1024,
1068 /* nInBufSize */ 1024,
1069 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1070 /* lpSecurityAttrib */ NULL);
1071 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1072
1073 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
1074 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
1075
1076 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1077 char buf[512];
1078 DWORD written;
1079 DWORD readden;
1080 DWORD dummy;
1081 BOOL success;
1082 OVERLAPPED oConnect;
1083 OVERLAPPED oRead;
1084 OVERLAPPED oWrite;
1085 OVERLAPPED *oResult;
1086 DWORD err;
1087 ULONG_PTR compkey;
1088
1089 memset(&oConnect, 0, sizeof(oConnect));
1090 memset(&oRead, 0, sizeof(oRead));
1091 memset(&oWrite, 0, sizeof(oWrite));
1092
1093 /* Wait for client to connect */
1094 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1095 success = ConnectNamedPipe(hnp, &oConnect);
1096 err = GetLastError();
1097 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
1098 "overlapped ConnectNamedPipe got %u err %u\n", success, err );
1099 if (!success && err == ERROR_IO_PENDING) {
1100 if (winetest_debug > 1) trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
1101 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
1102 if (!success)
1103 {
1104 ok( GetLastError() == WAIT_TIMEOUT,
1105 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
1106 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
1107 }
1108 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1109 if (success)
1110 {
1111 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1112 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
1113 }
1114 }
1115 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
1116
1117 /* Echo bytes once */
1118 memset(buf, 0, sizeof(buf));
1119
1120 if (winetest_debug > 1) trace("Server reading...\n");
1121 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1122 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1123 err = GetLastError();
1124 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
1125 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1126 &oResult, 10000);
1127 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1128 if (success)
1129 {
1130 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1131 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
1132 }
1133 if (winetest_debug > 1) trace("Server done reading.\n");
1134
1135 if (winetest_debug > 1) trace("Server writing...\n");
1136 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1137 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1138 err = GetLastError();
1139 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
1140 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1141 &oResult, 10000);
1142 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1143 if (success)
1144 {
1145 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1146 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
1147 ok(written == readden, "write file len\n");
1148 }
1149 if (winetest_debug > 1) trace("Server done writing.\n");
1150
1151 /* Client will finish this connection, the following ops will trigger broken pipe errors. */
1152
1153 /* Wait for the pipe to break. */
1154 while (PeekNamedPipe(hnp, NULL, 0, NULL, &written, &written));
1155
1156 if (winetest_debug > 1) trace("Server writing on disconnected pipe...\n");
1157 SetLastError(ERROR_SUCCESS);
1158 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1159 err = GetLastError();
1160 todo_wine_if (!success && err == ERROR_PIPE_NOT_CONNECTED) ok(!success && err == ERROR_NO_DATA,
1161 "overlapped WriteFile on disconnected pipe returned %u, err=%i\n", success, err);
1162
1163 /* No completion status is queued on immediate error. */
1164 SetLastError(ERROR_SUCCESS);
1165 oResult = (OVERLAPPED *)0xdeadbeef;
1166 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1167 &oResult, 0);
1168 err = GetLastError();
1169 ok(!success && err == WAIT_TIMEOUT && !oResult,
1170 "WriteFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p\n",
1171 success, err, oResult);
1172
1173 if (winetest_debug > 1) trace("Server reading from disconnected pipe...\n");
1174 SetLastError(ERROR_SUCCESS);
1175 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1176 if (winetest_debug > 1) trace("Server ReadFile from disconnected pipe returned...\n");
1177 err = GetLastError();
1178 ok(!success && err == ERROR_BROKEN_PIPE,
1179 "overlapped ReadFile on disconnected pipe returned %u, err=%i\n", success, err);
1180
1181 SetLastError(ERROR_SUCCESS);
1182 oResult = (OVERLAPPED *)0xdeadbeef;
1183 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1184 &oResult, 0);
1185 err = GetLastError();
1186 ok(!success && err == WAIT_TIMEOUT && !oResult,
1187 "ReadFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p\n",
1188 success, err, oResult);
1189
1190 /* finish this connection, wait for next one */
1191 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1192 success = DisconnectNamedPipe(hnp);
1193 ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
1194 }
1195
1196 ret = CloseHandle(hnp);
1197 ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
1198 ret = CloseHandle(hcompletion);
1199 ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
1200
1201 return 0;
1202 }
1203
1204 static int completion_called;
1205 static DWORD completion_errorcode;
1206 static DWORD completion_num_bytes;
1207 static LPOVERLAPPED completion_lpoverlapped;
1208
completion_routine(DWORD errorcode,DWORD num_bytes,LPOVERLAPPED lpoverlapped)1209 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
1210 {
1211 completion_called++;
1212 completion_errorcode = errorcode;
1213 completion_num_bytes = num_bytes;
1214 completion_lpoverlapped = lpoverlapped;
1215 SetEvent(lpoverlapped->hEvent);
1216 }
1217
1218 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
serverThreadMain5(LPVOID arg)1219 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
1220 {
1221 int i;
1222 HANDLE hEvent;
1223
1224 if (winetest_debug > 1) trace("serverThreadMain5\n");
1225 /* Set up a simple echo server */
1226 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1227 PIPE_TYPE_BYTE | PIPE_WAIT,
1228 /* nMaxInstances */ 1,
1229 /* nOutBufSize */ 1024,
1230 /* nInBufSize */ 1024,
1231 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1232 /* lpSecurityAttrib */ NULL);
1233 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1234
1235 hEvent = CreateEventW(NULL, /* security attribute */
1236 TRUE, /* manual reset event */
1237 FALSE, /* initial state */
1238 NULL); /* name */
1239 ok(hEvent != NULL, "CreateEvent\n");
1240
1241 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1242 char buf[512];
1243 DWORD readden;
1244 BOOL success;
1245 OVERLAPPED oOverlap;
1246 DWORD err;
1247
1248 memset(&oOverlap, 0, sizeof(oOverlap));
1249 oOverlap.hEvent = hEvent;
1250
1251 /* Wait for client to connect */
1252 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
1253 success = ConnectNamedPipe(hnp, NULL);
1254 err = GetLastError();
1255 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
1256 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1257
1258 /* Echo bytes once */
1259 memset(buf, 0, sizeof(buf));
1260
1261 if (winetest_debug > 1) trace("Server reading...\n");
1262 completion_called = 0;
1263 ResetEvent(hEvent);
1264 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
1265 if (winetest_debug > 1) trace("Server ReadFileEx returned...\n");
1266 ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
1267 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1268 if (winetest_debug > 1) trace("ReadFileEx returned.\n");
1269 if (success) {
1270 DWORD ret;
1271 do {
1272 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1273 } while (ret == WAIT_IO_COMPLETION);
1274 ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
1275 }
1276 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1277 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1278 ok(completion_num_bytes != 0, "read 0 bytes\n");
1279 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1280 readden = completion_num_bytes;
1281 if (winetest_debug > 1) trace("Server done reading.\n");
1282
1283 if (winetest_debug > 1) trace("Server writing...\n");
1284 completion_called = 0;
1285 ResetEvent(hEvent);
1286 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
1287 if (winetest_debug > 1) trace("Server WriteFileEx returned...\n");
1288 ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
1289 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1290 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1291 if (success) {
1292 DWORD ret;
1293 do {
1294 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1295 } while (ret == WAIT_IO_COMPLETION);
1296 ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
1297 }
1298 if (winetest_debug > 1) trace("Server done writing.\n");
1299 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1300 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1301 ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
1302 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1303
1304 /* finish this connection, wait for next one */
1305 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1306 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1307 }
1308 return 0;
1309 }
1310
exercizeServer(const char * pipename,HANDLE serverThread)1311 static void exercizeServer(const char *pipename, HANDLE serverThread)
1312 {
1313 int i;
1314
1315 if (winetest_debug > 1) trace("exercizeServer starting\n");
1316 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1317 HANDLE hFile=INVALID_HANDLE_VALUE;
1318 static const char obuf[] = "Bit Bucket";
1319 char ibuf[32];
1320 DWORD written;
1321 DWORD readden;
1322 int loop;
1323
1324 for (loop = 0; loop < 3; loop++) {
1325 DWORD err;
1326 if (winetest_debug > 1) trace("Client connecting...\n");
1327 /* Connect to the server */
1328 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
1329 NULL, OPEN_EXISTING, 0, 0);
1330 if (hFile != INVALID_HANDLE_VALUE)
1331 break;
1332 err = GetLastError();
1333 if (loop == 0)
1334 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
1335 else
1336 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
1337 if (winetest_debug > 1) trace("connect failed, retrying\n");
1338 Sleep(200);
1339 }
1340 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
1341
1342 /* Make sure it can echo */
1343 memset(ibuf, 0, sizeof(ibuf));
1344 if (winetest_debug > 1) trace("Client writing...\n");
1345 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1346 ok(written == sizeof(obuf), "write file len\n");
1347 if (winetest_debug > 1) trace("Client reading...\n");
1348 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1349 ok(readden == sizeof(obuf), "read file len\n");
1350 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1351
1352 if (winetest_debug > 1) trace("Client closing...\n");
1353 ok(CloseHandle(hFile), "CloseHandle\n");
1354 }
1355
1356 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1357 CloseHandle(hnp);
1358 if (winetest_debug > 1) trace("exercizeServer returning\n");
1359 }
1360
test_NamedPipe_2(void)1361 static void test_NamedPipe_2(void)
1362 {
1363 HANDLE serverThread;
1364 DWORD serverThreadId;
1365 HANDLE alarmThread;
1366 DWORD alarmThreadId;
1367
1368 trace("test_NamedPipe_2 starting\n");
1369 /* Set up a twenty second timeout */
1370 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1371 SetLastError(0xdeadbeef);
1372 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1373 ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
1374
1375 /* The servers we're about to exercise do try to clean up carefully,
1376 * but to reduce the chance of a test failure due to a pipe handle
1377 * leak in the test code, we'll use a different pipe name for each server.
1378 */
1379
1380 /* Try server #1 */
1381 SetLastError(0xdeadbeef);
1382 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1383 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1384 exercizeServer(PIPENAME "serverThreadMain1", serverThread);
1385
1386 /* Try server #2 */
1387 SetLastError(0xdeadbeef);
1388 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1389 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1390 exercizeServer(PIPENAME "serverThreadMain2", serverThread);
1391
1392 /* Try server #3 */
1393 SetLastError(0xdeadbeef);
1394 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1395 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1396 exercizeServer(PIPENAME "serverThreadMain3", serverThread);
1397
1398 /* Try server #4 */
1399 SetLastError(0xdeadbeef);
1400 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1401 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1402 exercizeServer(PIPENAME "serverThreadMain4", serverThread);
1403
1404 /* Try server #5 */
1405 SetLastError(0xdeadbeef);
1406 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1407 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1408 exercizeServer(PIPENAME "serverThreadMain5", serverThread);
1409
1410 ok(SetEvent( alarm_event ), "SetEvent\n");
1411 CloseHandle( alarm_event );
1412 if (winetest_debug > 1) trace("test_NamedPipe_2 returning\n");
1413 }
1414
test_DisconnectNamedPipe(void)1415 static int test_DisconnectNamedPipe(void)
1416 {
1417 HANDLE hnp;
1418 HANDLE hFile;
1419 static const char obuf[] = "Bit Bucket";
1420 char ibuf[32];
1421 DWORD written;
1422 DWORD readden;
1423 DWORD ret;
1424
1425 SetLastError(0xdeadbeef);
1426 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1427 /* nMaxInstances */ 1,
1428 /* nOutBufSize */ 1024,
1429 /* nInBufSize */ 1024,
1430 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1431 /* lpSecurityAttrib */ NULL);
1432 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1433 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1434
1435 win_skip("Named pipes are not implemented\n");
1436 return 1;
1437 }
1438
1439 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1440 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1441 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1442 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1443
1444 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1445 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1446
1447 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1448 if (hFile != INVALID_HANDLE_VALUE) {
1449
1450 /* see what happens if server calls DisconnectNamedPipe
1451 * when there are bytes in the pipe
1452 */
1453
1454 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1455 ok(written == sizeof(obuf), "write file len\n");
1456 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1457 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1458 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1459 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1460 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1461 "ReadFile from disconnected pipe with bytes waiting\n");
1462
1463 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1464 "DisconnectNamedPipe worked twice\n");
1465 ret = WaitForSingleObject(hFile, 0);
1466 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1467
1468 ret = PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL);
1469 todo_wine
1470 ok(!ret && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "PeekNamedPipe returned %x (%u)\n",
1471 ret, GetLastError());
1472 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
1473 todo_wine
1474 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%u)\n",
1475 ret, GetLastError());
1476 ok(CloseHandle(hFile), "CloseHandle\n");
1477 }
1478
1479 ok(CloseHandle(hnp), "CloseHandle\n");
1480
1481 return 0;
1482 }
test_CreatePipe(void)1483 static void test_CreatePipe(void)
1484 {
1485 SECURITY_ATTRIBUTES pipe_attr;
1486 HANDLE piperead, pipewrite;
1487 DWORD written;
1488 DWORD read;
1489 DWORD i, size;
1490 BYTE *buffer;
1491 char readbuf[32];
1492
1493 user_apc_ran = FALSE;
1494 if (pQueueUserAPC)
1495 ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1496
1497 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1498 pipe_attr.bInheritHandle = TRUE;
1499 pipe_attr.lpSecurityDescriptor = NULL;
1500 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1501 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 4096, 4096, 1);
1502 test_pipe_info(pipewrite, 0, 4096, 4096, 1);
1503
1504 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1505 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1506 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1507 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1508 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1509 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1510
1511 /* Now write another chunk*/
1512 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1513 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1514 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1515 /* and close the write end, read should still succeed*/
1516 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1517 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe with pending data failed\n");
1518 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1519 /* But now we need to get informed that the pipe is closed */
1520 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1521 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1522
1523 /* Try bigger chunks */
1524 size = 32768;
1525 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1526 for (i = 0; i < size; i++) buffer[i] = i;
1527 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1528 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1529 ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1530 /* and close the write end, read should still succeed*/
1531 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1532 memset( buffer, 0, size );
1533 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe with pending data failed\n");
1534 ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
1535 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1536 /* But now we need to get informed that the pipe is closed */
1537 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1538 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1539 HeapFree(GetProcessHeap(), 0, buffer);
1540
1541 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1542 SleepEx(0, TRUE); /* get rid of apc */
1543
1544 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 1) != 0, "CreatePipe failed\n");
1545 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 1, 1, 1);
1546 test_pipe_info(pipewrite, 0, 1, 1, 1);
1547 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1548 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1549 }
1550
test_CloseHandle(void)1551 static void test_CloseHandle(void)
1552 {
1553 static const char testdata[] = "Hello World";
1554 DWORD state, numbytes;
1555 HANDLE hpipe, hfile;
1556 char buffer[32];
1557 BOOL ret;
1558
1559 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1560 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1561 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1562 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1563
1564 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1565 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1566
1567 numbytes = 0xdeadbeef;
1568 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1569 ok(ret, "WriteFile failed with %u\n", GetLastError());
1570 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1571
1572 numbytes = 0xdeadbeef;
1573 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1574 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1575 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1576
1577 ret = CloseHandle(hpipe);
1578 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1579
1580 numbytes = 0xdeadbeef;
1581 memset(buffer, 0, sizeof(buffer));
1582 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1583 ok(ret, "ReadFile failed with %u\n", GetLastError());
1584 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1585
1586 numbytes = 0xdeadbeef;
1587 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1588 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1589 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1590
1591 numbytes = 0xdeadbeef;
1592 memset(buffer, 0, sizeof(buffer));
1593 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1594 ok(ret, "ReadFile failed with %u\n", GetLastError());
1595 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1596
1597 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1598 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1599 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1600 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1601 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1602
1603 SetLastError(0xdeadbeef);
1604 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1605 ok(!ret, "ReadFile unexpectedly succeeded\n");
1606 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1607
1608 numbytes = 0xdeadbeef;
1609 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1610 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%u)\n",
1611 ret, GetLastError());
1612 ok(numbytes == 0xdeadbeef, "numbytes = %u\n", numbytes);
1613
1614 SetLastError(0xdeadbeef);
1615 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1616 ok(!ret, "WriteFile unexpectedly succeeded\n");
1617 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1618
1619 CloseHandle(hfile);
1620
1621 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1622 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1623 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1624 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1625
1626 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1627 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1628
1629 numbytes = 0xdeadbeef;
1630 ret = WriteFile(hpipe, testdata, 0, &numbytes, NULL);
1631 ok(ret, "WriteFile failed with %u\n", GetLastError());
1632 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1633
1634 ret = CloseHandle(hpipe);
1635 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1636
1637 numbytes = 0xdeadbeef;
1638 memset(buffer, 0, sizeof(buffer));
1639 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1640 ok(ret, "ReadFile failed with %u\n", GetLastError());
1641 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1642
1643 SetLastError(0xdeadbeef);
1644 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1645 ok(!ret, "ReadFile unexpectedly succeeded\n");
1646 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1647
1648 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1649 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1650 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1651 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1652 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1653
1654 SetLastError(0xdeadbeef);
1655 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1656 ok(!ret, "ReadFile unexpectedly succeeded\n");
1657 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1658
1659 SetLastError(0xdeadbeef);
1660 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1661 ok(!ret, "WriteFile unexpectedly succeeded\n");
1662 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1663
1664 CloseHandle(hfile);
1665
1666 /* repeat test with hpipe <-> hfile swapped */
1667
1668 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1669 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1670 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1671 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1672
1673 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1674 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1675
1676 numbytes = 0xdeadbeef;
1677 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1678 ok(ret, "WriteFile failed with %u\n", GetLastError());
1679 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1680
1681 numbytes = 0xdeadbeef;
1682 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1683 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1684 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1685
1686 ret = CloseHandle(hfile);
1687 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1688
1689 numbytes = 0xdeadbeef;
1690 memset(buffer, 0, sizeof(buffer));
1691 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1692 ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
1693 "ReadFile failed with %u\n", GetLastError());
1694 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1695
1696 numbytes = 0xdeadbeef;
1697 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1698 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1699 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1700
1701 numbytes = 0xdeadbeef;
1702 memset(buffer, 0, sizeof(buffer));
1703 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1704 ok(ret, "ReadFile failed with %u\n", GetLastError());
1705 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1706
1707 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1708 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1709 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1710 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1711 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1712
1713 SetLastError(0xdeadbeef);
1714 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1715 ok(!ret, "ReadFile unexpectedly succeeded\n");
1716 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1717
1718 numbytes = 0xdeadbeef;
1719 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1720 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%u)\n",
1721 ret, GetLastError());
1722 ok(numbytes == 0xdeadbeef, "numbytes = %u\n", numbytes);
1723
1724 SetLastError(0xdeadbeef);
1725 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1726 ok(!ret, "WriteFile unexpectedly succeeded\n");
1727 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1728
1729 CloseHandle(hpipe);
1730
1731 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1732 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1733 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1734 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1735
1736 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1737 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1738
1739 numbytes = 0xdeadbeef;
1740 ret = WriteFile(hfile, testdata, 0, &numbytes, NULL);
1741 ok(ret, "WriteFile failed with %u\n", GetLastError());
1742 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1743
1744 ret = CloseHandle(hfile);
1745 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1746
1747 numbytes = 0xdeadbeef;
1748 memset(buffer, 0, sizeof(buffer));
1749 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1750 ok(ret, "ReadFile failed with %u\n", GetLastError());
1751 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1752
1753 SetLastError(0xdeadbeef);
1754 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1755 ok(!ret, "ReadFile unexpectedly succeeded\n");
1756 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1757
1758 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1759 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1760 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1761 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1762 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1763
1764 SetLastError(0xdeadbeef);
1765 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1766 ok(!ret, "ReadFile unexpectedly succeeded\n");
1767 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1768
1769 SetLastError(0xdeadbeef);
1770 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1771 ok(!ret, "WriteFile unexpectedly succeeded\n");
1772 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1773
1774 CloseHandle(hpipe);
1775 }
1776
1777 struct named_pipe_client_params
1778 {
1779 DWORD security_flags;
1780 HANDLE token;
1781 BOOL revert;
1782 };
1783
1784 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1785
named_pipe_client_func(LPVOID p)1786 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1787 {
1788 struct named_pipe_client_params *params = p;
1789 HANDLE pipe;
1790 BOOL ret;
1791 const char message[] = "Test";
1792 DWORD bytes_read, bytes_written;
1793 char dummy;
1794 TOKEN_PRIVILEGES *Privileges = NULL;
1795
1796 if (params->token)
1797 {
1798 if (params->revert)
1799 {
1800 /* modify the token so we can tell if the pipe impersonation
1801 * token reverts to the process token */
1802 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1803 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1804 }
1805 ret = SetThreadToken(NULL, params->token);
1806 ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1807 }
1808 else
1809 {
1810 DWORD Size = 0;
1811 HANDLE process_token;
1812
1813 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1814 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1815
1816 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1817 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1818 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1819 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1820 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1821
1822 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1823 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1824
1825 CloseHandle(process_token);
1826 }
1827
1828 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1829 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1830
1831 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1832 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1833
1834 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1835 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1836
1837 if (params->token)
1838 {
1839 if (params->revert)
1840 {
1841 ret = RevertToSelf();
1842 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1843 }
1844 else
1845 {
1846 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1847 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1848 }
1849 }
1850 else
1851 {
1852 HANDLE process_token;
1853
1854 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1855 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1856
1857 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1858 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1859
1860 HeapFree(GetProcessHeap(), 0, Privileges);
1861
1862 CloseHandle(process_token);
1863 }
1864
1865 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1866 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1867
1868 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1869 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1870
1871 CloseHandle(pipe);
1872
1873 return 0;
1874 }
1875
make_impersonation_token(DWORD Access,SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)1876 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1877 {
1878 HANDLE ProcessToken;
1879 HANDLE Token = NULL;
1880 BOOL ret;
1881
1882 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1883 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1884
1885 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1886 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1887
1888 CloseHandle(ProcessToken);
1889
1890 return Token;
1891 }
1892
test_ImpersonateNamedPipeClient(HANDLE hClientToken,DWORD security_flags,BOOL revert,void (* test_func)(int,HANDLE))1893 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1894 {
1895 HANDLE hPipeServer;
1896 BOOL ret;
1897 DWORD dwTid;
1898 HANDLE hThread;
1899 char buffer[256];
1900 DWORD dwBytesRead;
1901 DWORD error;
1902 struct named_pipe_client_params params;
1903 char dummy = 0;
1904 DWORD dwBytesWritten;
1905 HANDLE hToken = NULL;
1906 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1907 DWORD size;
1908
1909 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1910 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1911
1912 params.security_flags = security_flags;
1913 params.token = hClientToken;
1914 params.revert = revert;
1915 hThread = CreateThread(NULL, 0, named_pipe_client_func, ¶ms, 0, &dwTid);
1916 ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1917
1918 SetLastError(0xdeadbeef);
1919 ret = ImpersonateNamedPipeClient(hPipeServer);
1920 error = GetLastError();
1921 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1922 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1923
1924 ret = ConnectNamedPipe(hPipeServer, NULL);
1925 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1926
1927 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1928 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1929
1930 ret = ImpersonateNamedPipeClient(hPipeServer);
1931 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1932
1933 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1934 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1935
1936 (*test_func)(0, hToken);
1937
1938 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1939 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1940 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1941 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1942
1943 CloseHandle(hToken);
1944
1945 RevertToSelf();
1946
1947 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1948 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1949
1950 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1951 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1952
1953 ret = ImpersonateNamedPipeClient(hPipeServer);
1954 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1955
1956 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1957 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1958
1959 (*test_func)(1, hToken);
1960
1961 CloseHandle(hToken);
1962
1963 RevertToSelf();
1964
1965 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1966 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1967
1968 WaitForSingleObject(hThread, INFINITE);
1969
1970 ret = ImpersonateNamedPipeClient(hPipeServer);
1971 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1972
1973 RevertToSelf();
1974
1975 CloseHandle(hThread);
1976 CloseHandle(hPipeServer);
1977 }
1978
are_all_privileges_disabled(HANDLE hToken)1979 static BOOL are_all_privileges_disabled(HANDLE hToken)
1980 {
1981 BOOL ret;
1982 TOKEN_PRIVILEGES *Privileges = NULL;
1983 DWORD Size = 0;
1984 BOOL all_privs_disabled = TRUE;
1985 DWORD i;
1986
1987 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1988 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1989 {
1990 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1991 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1992 if (!ret)
1993 {
1994 HeapFree(GetProcessHeap(), 0, Privileges);
1995 return FALSE;
1996 }
1997 }
1998 else
1999 return FALSE;
2000
2001 for (i = 0; i < Privileges->PrivilegeCount; i++)
2002 {
2003 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
2004 {
2005 all_privs_disabled = FALSE;
2006 break;
2007 }
2008 }
2009
2010 HeapFree(GetProcessHeap(), 0, Privileges);
2011
2012 return all_privs_disabled;
2013 }
2014
get_privilege_count(HANDLE hToken)2015 static DWORD get_privilege_count(HANDLE hToken)
2016 {
2017 TOKEN_STATISTICS Statistics;
2018 DWORD Size = sizeof(Statistics);
2019 BOOL ret;
2020
2021 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
2022 ok(ret, "GetTokenInformation(TokenStatistics)\n");
2023 if (!ret) return -1;
2024
2025 return Statistics.PrivilegeCount;
2026 }
2027
test_no_sqos_no_token(int call_index,HANDLE hToken)2028 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
2029 {
2030 DWORD priv_count;
2031
2032 switch (call_index)
2033 {
2034 case 0:
2035 priv_count = get_privilege_count(hToken);
2036 todo_wine
2037 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
2038 break;
2039 case 1:
2040 priv_count = get_privilege_count(hToken);
2041 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2042 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2043 break;
2044 default:
2045 ok(0, "shouldn't happen\n");
2046 }
2047 }
2048
test_no_sqos(int call_index,HANDLE hToken)2049 static void test_no_sqos(int call_index, HANDLE hToken)
2050 {
2051 switch (call_index)
2052 {
2053 case 0:
2054 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2055 break;
2056 case 1:
2057 todo_wine
2058 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2059 break;
2060 default:
2061 ok(0, "shouldn't happen\n");
2062 }
2063 }
2064
test_static_context(int call_index,HANDLE hToken)2065 static void test_static_context(int call_index, HANDLE hToken)
2066 {
2067 switch (call_index)
2068 {
2069 case 0:
2070 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2071 break;
2072 case 1:
2073 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2074 break;
2075 default:
2076 ok(0, "shouldn't happen\n");
2077 }
2078 }
2079
test_dynamic_context(int call_index,HANDLE hToken)2080 static void test_dynamic_context(int call_index, HANDLE hToken)
2081 {
2082 switch (call_index)
2083 {
2084 case 0:
2085 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2086 break;
2087 case 1:
2088 todo_wine
2089 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2090 break;
2091 default:
2092 ok(0, "shouldn't happen\n");
2093 }
2094 }
2095
test_dynamic_context_no_token(int call_index,HANDLE hToken)2096 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
2097 {
2098 switch (call_index)
2099 {
2100 case 0:
2101 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2102 break;
2103 case 1:
2104 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
2105 break;
2106 default:
2107 ok(0, "shouldn't happen\n");
2108 }
2109 }
2110
test_no_sqos_revert(int call_index,HANDLE hToken)2111 static void test_no_sqos_revert(int call_index, HANDLE hToken)
2112 {
2113 DWORD priv_count;
2114 switch (call_index)
2115 {
2116 case 0:
2117 priv_count = get_privilege_count(hToken);
2118 todo_wine
2119 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
2120 break;
2121 case 1:
2122 priv_count = get_privilege_count(hToken);
2123 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2124 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2125 break;
2126 default:
2127 ok(0, "shouldn't happen\n");
2128 }
2129 }
2130
test_static_context_revert(int call_index,HANDLE hToken)2131 static void test_static_context_revert(int call_index, HANDLE hToken)
2132 {
2133 switch (call_index)
2134 {
2135 case 0:
2136 todo_wine
2137 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2138 break;
2139 case 1:
2140 todo_wine
2141 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2142 break;
2143 default:
2144 ok(0, "shouldn't happen\n");
2145 }
2146 }
2147
test_dynamic_context_revert(int call_index,HANDLE hToken)2148 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
2149 {
2150 switch (call_index)
2151 {
2152 case 0:
2153 todo_wine
2154 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2155 break;
2156 case 1:
2157 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
2158 break;
2159 default:
2160 ok(0, "shouldn't happen\n");
2161 }
2162 }
2163
test_impersonation(void)2164 static void test_impersonation(void)
2165 {
2166 HANDLE hClientToken;
2167 HANDLE hProcessToken;
2168 BOOL ret;
2169
2170 if( !pDuplicateTokenEx ) {
2171 skip("DuplicateTokenEx not found\n");
2172 return;
2173 }
2174
2175 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
2176 if (!ret)
2177 {
2178 skip("couldn't open process token, skipping impersonation tests\n");
2179 return;
2180 }
2181
2182 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
2183 {
2184 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
2185 CloseHandle(hProcessToken);
2186 return;
2187 }
2188 CloseHandle(hProcessToken);
2189
2190 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
2191 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2192 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
2193 CloseHandle(hClientToken);
2194 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2195 test_ImpersonateNamedPipeClient(hClientToken,
2196 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
2197 test_static_context);
2198 CloseHandle(hClientToken);
2199 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2200 test_ImpersonateNamedPipeClient(hClientToken,
2201 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2202 FALSE, test_dynamic_context);
2203 CloseHandle(hClientToken);
2204 test_ImpersonateNamedPipeClient(NULL,
2205 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2206 FALSE, test_dynamic_context_no_token);
2207
2208 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2209 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
2210 CloseHandle(hClientToken);
2211 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2212 test_ImpersonateNamedPipeClient(hClientToken,
2213 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
2214 test_static_context_revert);
2215 CloseHandle(hClientToken);
2216 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2217 test_ImpersonateNamedPipeClient(hClientToken,
2218 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2219 TRUE, test_dynamic_context_revert);
2220 CloseHandle(hClientToken);
2221 }
2222
2223 struct overlapped_server_args
2224 {
2225 HANDLE pipe_created;
2226 };
2227
overlapped_server(LPVOID arg)2228 static DWORD CALLBACK overlapped_server(LPVOID arg)
2229 {
2230 OVERLAPPED ol;
2231 HANDLE pipe;
2232 int ret, err;
2233 struct overlapped_server_args *a = arg;
2234 DWORD num;
2235 char buf[100];
2236
2237 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
2238 ok(pipe != NULL, "pipe NULL\n");
2239
2240 ol.hEvent = CreateEventA(0, 1, 0, 0);
2241 ok(ol.hEvent != NULL, "event NULL\n");
2242 ret = ConnectNamedPipe(pipe, &ol);
2243 err = GetLastError();
2244 ok(ret == 0, "ret %d\n", ret);
2245 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2246 SetEvent(a->pipe_created);
2247
2248 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2249 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2250
2251 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2252 ok(ret == 1, "ret %d\n", ret);
2253
2254 /* This should block */
2255 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
2256 ok(ret == 1, "ret %d\n", ret);
2257
2258 DisconnectNamedPipe(pipe);
2259
2260 ret = ConnectNamedPipe(pipe, &ol);
2261 err = GetLastError();
2262 ok(ret == 0, "ret %d\n", ret);
2263 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2264 CancelIo(pipe);
2265 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2266 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2267
2268 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2269 err = GetLastError();
2270 ok(ret == 0, "ret %d\n", ret);
2271 ok(err == ERROR_OPERATION_ABORTED, "gle %d\n", err);
2272
2273 CloseHandle(ol.hEvent);
2274 CloseHandle(pipe);
2275 return 1;
2276 }
2277
test_overlapped(void)2278 static void test_overlapped(void)
2279 {
2280 DWORD tid, num;
2281 HANDLE thread, pipe;
2282 BOOL ret;
2283 struct overlapped_server_args args;
2284
2285 args.pipe_created = CreateEventA(0, 1, 0, 0);
2286 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
2287
2288 WaitForSingleObject(args.pipe_created, INFINITE);
2289 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
2290 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
2291
2292 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
2293 Sleep(1);
2294
2295 ret = WriteFile(pipe, "x", 1, &num, NULL);
2296 ok(ret, "WriteFile failed with error %d\n", GetLastError());
2297
2298 WaitForSingleObject(thread, INFINITE);
2299 CloseHandle(pipe);
2300 CloseHandle(args.pipe_created);
2301 CloseHandle(thread);
2302 }
2303
test_overlapped_error(void)2304 static void test_overlapped_error(void)
2305 {
2306 HANDLE pipe, file, event;
2307 DWORD err, numbytes;
2308 OVERLAPPED overlapped;
2309 BOOL ret;
2310
2311 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2312 ok(event != NULL, "CreateEventA failed with %u\n", GetLastError());
2313
2314 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2315 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2316 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2317 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2318
2319 memset(&overlapped, 0, sizeof(overlapped));
2320 overlapped.hEvent = event;
2321 ret = ConnectNamedPipe(pipe, &overlapped);
2322 err = GetLastError();
2323 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2324 ok(err == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", err);
2325
2326 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2327 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2328 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2329
2330 numbytes = 0xdeadbeef;
2331 ret = GetOverlappedResult(pipe, &overlapped, &numbytes, TRUE);
2332 ok(ret == TRUE, "GetOverlappedResult failed\n");
2333 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
2334 ok(overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", overlapped.Internal);
2335
2336 CloseHandle(file);
2337 CloseHandle(pipe);
2338
2339 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2340 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2341 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2342 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2343
2344 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2345 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2346 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2347
2348 memset(&overlapped, 0, sizeof(overlapped));
2349 overlapped.hEvent = event;
2350 ret = ConnectNamedPipe(pipe, &overlapped);
2351 err = GetLastError();
2352 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2353 ok(err == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", err);
2354 ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", overlapped.Internal);
2355
2356 CloseHandle(file);
2357 CloseHandle(pipe);
2358
2359 CloseHandle(event);
2360 }
2361
test_NamedPipeHandleState(void)2362 static void test_NamedPipeHandleState(void)
2363 {
2364 HANDLE server, client;
2365 BOOL ret;
2366 DWORD state, instances, maxCollectionCount, collectDataTimeout;
2367 char userName[MAX_PATH];
2368
2369 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2370 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2371 /* nMaxInstances */ 1,
2372 /* nOutBufSize */ 1024,
2373 /* nInBufSize */ 1024,
2374 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2375 /* lpSecurityAttrib */ NULL);
2376 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2377 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2378 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2379 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2380 0);
2381 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2382 if (ret)
2383 {
2384 ok(state == 0, "unexpected state %08x\n", state);
2385 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2386 }
2387 /* Some parameters have no meaning, and therefore can't be retrieved,
2388 * on a local pipe.
2389 */
2390 SetLastError(0xdeadbeef);
2391 ret = GetNamedPipeHandleStateA(server, &state, &instances,
2392 &maxCollectionCount, &collectDataTimeout, userName,
2393 sizeof(userName) / sizeof(userName[0]));
2394 todo_wine
2395 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2396 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2397 /* A byte-mode pipe server can't be changed to message mode. */
2398 state = PIPE_READMODE_MESSAGE;
2399 SetLastError(0xdeadbeef);
2400 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2401 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2402 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2403
2404 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2405 OPEN_EXISTING, 0, NULL);
2406 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2407
2408 state = PIPE_READMODE_BYTE;
2409 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2410 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2411 /* A byte-mode pipe client can't be changed to message mode, either. */
2412 state = PIPE_READMODE_MESSAGE;
2413 SetLastError(0xdeadbeef);
2414 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2415 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2416 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2417
2418 CloseHandle(client);
2419 CloseHandle(server);
2420
2421 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2422 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2423 /* nMaxInstances */ 1,
2424 /* nOutBufSize */ 1024,
2425 /* nInBufSize */ 1024,
2426 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2427 /* lpSecurityAttrib */ NULL);
2428 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2429 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2430 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2431 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2432 0);
2433 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2434 if (ret)
2435 {
2436 ok(state == 0, "unexpected state %08x\n", state);
2437 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2438 }
2439 /* In contrast to byte-mode pipes, a message-mode pipe server can be
2440 * changed to byte mode.
2441 */
2442 state = PIPE_READMODE_BYTE;
2443 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2444 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2445
2446 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2447 OPEN_EXISTING, 0, NULL);
2448 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2449
2450 state = PIPE_READMODE_MESSAGE;
2451 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2452 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2453 /* A message-mode pipe client can also be changed to byte mode.
2454 */
2455 state = PIPE_READMODE_BYTE;
2456 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2457 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2458
2459 CloseHandle(client);
2460 CloseHandle(server);
2461 }
2462
test_GetNamedPipeInfo(void)2463 static void test_GetNamedPipeInfo(void)
2464 {
2465 HANDLE server;
2466
2467 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2468 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2469 /* nMaxInstances */ 1,
2470 /* nOutBufSize */ 1024,
2471 /* nInBufSize */ 1024,
2472 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2473 /* lpSecurityAttrib */ NULL);
2474 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2475
2476 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_BYTE, 1024, 1024, 1);
2477
2478 CloseHandle(server);
2479
2480 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2481 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
2482 /* nMaxInstances */ 3,
2483 /* nOutBufSize */ 1024,
2484 /* nInBufSize */ 1024,
2485 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2486 /* lpSecurityAttrib */ NULL);
2487 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2488
2489 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 1024, 1024, 3);
2490
2491 CloseHandle(server);
2492
2493 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2494 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2495 /* nMaxInstances */ 1,
2496 /* nOutBufSize */ 0,
2497 /* nInBufSize */ 0,
2498 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2499 /* lpSecurityAttrib */ NULL);
2500 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2501
2502 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0, 0, 1);
2503
2504 CloseHandle(server);
2505
2506 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2507 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2508 /* nMaxInstances */ 1,
2509 /* nOutBufSize */ 0xf000,
2510 /* nInBufSize */ 0xf000,
2511 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2512 /* lpSecurityAttrib */ NULL);
2513 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2514
2515 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0xf000, 0xf000, 1);
2516
2517 CloseHandle(server);
2518 }
2519
test_readfileex_pending(void)2520 static void test_readfileex_pending(void)
2521 {
2522 HANDLE server, client, event;
2523 BOOL ret;
2524 DWORD err, wait, num_bytes;
2525 OVERLAPPED overlapped;
2526 char read_buf[1024];
2527 char write_buf[1024];
2528 const char test_string[] = "test";
2529 int i;
2530
2531 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2532 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2533 /* nMaxInstances */ 1,
2534 /* nOutBufSize */ 1024,
2535 /* nInBufSize */ 1024,
2536 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2537 /* lpSecurityAttrib */ NULL);
2538 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2539
2540 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2541 ok(event != NULL, "CreateEventA failed\n");
2542
2543 memset(&overlapped, 0, sizeof(overlapped));
2544 overlapped.hEvent = event;
2545
2546 ret = ConnectNamedPipe(server, &overlapped);
2547 err = GetLastError();
2548 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2549 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
2550
2551 wait = WaitForSingleObject(event, 0);
2552 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
2553
2554 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2555 OPEN_EXISTING, 0, NULL);
2556 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2557
2558 wait = WaitForSingleObject(event, 0);
2559 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2560
2561 /* Start a read that can't complete immediately. */
2562 completion_called = 0;
2563 ResetEvent(event);
2564 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
2565 ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
2566 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
2567
2568 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
2569 ok(ret == TRUE, "WriteFile failed\n");
2570 ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
2571
2572 ok(completion_called == 0, "completion routine called during WriteFile\n");
2573
2574 wait = WaitForSingleObjectEx(event, 0, TRUE);
2575 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
2576
2577 ok(completion_called == 1, "completion not called after writing pipe\n");
2578 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2579 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
2580 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2581 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
2582
2583 /* Make writes until the pipe is full and the write fails */
2584 memset(write_buf, 0xaa, sizeof(write_buf));
2585 for (i=0; i<256; i++)
2586 {
2587 completion_called = 0;
2588 ResetEvent(event);
2589 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
2590 err = GetLastError();
2591
2592 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
2593
2594 wait = WaitForSingleObjectEx(event, 0, TRUE);
2595
2596 if (wait == WAIT_TIMEOUT)
2597 /* write couldn't complete immediately, presumably the pipe is full */
2598 break;
2599
2600 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2601
2602 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
2603 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2604 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2605 }
2606
2607 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
2608 ok(completion_called == 0, "completion routine called but wait timed out\n");
2609 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2610 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2611
2612 /* free up some space in the pipe */
2613 for (i=0; i<256; i++)
2614 {
2615 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
2616 ok(ret == TRUE, "ReadFile failed\n");
2617
2618 ok(completion_called == 0, "completion routine called during ReadFile\n");
2619
2620 wait = WaitForSingleObjectEx(event, 0, TRUE);
2621 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0 || wait == WAIT_TIMEOUT,
2622 "WaitForSingleObject returned %x\n", wait);
2623 if (wait != WAIT_TIMEOUT) break;
2624 }
2625
2626 ok(completion_called == 1, "completion routine not called\n");
2627 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2628 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2629
2630 num_bytes = 0xdeadbeef;
2631 SetLastError(0xdeadbeef);
2632 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
2633 ok(!ret, "ReadFile should fail\n");
2634 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
2635 ok(num_bytes == 0, "expected 0, got %u\n", num_bytes);
2636
2637 S(U(overlapped)).Offset = 0;
2638 S(U(overlapped)).OffsetHigh = 0;
2639 overlapped.Internal = -1;
2640 overlapped.InternalHigh = -1;
2641 overlapped.hEvent = event;
2642 num_bytes = 0xdeadbeef;
2643 SetLastError(0xdeadbeef);
2644 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
2645 ok(!ret, "ReadFile should fail\n");
2646 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2647 ok(num_bytes == 0, "bytes %u\n", num_bytes);
2648 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
2649 ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
2650
2651 wait = WaitForSingleObject(event, 100);
2652 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
2653
2654 num_bytes = 0xdeadbeef;
2655 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
2656 ok(ret, "WriteFile failed\n");
2657 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2658
2659 wait = WaitForSingleObject(event, 100);
2660 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2661
2662 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2663 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
2664 ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
2665
2666 /* read the pending byte and clear the pipe */
2667 num_bytes = 0xdeadbeef;
2668 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
2669 ok(ret, "ReadFile failed\n");
2670 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2671
2672 CloseHandle(client);
2673 CloseHandle(server);
2674 CloseHandle(event);
2675 }
2676
2677 #define test_peek_pipe(a,b,c,d) _test_peek_pipe(__LINE__,a,b,c,d)
_test_peek_pipe(unsigned line,HANDLE pipe,DWORD expected_read,DWORD expected_avail,DWORD expected_message_length)2678 static void _test_peek_pipe(unsigned line, HANDLE pipe, DWORD expected_read, DWORD expected_avail, DWORD expected_message_length)
2679 {
2680 DWORD bytes_read = 0xdeadbeed, avail = 0xdeadbeef, left = 0xdeadbeed;
2681 char buf[4000];
2682 FILE_PIPE_PEEK_BUFFER *peek_buf = (void*)buf;
2683 IO_STATUS_BLOCK io;
2684 NTSTATUS status;
2685 BOOL r;
2686
2687 r = PeekNamedPipe(pipe, buf, sizeof(buf), &bytes_read, &avail, &left);
2688 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %u\n", GetLastError());
2689 ok_(__FILE__,line)(bytes_read == expected_read, "bytes_read = %u, expected %u\n", bytes_read, expected_read);
2690 ok_(__FILE__,line)(avail == expected_avail, "avail = %u, expected %u\n", avail, expected_avail);
2691 ok_(__FILE__,line)(left == expected_message_length - expected_read, "left = %d, expected %d\n",
2692 left, expected_message_length - expected_read);
2693
2694 status = NtFsControlFile(pipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0, buf, sizeof(buf));
2695 ok_(__FILE__,line)(!status || status == STATUS_PENDING, "NtFsControlFile(FSCTL_PIPE_PEEK) failed: %x\n", status);
2696 ok_(__FILE__,line)(io.Information == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[expected_read]),
2697 "io.Information = %lu\n", io.Information);
2698 ok_(__FILE__,line)(peek_buf->ReadDataAvailable == expected_avail, "ReadDataAvailable = %u, expected %u\n",
2699 peek_buf->ReadDataAvailable, expected_avail);
2700 ok_(__FILE__,line)(peek_buf->MessageLength == expected_message_length, "MessageLength = %u, expected %u\n",
2701 peek_buf->MessageLength, expected_message_length);
2702
2703 if (expected_read)
2704 {
2705 r = PeekNamedPipe(pipe, buf, 1, &bytes_read, &avail, &left);
2706 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %u\n", GetLastError());
2707 ok_(__FILE__,line)(bytes_read == 1, "bytes_read = %u, expected %u\n", bytes_read, expected_read);
2708 ok_(__FILE__,line)(avail == expected_avail, "avail = %u, expected %u\n", avail, expected_avail);
2709 ok_(__FILE__,line)(left == expected_message_length-1, "left = %d, expected %d\n", left, expected_message_length-1);
2710 }
2711 }
2712
2713 #define overlapped_read_sync(a,b,c,d,e) _overlapped_read_sync(__LINE__,a,b,c,d,e)
_overlapped_read_sync(unsigned line,HANDLE reader,void * buf,DWORD buf_size,DWORD expected_result,BOOL partial_read)2714 static void _overlapped_read_sync(unsigned line, HANDLE reader, void *buf, DWORD buf_size, DWORD expected_result, BOOL partial_read)
2715 {
2716 DWORD read_bytes = 0xdeadbeef;
2717 OVERLAPPED overlapped;
2718 BOOL res;
2719
2720 memset(&overlapped, 0, sizeof(overlapped));
2721 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2722 res = ReadFile(reader, buf, buf_size, &read_bytes, &overlapped);
2723 if (partial_read)
2724 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x (%u)\n", res, GetLastError());
2725 else
2726 ok_(__FILE__,line)(res, "ReadFile failed: %u\n", GetLastError());
2727 if(partial_read)
2728 ok_(__FILE__,line)(!read_bytes, "read_bytes %u expected 0\n", read_bytes);
2729 else
2730 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %u expected %u\n", read_bytes, expected_result);
2731
2732 read_bytes = 0xdeadbeef;
2733 res = GetOverlappedResult(reader, &overlapped, &read_bytes, FALSE);
2734 if (partial_read)
2735 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA,
2736 "GetOverlappedResult returned: %x (%u)\n", res, GetLastError());
2737 else
2738 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2739 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %u expected %u\n", read_bytes, expected_result);
2740 CloseHandle(overlapped.hEvent);
2741 }
2742
2743 #define overlapped_read_async(a,b,c,d) _overlapped_read_async(__LINE__,a,b,c,d)
_overlapped_read_async(unsigned line,HANDLE reader,void * buf,DWORD buf_size,OVERLAPPED * overlapped)2744 static void _overlapped_read_async(unsigned line, HANDLE reader, void *buf, DWORD buf_size, OVERLAPPED *overlapped)
2745 {
2746 DWORD read_bytes = 0xdeadbeef;
2747 BOOL res;
2748
2749 memset(overlapped, 0, sizeof(*overlapped));
2750 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2751 res = ReadFile(reader, buf, buf_size, &read_bytes, overlapped);
2752 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "ReadFile returned %x(%u)\n", res, GetLastError());
2753 ok_(__FILE__,line)(!read_bytes, "read_bytes %u expected 0\n", read_bytes);
2754
2755 _test_not_signaled(line, overlapped->hEvent);
2756 }
2757
2758 #define overlapped_write_sync(a,b,c) _overlapped_write_sync(__LINE__,a,b,c)
_overlapped_write_sync(unsigned line,HANDLE writer,void * buf,DWORD size)2759 static void _overlapped_write_sync(unsigned line, HANDLE writer, void *buf, DWORD size)
2760 {
2761 DWORD written_bytes = 0xdeadbeef;
2762 OVERLAPPED overlapped;
2763 BOOL res;
2764
2765 memset(&overlapped, 0, sizeof(overlapped));
2766 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2767 res = WriteFile(writer, buf, size, &written_bytes, &overlapped);
2768 ok_(__FILE__,line)(res, "WriteFile returned %x(%u)\n", res, GetLastError());
2769 ok_(__FILE__,line)(written_bytes == size, "WriteFile returned written_bytes = %u\n", written_bytes);
2770
2771 written_bytes = 0xdeadbeef;
2772 res = GetOverlappedResult(writer, &overlapped, &written_bytes, FALSE);
2773 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2774 ok_(__FILE__,line)(written_bytes == size, "GetOverlappedResult returned written_bytes %u expected %u\n", written_bytes, size);
2775
2776 CloseHandle(overlapped.hEvent);
2777 }
2778
2779 #define overlapped_write_async(a,b,c,d) _overlapped_write_async(__LINE__,a,b,c,d)
_overlapped_write_async(unsigned line,HANDLE writer,void * buf,DWORD size,OVERLAPPED * overlapped)2780 static void _overlapped_write_async(unsigned line, HANDLE writer, void *buf, DWORD size, OVERLAPPED *overlapped)
2781 {
2782 DWORD written_bytes = 0xdeadbeef;
2783 BOOL res;
2784
2785 memset(overlapped, 0, sizeof(*overlapped));
2786 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2787 res = WriteFile(writer, buf, size, &written_bytes, overlapped);
2788 disable_success_count
2789 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%u)\n", res, GetLastError());
2790 disable_success_count
2791 ok_(__FILE__,line)(!written_bytes, "written_bytes = %u\n", written_bytes);
2792
2793 _test_not_signaled(line, overlapped->hEvent);
2794 }
2795
2796 #define test_flush_sync(a) _test_flush_sync(__LINE__,a)
_test_flush_sync(unsigned line,HANDLE pipe)2797 static void _test_flush_sync(unsigned line, HANDLE pipe)
2798 {
2799 BOOL res;
2800
2801 res = FlushFileBuffers(pipe);
2802 ok_(__FILE__,line)(res, "FlushFileBuffers failed: %u\n", GetLastError());
2803 }
2804
2805 static DWORD expected_flush_error;
2806
flush_proc(HANDLE pipe)2807 static DWORD CALLBACK flush_proc(HANDLE pipe)
2808 {
2809 BOOL res;
2810
2811 res = FlushFileBuffers(pipe);
2812 if (expected_flush_error == ERROR_SUCCESS)
2813 ok(res, "FlushFileBuffers failed: %u\n", GetLastError());
2814 else
2815 todo_wine ok(!res && GetLastError() == expected_flush_error, "FlushFileBuffers failed: %u\n", GetLastError());
2816 return 0;
2817 }
2818
2819 #define test_flush_async(a,b) _test_flush_async(__LINE__,a,b)
_test_flush_async(unsigned line,HANDLE pipe,DWORD error)2820 static HANDLE _test_flush_async(unsigned line, HANDLE pipe, DWORD error)
2821 {
2822 HANDLE thread;
2823 DWORD tid;
2824
2825 expected_flush_error = error;
2826 thread = CreateThread(NULL, 0, flush_proc, pipe, 0, &tid);
2827 ok_(__FILE__,line)(thread != NULL, "CreateThread failed: %u\n", GetLastError());
2828
2829 Sleep(50);
2830 _test_not_signaled(line, thread);
2831 return thread;
2832 }
2833
2834 #define test_flush_done(a) _test_flush_done(__LINE__,a)
_test_flush_done(unsigned line,HANDLE thread)2835 static void _test_flush_done(unsigned line, HANDLE thread)
2836 {
2837 DWORD res = WaitForSingleObject(thread, 1000);
2838 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
2839 CloseHandle(thread);
2840 }
2841
2842 #define test_overlapped_result(a,b,c,d) _test_overlapped_result(__LINE__,a,b,c,d)
_test_overlapped_result(unsigned line,HANDLE handle,OVERLAPPED * overlapped,DWORD expected_result,BOOL partial_read)2843 static void _test_overlapped_result(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD expected_result, BOOL partial_read)
2844 {
2845 DWORD result = 0xdeadbeef;
2846 BOOL res;
2847
2848 _test_signaled(line, overlapped->hEvent);
2849
2850 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2851 if (partial_read)
2852 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "GetOverlappedResult returned: %x (%u)\n", res, GetLastError());
2853 else
2854 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2855 ok_(__FILE__,line)(result == expected_result, "read_bytes = %u, expected %u\n", result, expected_result);
2856 CloseHandle(overlapped->hEvent);
2857 }
2858
2859 #define test_overlapped_failure(a,b,c) _test_overlapped_failure(__LINE__,a,b,c)
_test_overlapped_failure(unsigned line,HANDLE handle,OVERLAPPED * overlapped,DWORD error)2860 static void _test_overlapped_failure(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD error)
2861 {
2862 DWORD result;
2863 BOOL res;
2864
2865 _test_signaled(line, overlapped->hEvent);
2866
2867 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2868 ok_(__FILE__,line)(!res && GetLastError() == error, "GetOverlappedResult returned: %x (%u), expected error %u\n",
2869 res, GetLastError(), error);
2870 ok_(__FILE__,line)(!result, "result = %u\n", result);
2871 CloseHandle(overlapped->hEvent);
2872 }
2873
2874 #define cancel_overlapped(a,b) _cancel_overlapped(__LINE__,a,b)
_cancel_overlapped(unsigned line,HANDLE handle,OVERLAPPED * overlapped)2875 static void _cancel_overlapped(unsigned line, HANDLE handle, OVERLAPPED *overlapped)
2876 {
2877 BOOL res;
2878
2879 res = pCancelIoEx(handle, overlapped);
2880 ok_(__FILE__,line)(res, "CancelIoEx failed: %u\n", GetLastError());
2881
2882 _test_overlapped_failure(line, handle, overlapped, ERROR_OPERATION_ABORTED);
2883 }
2884
test_blocking_rw(HANDLE writer,HANDLE reader,DWORD buf_size,BOOL msg_mode,BOOL msg_read)2885 static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL msg_mode, BOOL msg_read)
2886 {
2887 OVERLAPPED read_overlapped, read_overlapped2, write_overlapped, write_overlapped2;
2888 char buf[10000], read_buf[10000];
2889 HANDLE flush_thread;
2890
2891 memset(buf, 0xaa, sizeof(buf));
2892
2893 /* test pending read with overlapped event */
2894 overlapped_read_async(reader, read_buf, 1000, &read_overlapped);
2895 test_flush_sync(writer);
2896 test_peek_pipe(reader, 0, 0, 0);
2897
2898 /* write more data than needed for read */
2899 overlapped_write_sync(writer, buf, 4000);
2900 test_overlapped_result(reader, &read_overlapped, 1000, msg_read);
2901
2902 /* test pending write with overlapped event */
2903 overlapped_write_async(writer, buf, buf_size, &write_overlapped);
2904
2905 /* write one more byte */
2906 overlapped_write_async(writer, buf, 1, &write_overlapped2);
2907 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
2908 test_not_signaled(write_overlapped.hEvent);
2909
2910 /* empty write will not block */
2911 overlapped_write_sync(writer, buf, 0);
2912 test_not_signaled(write_overlapped.hEvent);
2913 test_not_signaled(write_overlapped2.hEvent);
2914
2915 /* read remaining data from the first write */
2916 overlapped_read_sync(reader, read_buf, 3000, 3000, FALSE);
2917 test_overlapped_result(writer, &write_overlapped, buf_size, FALSE);
2918 test_not_signaled(write_overlapped2.hEvent);
2919 test_not_signaled(flush_thread);
2920
2921 /* read one byte so that the next write fits the buffer */
2922 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
2923 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
2924
2925 /* read the whole buffer */
2926 overlapped_read_sync(reader, read_buf, buf_size, buf_size-msg_read, FALSE);
2927
2928 if(msg_read)
2929 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
2930
2931 if(msg_mode) {
2932 /* we still have an empty message in queue */
2933 overlapped_read_sync(reader, read_buf, 1000, 0, FALSE);
2934 }
2935 test_flush_done(flush_thread);
2936
2937 /* pipe is empty, the next read will block */
2938 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
2939 overlapped_read_async(reader, read_buf, 1000, &read_overlapped2);
2940
2941 /* write one byte */
2942 overlapped_write_sync(writer, buf, 1);
2943 test_overlapped_result(reader, &read_overlapped, 0, msg_read);
2944 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
2945
2946 /* write a message larger than buffer */
2947 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
2948
2949 /* read so that pending write is still larger than the buffer */
2950 overlapped_read_sync(reader, read_buf, 1999, 1999, msg_read);
2951 test_not_signaled(write_overlapped.hEvent);
2952
2953 /* read one more byte */
2954 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
2955 test_overlapped_result(writer, &write_overlapped, buf_size+2000, FALSE);
2956
2957 /* read remaining data */
2958 overlapped_read_sync(reader, read_buf, buf_size+1, buf_size, FALSE);
2959
2960 /* simple pass of empty message */
2961 overlapped_write_sync(writer, buf, 0);
2962 if(msg_mode)
2963 overlapped_read_sync(reader, read_buf, 1, 0, FALSE);
2964
2965 /* pipe is empty, the next read will block */
2966 test_flush_sync(writer);
2967 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
2968 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
2969
2970 /* 0 length write wakes one read in msg mode */
2971 overlapped_write_sync(writer, buf, 0);
2972 if(msg_mode)
2973 test_overlapped_result(reader, &read_overlapped, 0, FALSE);
2974 else
2975 test_not_signaled(read_overlapped.hEvent);
2976 test_not_signaled(read_overlapped2.hEvent);
2977 overlapped_write_sync(writer, buf, 1);
2978 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
2979
2980 overlapped_write_sync(writer, buf, 20);
2981 test_peek_pipe(reader, 20, 20, msg_mode ? 20 : 0);
2982 overlapped_write_sync(writer, buf, 15);
2983 test_peek_pipe(reader, msg_mode ? 20 : 35, 35, msg_mode ? 20 : 0);
2984 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
2985 test_peek_pipe(reader, msg_mode ? 10 : 25, 25, msg_mode ? 10 : 0);
2986 overlapped_read_sync(reader, read_buf, 10, 10, FALSE);
2987 test_peek_pipe(reader, 15, 15, msg_mode ? 15 : 0);
2988 overlapped_read_sync(reader, read_buf, 15, 15, FALSE);
2989
2990 if(!pCancelIoEx) {
2991 win_skip("CancelIoEx not available\n");
2992 return;
2993 }
2994
2995 /* add one more pending read, then cancel the first one */
2996 overlapped_read_async(reader, read_buf, 1, &read_overlapped);
2997 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
2998 cancel_overlapped(reader, &read_overlapped2);
2999 test_not_signaled(read_overlapped.hEvent);
3000 overlapped_write_sync(writer, buf, 1);
3001 test_overlapped_result(reader, &read_overlapped, 1, FALSE);
3002
3003 /* make two async writes, cancel the first one and make sure that we read from the second one */
3004 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3005 overlapped_write_async(writer, buf, 1, &write_overlapped2);
3006 cancel_overlapped(writer, &write_overlapped);
3007 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3008 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
3009
3010 /* same as above, but parially read written data before canceling */
3011 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3012 overlapped_write_async(writer, buf, 1, &write_overlapped2);
3013 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
3014 test_not_signaled(write_overlapped.hEvent);
3015 cancel_overlapped(writer, &write_overlapped);
3016 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3017 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
3018
3019 /* empty queue by canceling write and make sure that flush is signaled */
3020 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3021 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
3022 test_not_signaled(flush_thread);
3023 cancel_overlapped(writer, &write_overlapped);
3024 test_flush_done(flush_thread);
3025 }
3026
child_process_write_pipe(HANDLE pipe)3027 static void child_process_write_pipe(HANDLE pipe)
3028 {
3029 OVERLAPPED overlapped;
3030 char buf[10000];
3031
3032 memset(buf, 'x', sizeof(buf));
3033 overlapped_write_async(pipe, buf, sizeof(buf), &overlapped);
3034
3035 /* sleep until parent process terminates this process */
3036 Sleep(INFINITE);
3037 }
3038
create_writepipe_process(HANDLE pipe)3039 static HANDLE create_writepipe_process(HANDLE pipe)
3040 {
3041 STARTUPINFOA si = { sizeof(si) };
3042 PROCESS_INFORMATION info;
3043 char **argv, buf[MAX_PATH];
3044 BOOL res;
3045
3046 winetest_get_mainargs(&argv);
3047 sprintf(buf, "\"%s\" pipe writepipe %lx", argv[0], (UINT_PTR)pipe);
3048 res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0L, NULL, NULL, &si, &info);
3049 ok(res, "CreateProcess failed: %u\n", GetLastError());
3050 CloseHandle(info.hThread);
3051
3052 return info.hProcess;
3053 }
3054
create_overlapped_pipe(DWORD mode,HANDLE * client,HANDLE * server)3055 static void create_overlapped_pipe(DWORD mode, HANDLE *client, HANDLE *server)
3056 {
3057 SECURITY_ATTRIBUTES sec_attr = { sizeof(sec_attr), NULL, TRUE };
3058 DWORD read_mode = mode & (PIPE_READMODE_BYTE | PIPE_READMODE_MESSAGE);
3059 OVERLAPPED overlapped;
3060 BOOL res;
3061
3062 *server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3063 PIPE_WAIT | mode, 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
3064 ok(&server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError());
3065 test_signaled(*server);
3066
3067 memset(&overlapped, 0, sizeof(overlapped));
3068 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3069 res = ConnectNamedPipe(*server, &overlapped);
3070 ok(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%u)\n", res, GetLastError());
3071 test_not_signaled(*server);
3072 test_not_signaled(overlapped.hEvent);
3073
3074 *client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, &sec_attr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
3075 ok(*server != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
3076
3077 res = SetNamedPipeHandleState(*client, &read_mode, NULL, NULL);
3078 ok(res, "SetNamedPipeHandleState failed: %u\n", GetLastError());
3079
3080 test_signaled(*client);
3081 test_not_signaled(*server);
3082 test_overlapped_result(*server, &overlapped, 0, FALSE);
3083 }
3084
test_overlapped_transport(BOOL msg_mode,BOOL msg_read_mode)3085 static void test_overlapped_transport(BOOL msg_mode, BOOL msg_read_mode)
3086 {
3087 OVERLAPPED overlapped, overlapped2;
3088 HANDLE server, client, flush;
3089 DWORD read_bytes;
3090 HANDLE process;
3091 char buf[60000];
3092 BOOL res;
3093
3094 DWORD create_flags =
3095 (msg_mode ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) |
3096 (msg_read_mode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
3097
3098 create_overlapped_pipe(create_flags, &client, &server);
3099
3100 trace("testing %s, %s server->client writes...\n",
3101 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3102 test_blocking_rw(server, client, 5000, msg_mode, msg_read_mode);
3103 trace("testing %s, %s client->server writes...\n",
3104 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3105 test_blocking_rw(client, server, 6000, msg_mode, msg_read_mode);
3106
3107 CloseHandle(client);
3108 CloseHandle(server);
3109
3110 /* close client with pending writes */
3111 create_overlapped_pipe(create_flags, &client, &server);
3112 overlapped_write_async(server, buf, 7000, &overlapped);
3113 flush = test_flush_async(server, ERROR_BROKEN_PIPE);
3114 CloseHandle(client);
3115 test_overlapped_failure(server, &overlapped, ERROR_BROKEN_PIPE);
3116 test_flush_done(flush);
3117 CloseHandle(server);
3118
3119 /* close server with pending writes */
3120 create_overlapped_pipe(create_flags, &client, &server);
3121 overlapped_write_async(client, buf, 7000, &overlapped);
3122 flush = test_flush_async(client, ERROR_BROKEN_PIPE);
3123 CloseHandle(server);
3124 test_overlapped_failure(client, &overlapped, ERROR_BROKEN_PIPE);
3125 test_flush_done(flush);
3126 CloseHandle(client);
3127
3128 /* disconnect with pending writes */
3129 create_overlapped_pipe(create_flags, &client, &server);
3130 overlapped_write_async(client, buf, 7000, &overlapped);
3131 overlapped_write_async(server, buf, 7000, &overlapped2);
3132 flush = test_flush_async(client, ERROR_PIPE_NOT_CONNECTED);
3133 res = DisconnectNamedPipe(server);
3134 ok(res, "DisconnectNamedPipe failed: %u\n", GetLastError());
3135 test_overlapped_failure(client, &overlapped, ERROR_PIPE_NOT_CONNECTED);
3136 test_overlapped_failure(client, &overlapped2, ERROR_PIPE_NOT_CONNECTED);
3137 test_flush_done(flush);
3138 CloseHandle(server);
3139 CloseHandle(client);
3140
3141 /* terminate process with pending write */
3142 create_overlapped_pipe(create_flags, &client, &server);
3143 process = create_writepipe_process(client);
3144 /* successfully read part of write that is pending in child process */
3145 res = ReadFile(server, buf, 10, &read_bytes, NULL);
3146 if(!msg_read_mode)
3147 ok(res, "ReadFile failed: %u\n", GetLastError());
3148 else
3149 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %u\n", res, GetLastError());
3150 ok(read_bytes == 10, "read_bytes = %u\n", read_bytes);
3151 TerminateProcess(process, 0);
3152 winetest_wait_child_process(process);
3153 /* after terminating process, there is no pending write and pipe buffer is empty */
3154 overlapped_read_async(server, buf, 10, &overlapped);
3155 overlapped_write_sync(client, buf, 1);
3156 test_overlapped_result(server, &overlapped, 1, FALSE);
3157 CloseHandle(process);
3158 CloseHandle(server);
3159 CloseHandle(client);
3160 }
3161
START_TEST(pipe)3162 START_TEST(pipe)
3163 {
3164 char **argv;
3165 int argc;
3166 HMODULE hmod;
3167
3168 #if defined(__REACTOS__) && defined(_M_AMD64)
3169 if (!winetest_interactive)
3170 {
3171 skip("ROSTESTS-370: Skipping kernel32_winetest:pipe because it hangs on Windows Server 2003 x64-Testbot. Set winetest_interactive to run it anyway.\n");
3172 return;
3173 }
3174 #endif
3175
3176 hmod = GetModuleHandleA("advapi32.dll");
3177 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
3178 hmod = GetModuleHandleA("kernel32.dll");
3179 pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
3180 pCancelIoEx = (void *) GetProcAddress(hmod, "CancelIoEx");
3181
3182 argc = winetest_get_mainargs(&argv);
3183
3184 if (argc > 3 && !strcmp(argv[2], "writepipe"))
3185 {
3186 UINT_PTR handle;
3187 sscanf(argv[3], "%lx", &handle);
3188 child_process_write_pipe((HANDLE)handle);
3189 return;
3190 }
3191
3192 if (test_DisconnectNamedPipe())
3193 return;
3194 test_CreateNamedPipe_instances_must_match();
3195 test_NamedPipe_2();
3196 test_CreateNamedPipe(PIPE_TYPE_BYTE);
3197 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
3198 test_CreatePipe();
3199 test_ReadFile();
3200 test_CloseHandle();
3201 test_impersonation();
3202 test_overlapped();
3203 test_overlapped_error();
3204 test_NamedPipeHandleState();
3205 test_GetNamedPipeInfo();
3206 test_readfileex_pending();
3207 test_overlapped_transport(TRUE, FALSE);
3208 test_overlapped_transport(TRUE, TRUE);
3209 test_overlapped_transport(FALSE, FALSE);
3210 }
3211