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