Remove unnecessary executable bits
[reactos.git] / modules / 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 "winternl.h"
29 #include "winioctl.h"
30 #include "wine/test.h"
31
32 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
33 #define PIPENAME_SPECIAL "\\\\.\\PiPe\\tests->pipe.c"
34
35 #define NB_SERVER_LOOPS 8
36
37 static HANDLE alarm_event;
38 static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
39 SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
40 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
41 static BOOL (WINAPI *pCancelIoEx)(HANDLE handle, LPOVERLAPPED lpOverlapped);
42
43 static BOOL user_apc_ran;
44 static void CALLBACK user_apc(ULONG_PTR param)
45 {
46 user_apc_ran = TRUE;
47 }
48
49
50 enum rpcThreadOp
51 {
52 RPC_READFILE
53 };
54
55 struct rpcThreadArgs
56 {
57 ULONG_PTR returnValue;
58 DWORD lastError;
59 enum rpcThreadOp op;
60 ULONG_PTR args[5];
61 };
62
63 static DWORD CALLBACK rpcThreadMain(LPVOID arg)
64 {
65 struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
66 if (winetest_debug > 1) trace("rpcThreadMain starting\n");
67 SetLastError( rpcargs->lastError );
68
69 switch (rpcargs->op)
70 {
71 case RPC_READFILE:
72 rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */
73 (LPVOID)rpcargs->args[1], /* buffer */
74 (DWORD)rpcargs->args[2], /* bytesToRead */
75 (LPDWORD)rpcargs->args[3], /* bytesRead */
76 (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
77 break;
78
79 default:
80 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
81 rpcargs->returnValue = 0;
82 break;
83 }
84
85 rpcargs->lastError = GetLastError();
86 if (winetest_debug > 1) trace("rpcThreadMain returning\n");
87 return 0;
88 }
89
90 /* Runs ReadFile(...) from a different thread */
91 static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
92 {
93 struct rpcThreadArgs rpcargs;
94 HANDLE thread;
95 DWORD threadId, ret;
96
97 rpcargs.returnValue = 0;
98 rpcargs.lastError = GetLastError();
99 rpcargs.op = RPC_READFILE;
100 rpcargs.args[0] = (ULONG_PTR)hFile;
101 rpcargs.args[1] = (ULONG_PTR)buffer;
102 rpcargs.args[2] = (ULONG_PTR)bytesToRead;
103 rpcargs.args[3] = (ULONG_PTR)bytesRead;
104 rpcargs.args[4] = (ULONG_PTR)overlapped;
105
106 thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
107 ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
108 ret = WaitForSingleObject(thread, INFINITE);
109 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
110 CloseHandle(thread);
111
112 SetLastError(rpcargs.lastError);
113 return (BOOL)rpcargs.returnValue;
114 }
115
116 #define test_not_signaled(h) _test_not_signaled(__LINE__,h)
117 static void _test_not_signaled(unsigned line, HANDLE handle)
118 {
119 DWORD res = WaitForSingleObject(handle, 0);
120 ok_(__FILE__,line)(res == WAIT_TIMEOUT, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
121 }
122
123 #define test_signaled(h) _test_signaled(__LINE__,h)
124 static void _test_signaled(unsigned line, HANDLE handle)
125 {
126 DWORD res = WaitForSingleObject(handle, 0);
127 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
128 }
129
130 #define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
131 static void _test_pipe_info(unsigned line, HANDLE pipe, DWORD ex_flags, DWORD ex_out_buf_size, DWORD ex_in_buf_size, DWORD ex_max_instances)
132 {
133 DWORD flags = 0xdeadbeef, out_buf_size = 0xdeadbeef, in_buf_size = 0xdeadbeef, max_instances = 0xdeadbeef;
134 BOOL res;
135
136 res = GetNamedPipeInfo(pipe, &flags, &out_buf_size, &in_buf_size, &max_instances);
137 ok_(__FILE__,line)(res, "GetNamedPipeInfo failed: %x\n", res);
138 ok_(__FILE__,line)(flags == ex_flags, "flags = %x, expected %x\n", flags, ex_flags);
139 ok_(__FILE__,line)(out_buf_size == ex_out_buf_size, "out_buf_size = %x, expected %u\n", out_buf_size, ex_out_buf_size);
140 ok_(__FILE__,line)(in_buf_size == ex_in_buf_size, "in_buf_size = %x, expected %u\n", in_buf_size, ex_in_buf_size);
141 ok_(__FILE__,line)(max_instances == ex_max_instances, "max_instances = %x, expected %u\n", max_instances, ex_max_instances);
142 }
143
144 static void test_CreateNamedPipe(int pipemode)
145 {
146 HANDLE hnp;
147 HANDLE hFile;
148 static const char obuf[] = "Bit Bucket";
149 static const char obuf2[] = "More bits";
150 char ibuf[32], *pbuf;
151 DWORD written;
152 DWORD readden;
153 DWORD avail;
154 DWORD left;
155 DWORD lpmode;
156 BOOL ret;
157
158 if (pipemode == PIPE_TYPE_BYTE)
159 trace("test_CreateNamedPipe starting in byte mode\n");
160 else
161 trace("test_CreateNamedPipe starting in message mode\n");
162
163 /* Wait for nonexistent pipe */
164 ret = WaitNamedPipeA(PIPENAME, 2000);
165 ok(ret == 0, "WaitNamedPipe returned %d for nonexistent pipe\n", ret);
166 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
167
168 /* Bad parameter checks */
169 hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
170 /* nMaxInstances */ 1,
171 /* nOutBufSize */ 1024,
172 /* nInBufSize */ 1024,
173 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
174 /* lpSecurityAttrib */ NULL);
175 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
176 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
177
178 if (pipemode == PIPE_TYPE_BYTE)
179 {
180 /* Bad parameter checks */
181 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
182 /* nMaxInstances */ 1,
183 /* nOutBufSize */ 1024,
184 /* nInBufSize */ 1024,
185 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
186 /* lpSecurityAttrib */ NULL);
187 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
188 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
189 }
190
191 hnp = CreateNamedPipeA(NULL,
192 PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
193 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
194 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
195 "CreateNamedPipe should fail if name is NULL\n");
196
197 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
198 ok(hFile == INVALID_HANDLE_VALUE
199 && GetLastError() == ERROR_FILE_NOT_FOUND,
200 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
201
202 /* Functional checks */
203
204 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
205 /* nMaxInstances */ 1,
206 /* nOutBufSize */ 1024,
207 /* nInBufSize */ 1024,
208 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
209 /* lpSecurityAttrib */ NULL);
210 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
211 test_signaled(hnp);
212
213 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
214 todo_wine
215 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%u)\n",
216 ret, GetLastError());
217
218 ret = WaitNamedPipeA(PIPENAME, 2000);
219 ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
220
221 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
222 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
223
224 ok(!WaitNamedPipeA(PIPENAME, 100), "WaitNamedPipe succeeded\n");
225
226 ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
227
228 /* Test ConnectNamedPipe() in both directions */
229 ok(!ConnectNamedPipe(hnp, NULL), "ConnectNamedPipe(server) succeeded\n");
230 ok(GetLastError() == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", GetLastError());
231 ok(!ConnectNamedPipe(hFile, NULL), "ConnectNamedPipe(client) succeeded\n");
232 ok(GetLastError() == ERROR_INVALID_FUNCTION, "expected ERROR_INVALID_FUNCTION, got %u\n", GetLastError());
233
234 /* don't try to do i/o if one side couldn't be opened, as it hangs */
235 if (hFile != INVALID_HANDLE_VALUE) {
236 HANDLE hFile2;
237
238 /* Make sure we can read and write a few bytes in both directions */
239 memset(ibuf, 0, sizeof(ibuf));
240 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
241 ok(written == sizeof(obuf), "write file len\n");
242 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
243 ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
244 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
245
246 memset(ibuf, 0, sizeof(ibuf));
247 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
248 ok(written == sizeof(obuf2), "write file len\n");
249 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
250 ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
251 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
252
253 /* Now the same again, but with an additional call to PeekNamedPipe */
254 memset(ibuf, 0, sizeof(ibuf));
255 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
256 ok(written == sizeof(obuf), "write file len 1\n");
257 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &avail, &left), "Peek\n");
258 ok(avail == sizeof(obuf), "peek 1 got %d bytes\n", avail);
259 if (pipemode == PIPE_TYPE_BYTE)
260 ok(left == 0, "peek 1 got %d bytes left\n", left);
261 else
262 ok(left == sizeof(obuf), "peek 1 got %d bytes left\n", left);
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, &avail, &left), "Peek\n");
271 ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
272 if (pipemode == PIPE_TYPE_BYTE)
273 ok(left == 0, "peek 2 got %d bytes left\n", left);
274 else
275 ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
276 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &avail, &left), "Peek\n");
277 ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
278 if (pipemode == PIPE_TYPE_BYTE)
279 ok(left == 0, "peek 2 got %d bytes left\n", left);
280 else
281 ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
282 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
283 ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
284 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
285
286 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
287 memset(ibuf, 0, sizeof(ibuf));
288 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
289 ok(written == sizeof(obuf2), "write file len\n");
290 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek\n");
291 ok(readden == 4, "peek got %d bytes\n", readden);
292 ok(avail == sizeof(obuf2), "peek got %d bytes available\n", avail);
293 if (pipemode == PIPE_TYPE_BYTE)
294 ok(left == -4, "peek got %d bytes left\n", left);
295 else
296 ok(left == sizeof(obuf2)-4, "peek got %d bytes left\n", left);
297 ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
298 ok(readden == 4, "read got %d bytes\n", readden);
299 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
300 ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
301 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
302
303 memset(ibuf, 0, sizeof(ibuf));
304 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
305 ok(written == sizeof(obuf), "write file len\n");
306 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek\n");
307 ok(readden == 4, "peek got %d bytes\n", readden);
308 ok(avail == sizeof(obuf), "peek got %d bytes available\n", avail);
309 if (pipemode == PIPE_TYPE_BYTE)
310 {
311 ok(left == -4, "peek got %d bytes left\n", left);
312 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
313 }
314 else
315 {
316 ok(left == sizeof(obuf)-4, "peek got %d bytes left\n", left);
317 SetLastError(0xdeadbeef);
318 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
319 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
320 }
321 ok(readden == 4, "read got %d bytes\n", readden);
322 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
323 ok(readden == sizeof(obuf) - 4, "read got %d bytes\n", readden);
324 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
325
326 /* Similar to above, but use a read buffer size small enough to read in three parts */
327 memset(ibuf, 0, sizeof(ibuf));
328 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
329 ok(written == sizeof(obuf2), "write file len\n");
330 if (pipemode == PIPE_TYPE_BYTE)
331 {
332 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
333 ok(readden == 4, "read got %d bytes\n", readden);
334 ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
335 }
336 else
337 {
338 SetLastError(0xdeadbeef);
339 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
340 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
341 ok(readden == 4, "read got %d bytes\n", readden);
342 SetLastError(0xdeadbeef);
343 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
344 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
345 }
346 ok(readden == 4, "read got %d bytes\n", readden);
347 ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n");
348 ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden);
349 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
350
351 /* Test reading of multiple writes */
352 memset(ibuf, 0, sizeof(ibuf));
353 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
354 ok(written == sizeof(obuf), "write file len 3a\n");
355 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
356 ok(written == sizeof(obuf2), "write file len 3b\n");
357 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek3\n");
358 ok(readden == 4, "peek3 got %d bytes\n", readden);
359 if (pipemode == PIPE_TYPE_BYTE)
360 ok(left == -4, "peek3 got %d bytes left\n", left);
361 else
362 ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
363 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
364 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek3\n");
365 if (pipemode == PIPE_TYPE_BYTE) {
366 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
367 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek3 got %d bytes left\n", left);
368 }
369 else
370 {
371 ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
372 ok(left == 0, "peek3 got %d bytes left\n", left);
373 }
374 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
375 pbuf = ibuf;
376 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
377 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
378 pbuf += sizeof(obuf);
379 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
380 }
381 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
382 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
383 pbuf = ibuf;
384 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
385 pbuf += sizeof(obuf);
386 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
387
388 /* Multiple writes in the reverse direction */
389 memset(ibuf, 0, sizeof(ibuf));
390 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
391 ok(written == sizeof(obuf), "write file len 4a\n");
392 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
393 ok(written == sizeof(obuf2), "write file len 4b\n");
394 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek3\n");
395 ok(readden == 4, "peek3 got %d bytes\n", readden);
396 if (pipemode == PIPE_TYPE_BYTE)
397 ok(left == -4, "peek3 got %d bytes left\n", left);
398 else
399 ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
400 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
401 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek4\n");
402 if (pipemode == PIPE_TYPE_BYTE) {
403 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
404 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek4 got %d bytes left\n", left);
405 }
406 else
407 {
408 ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
409 ok(left == 0, "peek4 got %d bytes left\n", left);
410 }
411 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
412 pbuf = ibuf;
413 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
414 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
415 pbuf += sizeof(obuf);
416 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
417 }
418 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
419 if (pipemode == PIPE_TYPE_BYTE) {
420 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
421 }
422 else {
423 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
424 }
425 pbuf = ibuf;
426 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
427 if (pipemode == PIPE_TYPE_BYTE) {
428 pbuf += sizeof(obuf);
429 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
430 }
431
432 /* Test reading of multiple writes after a mode change
433 (CreateFile always creates a byte mode pipe) */
434 lpmode = PIPE_READMODE_MESSAGE;
435 if (pipemode == PIPE_TYPE_BYTE) {
436 /* trying to change the client end of a byte pipe to message mode should fail */
437 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
438 }
439 else {
440 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
441
442 memset(ibuf, 0, sizeof(ibuf));
443 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
444 ok(written == sizeof(obuf), "write file len 3a\n");
445 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
446 ok(written == sizeof(obuf2), "write file len 3b\n");
447 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek5\n");
448 ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
449 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
450 ok(left == 0, "peek5 got %d bytes left\n", left);
451 pbuf = ibuf;
452 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
453 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
454 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
455 pbuf = ibuf;
456 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
457 if (readden <= sizeof(obuf))
458 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
459
460 /* Multiple writes in the reverse direction */
461 /* the write of obuf2 from write4 should still be in the buffer */
462 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
463 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
464 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
465 if (avail > 0) {
466 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
467 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
468 pbuf = ibuf;
469 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
470 }
471 memset(ibuf, 0, sizeof(ibuf));
472 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
473 ok(written == sizeof(obuf), "write file len 6a\n");
474 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
475 ok(written == sizeof(obuf2), "write file len 6b\n");
476 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
477 ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
478
479 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
480 pbuf = ibuf;
481 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
482 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
483 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
484 pbuf = ibuf;
485 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
486 if (readden <= sizeof(obuf))
487 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
488
489 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
490 memset(ibuf, 0, sizeof(ibuf));
491 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
492 ok(written == sizeof(obuf2), "write file len 7\n");
493 SetLastError(0xdeadbeef);
494 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
495 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
496 ok(readden == 4, "read got %d bytes 7\n", readden);
497 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
498 ok(readden == sizeof(obuf2) - 4, "read got %d bytes 7\n", readden);
499 ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n");
500
501 memset(ibuf, 0, sizeof(ibuf));
502 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
503 ok(written == sizeof(obuf), "write file len 8\n");
504 SetLastError(0xdeadbeef);
505 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
506 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
507 ok(readden == 4, "read got %d bytes 8\n", readden);
508 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
509 ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden);
510 ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
511
512 /* The following test shows that when doing a partial read of a message, the rest
513 * is still in the pipe, and can be received from a second thread. This shows
514 * especially that the content is _not_ stored in thread-local-storage until it is
515 * completely transmitted. The same method works even across multiple processes. */
516 memset(ibuf, 0, sizeof(ibuf));
517 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
518 ok(written == sizeof(obuf), "write file len 9\n");
519 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
520 ok(written == sizeof(obuf2), "write file len 9\n");
521 SetLastError(0xdeadbeef);
522 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
523 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
524 ok(readden == 4, "read got %d bytes 9\n", readden);
525 SetLastError(0xdeadbeef);
526 ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
527 ok(!ret, "RpcReadFile 9\n");
528 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
529 ok(readden == 4, "read got %d bytes 9\n", readden);
530 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
531 ok(ret, "RpcReadFile 9\n");
532 ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
533 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
534 if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
535 {
536 memset(ibuf, 0, sizeof(ibuf));
537 SetLastError(0xdeadbeef);
538 ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
539 ok(!ret, "RpcReadFile 9\n");
540 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
541 ok(readden == 4, "read got %d bytes 9\n", readden);
542 SetLastError(0xdeadbeef);
543 ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
544 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
545 ok(readden == 4, "read got %d bytes 9\n", readden);
546 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
547 ok(ret, "RpcReadFile 9\n");
548 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
549 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
550 }
551
552 /* Now the reverse direction */
553 memset(ibuf, 0, sizeof(ibuf));
554 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
555 ok(written == sizeof(obuf2), "write file len 10\n");
556 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
557 ok(written == sizeof(obuf), "write file len 10\n");
558 SetLastError(0xdeadbeef);
559 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
560 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
561 ok(readden == 4, "read got %d bytes 10\n", readden);
562 SetLastError(0xdeadbeef);
563 ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
564 ok(!ret, "RpcReadFile 10\n");
565 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
566 ok(readden == 4, "read got %d bytes 10\n", readden);
567 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
568 ok(ret, "RpcReadFile 10\n");
569 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
570 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
571 if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
572 {
573 memset(ibuf, 0, sizeof(ibuf));
574 SetLastError(0xdeadbeef);
575 ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
576 ok(!ret, "RpcReadFile 10\n");
577 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
578 ok(readden == 4, "read got %d bytes 10\n", readden);
579 SetLastError(0xdeadbeef);
580 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
581 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
582 ok(readden == 4, "read got %d bytes 10\n", readden);
583 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
584 ok(ret, "RpcReadFile 10\n");
585 ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
586 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
587 }
588
589 }
590
591 /* Picky conformance tests */
592
593 /* Verify that you can't connect to pipe again
594 * until server calls DisconnectNamedPipe+ConnectNamedPipe
595 * or creates a new pipe
596 * case 1: other client not yet closed
597 */
598 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
599 ok(hFile2 == INVALID_HANDLE_VALUE,
600 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
601 ok(GetLastError() == ERROR_PIPE_BUSY,
602 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
603
604 ok(CloseHandle(hFile), "CloseHandle\n");
605
606 /* case 2: other client already closed */
607 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
608 ok(hFile == INVALID_HANDLE_VALUE,
609 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
610 ok(GetLastError() == ERROR_PIPE_BUSY,
611 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
612
613 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
614
615 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
616 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
617 ok(hFile == INVALID_HANDLE_VALUE,
618 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
619 ok(GetLastError() == ERROR_PIPE_BUSY,
620 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
621
622 /* to be complete, we'd call ConnectNamedPipe here and loop,
623 * but by default that's blocking, so we'd either have
624 * to turn on the uncommon nonblocking mode, or
625 * use another thread.
626 */
627 }
628
629 ok(CloseHandle(hnp), "CloseHandle\n");
630
631 hnp = CreateNamedPipeA(PIPENAME_SPECIAL, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
632 /* nMaxInstances */ 1,
633 /* nOutBufSize */ 1024,
634 /* nInBufSize */ 1024,
635 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
636 /* lpSecurityAttrib */ NULL);
637 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe with special characters failed\n");
638 ok(CloseHandle(hnp), "CloseHandle\n");
639
640 if (winetest_debug > 1) trace("test_CreateNamedPipe returning\n");
641 }
642
643 static void test_CreateNamedPipe_instances_must_match(void)
644 {
645 HANDLE hnp, hnp2;
646
647 /* Check no mismatch */
648 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
649 /* nMaxInstances */ 2,
650 /* nOutBufSize */ 1024,
651 /* nInBufSize */ 1024,
652 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
653 /* lpSecurityAttrib */ NULL);
654 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
655
656 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
657 /* nMaxInstances */ 2,
658 /* nOutBufSize */ 1024,
659 /* nInBufSize */ 1024,
660 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
661 /* lpSecurityAttrib */ NULL);
662 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
663
664 ok(CloseHandle(hnp), "CloseHandle\n");
665 ok(CloseHandle(hnp2), "CloseHandle\n");
666
667 /* Check nMaxInstances */
668 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
669 /* nMaxInstances */ 1,
670 /* nOutBufSize */ 1024,
671 /* nInBufSize */ 1024,
672 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
673 /* lpSecurityAttrib */ NULL);
674 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
675
676 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
677 /* nMaxInstances */ 1,
678 /* nOutBufSize */ 1024,
679 /* nInBufSize */ 1024,
680 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
681 /* lpSecurityAttrib */ NULL);
682 ok(hnp2 == INVALID_HANDLE_VALUE
683 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
684
685 ok(CloseHandle(hnp), "CloseHandle\n");
686
687 /* Check PIPE_ACCESS_* */
688 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
689 /* nMaxInstances */ 2,
690 /* nOutBufSize */ 1024,
691 /* nInBufSize */ 1024,
692 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
693 /* lpSecurityAttrib */ NULL);
694 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
695
696 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
697 /* nMaxInstances */ 2,
698 /* nOutBufSize */ 1024,
699 /* nInBufSize */ 1024,
700 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
701 /* lpSecurityAttrib */ NULL);
702 ok(hnp2 == INVALID_HANDLE_VALUE
703 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
704
705 ok(CloseHandle(hnp), "CloseHandle\n");
706
707 /* check everything else */
708 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
709 /* nMaxInstances */ 4,
710 /* nOutBufSize */ 1024,
711 /* nInBufSize */ 1024,
712 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
713 /* lpSecurityAttrib */ NULL);
714 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
715
716 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
717 /* nMaxInstances */ 3,
718 /* nOutBufSize */ 102,
719 /* nInBufSize */ 24,
720 /* nDefaultWait */ 1234,
721 /* lpSecurityAttrib */ NULL);
722 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
723
724 ok(CloseHandle(hnp), "CloseHandle\n");
725 ok(CloseHandle(hnp2), "CloseHandle\n");
726 }
727
728 static void test_ReadFile(void)
729 {
730 HANDLE server, client;
731 OVERLAPPED overlapped;
732 DWORD size;
733 BOOL res;
734
735 static char buf[512];
736
737 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
738 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
739 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
740 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
741
742 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
743 OPEN_EXISTING, 0, 0);
744 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
745
746 ok(WriteFile(client, buf, sizeof(buf), &size, NULL), "WriteFile\n");
747
748 res = ReadFile(server, buf, 1, &size, NULL);
749 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%u)\n", res, GetLastError());
750 ok(size == 1, "size = %u\n", size);
751
752 /* pass both overlapped and ret read */
753 memset(&overlapped, 0, sizeof(overlapped));
754 res = ReadFile(server, buf, 1, &size, &overlapped);
755 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%u)\n", res, GetLastError());
756 ok(size == 0, "size = %u\n", size);
757 ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "Internal = %lx\n", overlapped.Internal);
758 ok(overlapped.InternalHigh == 1, "InternalHigh = %lx\n", overlapped.InternalHigh);
759
760 DisconnectNamedPipe(server);
761
762 memset(&overlapped, 0, sizeof(overlapped));
763 overlapped.InternalHigh = 0xdeadbeef;
764 res = ReadFile(server, buf, 1, &size, &overlapped);
765 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%u)\n", res, GetLastError());
766 ok(size == 0, "size = %u\n", size);
767 ok(overlapped.Internal == STATUS_PENDING, "Internal = %lx\n", overlapped.Internal);
768 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %lx\n", overlapped.InternalHigh);
769
770 memset(&overlapped, 0, sizeof(overlapped));
771 overlapped.InternalHigh = 0xdeadbeef;
772 res = WriteFile(server, buf, 1, &size, &overlapped);
773 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%u)\n", res, GetLastError());
774 ok(size == 0, "size = %u\n", size);
775 ok(overlapped.Internal == STATUS_PENDING, "Internal = %lx\n", overlapped.Internal);
776 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %lx\n", overlapped.InternalHigh);
777
778 CloseHandle(server);
779 CloseHandle(client);
780 }
781
782 /** implementation of alarm() */
783 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
784 {
785 DWORD_PTR timeout = (DWORD_PTR) arg;
786 if (winetest_debug > 1) trace("alarmThreadMain\n");
787 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
788 {
789 ok(FALSE, "alarm\n");
790 ExitProcess(1);
791 }
792 return 1;
793 }
794
795 static HANDLE hnp = INVALID_HANDLE_VALUE;
796
797 /** Trivial byte echo server - disconnects after each session */
798 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
799 {
800 int i;
801
802 if (winetest_debug > 1) trace("serverThreadMain1 start\n");
803 /* Set up a simple echo server */
804 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
805 PIPE_TYPE_BYTE | PIPE_WAIT,
806 /* nMaxInstances */ 1,
807 /* nOutBufSize */ 1024,
808 /* nInBufSize */ 1024,
809 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
810 /* lpSecurityAttrib */ NULL);
811
812 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
813 for (i = 0; i < NB_SERVER_LOOPS; i++) {
814 char buf[512];
815 DWORD written;
816 DWORD readden;
817 BOOL success;
818
819 /* Wait for client to connect */
820 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
821 ok(ConnectNamedPipe(hnp, NULL)
822 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
823 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
824
825 /* Echo bytes once */
826 memset(buf, 0, sizeof(buf));
827
828 if (winetest_debug > 1) trace("Server reading...\n");
829 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
830 if (winetest_debug > 1) trace("Server done reading.\n");
831 ok(success, "ReadFile\n");
832 ok(readden, "short read\n");
833
834 if (winetest_debug > 1) trace("Server writing...\n");
835 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
836 if (winetest_debug > 1) trace("Server done writing.\n");
837 ok(written == readden, "write file len\n");
838
839 /* finish this connection, wait for next one */
840 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
841 if (winetest_debug > 1) trace("Server done flushing.\n");
842 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
843 if (winetest_debug > 1) trace("Server done disconnecting.\n");
844 }
845 return 0;
846 }
847
848 /** Trivial byte echo server - closes after each connection */
849 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
850 {
851 int i;
852 HANDLE hnpNext = 0;
853
854 trace("serverThreadMain2\n");
855 /* Set up a simple echo server */
856 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
857 PIPE_TYPE_BYTE | PIPE_WAIT,
858 /* nMaxInstances */ 2,
859 /* nOutBufSize */ 1024,
860 /* nInBufSize */ 1024,
861 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
862 /* lpSecurityAttrib */ NULL);
863 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
864
865 for (i = 0; i < NB_SERVER_LOOPS; i++) {
866 char buf[512];
867 DWORD written;
868 DWORD readden;
869 DWORD ret;
870 BOOL success;
871
872
873 user_apc_ran = FALSE;
874 if (i == 0 && pQueueUserAPC) {
875 if (winetest_debug > 1) trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
876 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
877 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
878 }
879
880 /* Wait for client to connect */
881 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
882 ok(ConnectNamedPipe(hnp, NULL)
883 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
884 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
885
886 /* Echo bytes once */
887 memset(buf, 0, sizeof(buf));
888
889 if (winetest_debug > 1) trace("Server reading...\n");
890 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
891 if (winetest_debug > 1) trace("Server done reading.\n");
892 ok(success, "ReadFile\n");
893
894 if (winetest_debug > 1) trace("Server writing...\n");
895 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
896 if (winetest_debug > 1) trace("Server done writing.\n");
897 ok(written == readden, "write file len\n");
898
899 /* finish this connection, wait for next one */
900 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
901 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
902
903 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
904
905 if (i == 0 && pQueueUserAPC)
906 SleepEx(0, TRUE); /* get rid of apc */
907
908 /* Set up next echo server */
909 hnpNext =
910 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
911 PIPE_TYPE_BYTE | PIPE_WAIT,
912 /* nMaxInstances */ 2,
913 /* nOutBufSize */ 1024,
914 /* nInBufSize */ 1024,
915 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
916 /* lpSecurityAttrib */ NULL);
917
918 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
919
920 ok(CloseHandle(hnp), "CloseHandle\n");
921 hnp = hnpNext;
922 }
923 return 0;
924 }
925
926 /** Trivial byte echo server - uses overlapped named pipe calls */
927 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
928 {
929 int i;
930 HANDLE hEvent;
931
932 if (winetest_debug > 1) trace("serverThreadMain3\n");
933 /* Set up a simple echo server */
934 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
935 PIPE_TYPE_BYTE | PIPE_WAIT,
936 /* nMaxInstances */ 1,
937 /* nOutBufSize */ 1024,
938 /* nInBufSize */ 1024,
939 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
940 /* lpSecurityAttrib */ NULL);
941 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
942
943 hEvent = CreateEventW(NULL, /* security attribute */
944 TRUE, /* manual reset event */
945 FALSE, /* initial state */
946 NULL); /* name */
947 ok(hEvent != NULL, "CreateEvent\n");
948
949 for (i = 0; i < NB_SERVER_LOOPS; i++) {
950 char buf[512];
951 DWORD written;
952 DWORD readden;
953 DWORD dummy;
954 BOOL success;
955 OVERLAPPED oOverlap;
956 int letWFSOEwait = (i & 2);
957 int letGORwait = (i & 1);
958 DWORD err;
959
960 memset(&oOverlap, 0, sizeof(oOverlap));
961 oOverlap.hEvent = hEvent;
962
963 /* Wait for client to connect */
964 if (i == 0) {
965 if (winetest_debug > 1) trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
966 success = ConnectNamedPipe(hnp, NULL);
967 err = GetLastError();
968 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
969 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
970 } else {
971 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
972 success = ConnectNamedPipe(hnp, &oOverlap);
973 err = GetLastError();
974 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
975 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe returned.\n");
976 if (!success && (err == ERROR_IO_PENDING)) {
977 if (letWFSOEwait)
978 {
979 DWORD ret;
980 do {
981 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
982 } while (ret == WAIT_IO_COMPLETION);
983 ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
984 }
985 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
986 if (!letGORwait && !letWFSOEwait && !success) {
987 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
988 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
989 }
990 }
991 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
992 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
993 }
994
995 /* Echo bytes once */
996 memset(buf, 0, sizeof(buf));
997
998 if (winetest_debug > 1) trace("Server reading...\n");
999 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
1000 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1001 err = GetLastError();
1002 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
1003 if (winetest_debug > 1) trace("overlapped ReadFile returned.\n");
1004 if (!success && (err == ERROR_IO_PENDING)) {
1005 if (letWFSOEwait)
1006 {
1007 DWORD ret;
1008 do {
1009 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1010 } while (ret == WAIT_IO_COMPLETION);
1011 ok(ret == 0, "wait ReadFile returned %x\n", ret);
1012 }
1013 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
1014 if (!letGORwait && !letWFSOEwait && !success) {
1015 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1016 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
1017 }
1018 }
1019 if (winetest_debug > 1) trace("Server done reading.\n");
1020 ok(success, "overlapped ReadFile\n");
1021
1022 if (winetest_debug > 1) trace("Server writing...\n");
1023 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
1024 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1025 err = GetLastError();
1026 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
1027 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1028 if (!success && (err == ERROR_IO_PENDING)) {
1029 if (letWFSOEwait)
1030 {
1031 DWORD ret;
1032 do {
1033 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1034 } while (ret == WAIT_IO_COMPLETION);
1035 ok(ret == 0, "wait WriteFile returned %x\n", ret);
1036 }
1037 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
1038 if (!letGORwait && !letWFSOEwait && !success) {
1039 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1040 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
1041 }
1042 }
1043 if (winetest_debug > 1) trace("Server done writing.\n");
1044 ok(success, "overlapped WriteFile\n");
1045 ok(written == readden, "write file len\n");
1046
1047 /* finish this connection, wait for next one */
1048 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1049 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1050 }
1051 return 0;
1052 }
1053
1054 /** Trivial byte echo server - uses i/o completion ports */
1055 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
1056 {
1057 int i;
1058 HANDLE hcompletion;
1059 BOOL ret;
1060
1061 if (winetest_debug > 1) trace("serverThreadMain4\n");
1062 /* Set up a simple echo server */
1063 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1064 PIPE_TYPE_BYTE | PIPE_WAIT,
1065 /* nMaxInstances */ 1,
1066 /* nOutBufSize */ 1024,
1067 /* nInBufSize */ 1024,
1068 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1069 /* lpSecurityAttrib */ NULL);
1070 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1071
1072 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
1073 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
1074
1075 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1076 char buf[512];
1077 DWORD written;
1078 DWORD readden;
1079 DWORD dummy;
1080 BOOL success;
1081 OVERLAPPED oConnect;
1082 OVERLAPPED oRead;
1083 OVERLAPPED oWrite;
1084 OVERLAPPED *oResult;
1085 DWORD err;
1086 ULONG_PTR compkey;
1087
1088 memset(&oConnect, 0, sizeof(oConnect));
1089 memset(&oRead, 0, sizeof(oRead));
1090 memset(&oWrite, 0, sizeof(oWrite));
1091
1092 /* Wait for client to connect */
1093 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1094 success = ConnectNamedPipe(hnp, &oConnect);
1095 err = GetLastError();
1096 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
1097 "overlapped ConnectNamedPipe got %u err %u\n", success, err );
1098 if (!success && err == ERROR_IO_PENDING) {
1099 if (winetest_debug > 1) trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
1100 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
1101 if (!success)
1102 {
1103 ok( GetLastError() == WAIT_TIMEOUT,
1104 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
1105 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
1106 }
1107 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1108 if (success)
1109 {
1110 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1111 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
1112 }
1113 }
1114 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
1115
1116 /* Echo bytes once */
1117 memset(buf, 0, sizeof(buf));
1118
1119 if (winetest_debug > 1) trace("Server reading...\n");
1120 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1121 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1122 err = GetLastError();
1123 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
1124 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1125 &oResult, 10000);
1126 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1127 if (success)
1128 {
1129 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1130 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
1131 }
1132 if (winetest_debug > 1) trace("Server done reading.\n");
1133
1134 if (winetest_debug > 1) trace("Server writing...\n");
1135 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1136 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1137 err = GetLastError();
1138 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
1139 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1140 &oResult, 10000);
1141 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1142 if (success)
1143 {
1144 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1145 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
1146 ok(written == readden, "write file len\n");
1147 }
1148 if (winetest_debug > 1) trace("Server done writing.\n");
1149
1150 /* Client will finish this connection, the following ops will trigger broken pipe errors. */
1151
1152 /* Wait for the pipe to break. */
1153 while (PeekNamedPipe(hnp, NULL, 0, NULL, &written, &written));
1154
1155 if (winetest_debug > 1) trace("Server writing on disconnected pipe...\n");
1156 SetLastError(ERROR_SUCCESS);
1157 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1158 err = GetLastError();
1159 todo_wine_if (!success && err == ERROR_PIPE_NOT_CONNECTED) ok(!success && err == ERROR_NO_DATA,
1160 "overlapped WriteFile on disconnected pipe returned %u, err=%i\n", success, err);
1161
1162 /* No completion status is queued on immediate error. */
1163 SetLastError(ERROR_SUCCESS);
1164 oResult = (OVERLAPPED *)0xdeadbeef;
1165 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1166 &oResult, 0);
1167 err = GetLastError();
1168 ok(!success && err == WAIT_TIMEOUT && !oResult,
1169 "WriteFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p\n",
1170 success, err, oResult);
1171
1172 if (winetest_debug > 1) trace("Server reading from disconnected pipe...\n");
1173 SetLastError(ERROR_SUCCESS);
1174 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1175 if (winetest_debug > 1) trace("Server ReadFile from disconnected pipe returned...\n");
1176 err = GetLastError();
1177 ok(!success && err == ERROR_BROKEN_PIPE,
1178 "overlapped ReadFile on disconnected pipe returned %u, err=%i\n", success, err);
1179
1180 SetLastError(ERROR_SUCCESS);
1181 oResult = (OVERLAPPED *)0xdeadbeef;
1182 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1183 &oResult, 0);
1184 err = GetLastError();
1185 ok(!success && err == WAIT_TIMEOUT && !oResult,
1186 "ReadFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p\n",
1187 success, err, oResult);
1188
1189 /* finish this connection, wait for next one */
1190 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1191 success = DisconnectNamedPipe(hnp);
1192 ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
1193 }
1194
1195 ret = CloseHandle(hnp);
1196 ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
1197 ret = CloseHandle(hcompletion);
1198 ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
1199
1200 return 0;
1201 }
1202
1203 static int completion_called;
1204 static DWORD completion_errorcode;
1205 static DWORD completion_num_bytes;
1206 static LPOVERLAPPED completion_lpoverlapped;
1207
1208 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
1209 {
1210 completion_called++;
1211 completion_errorcode = errorcode;
1212 completion_num_bytes = num_bytes;
1213 completion_lpoverlapped = lpoverlapped;
1214 SetEvent(lpoverlapped->hEvent);
1215 }
1216
1217 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
1218 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
1219 {
1220 int i;
1221 HANDLE hEvent;
1222
1223 if (winetest_debug > 1) trace("serverThreadMain5\n");
1224 /* Set up a simple echo server */
1225 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1226 PIPE_TYPE_BYTE | PIPE_WAIT,
1227 /* nMaxInstances */ 1,
1228 /* nOutBufSize */ 1024,
1229 /* nInBufSize */ 1024,
1230 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1231 /* lpSecurityAttrib */ NULL);
1232 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1233
1234 hEvent = CreateEventW(NULL, /* security attribute */
1235 TRUE, /* manual reset event */
1236 FALSE, /* initial state */
1237 NULL); /* name */
1238 ok(hEvent != NULL, "CreateEvent\n");
1239
1240 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1241 char buf[512];
1242 DWORD readden;
1243 BOOL success;
1244 OVERLAPPED oOverlap;
1245 DWORD err;
1246
1247 memset(&oOverlap, 0, sizeof(oOverlap));
1248 oOverlap.hEvent = hEvent;
1249
1250 /* Wait for client to connect */
1251 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
1252 success = ConnectNamedPipe(hnp, NULL);
1253 err = GetLastError();
1254 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
1255 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1256
1257 /* Echo bytes once */
1258 memset(buf, 0, sizeof(buf));
1259
1260 if (winetest_debug > 1) trace("Server reading...\n");
1261 completion_called = 0;
1262 ResetEvent(hEvent);
1263 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
1264 if (winetest_debug > 1) trace("Server ReadFileEx returned...\n");
1265 ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
1266 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1267 if (winetest_debug > 1) trace("ReadFileEx returned.\n");
1268 if (success) {
1269 DWORD ret;
1270 do {
1271 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1272 } while (ret == WAIT_IO_COMPLETION);
1273 ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
1274 }
1275 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1276 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1277 ok(completion_num_bytes != 0, "read 0 bytes\n");
1278 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1279 readden = completion_num_bytes;
1280 if (winetest_debug > 1) trace("Server done reading.\n");
1281
1282 if (winetest_debug > 1) trace("Server writing...\n");
1283 completion_called = 0;
1284 ResetEvent(hEvent);
1285 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
1286 if (winetest_debug > 1) trace("Server WriteFileEx returned...\n");
1287 ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
1288 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1289 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1290 if (success) {
1291 DWORD ret;
1292 do {
1293 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1294 } while (ret == WAIT_IO_COMPLETION);
1295 ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
1296 }
1297 if (winetest_debug > 1) trace("Server done writing.\n");
1298 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1299 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1300 ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
1301 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1302
1303 /* finish this connection, wait for next one */
1304 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1305 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1306 }
1307 return 0;
1308 }
1309
1310 static void exercizeServer(const char *pipename, HANDLE serverThread)
1311 {
1312 int i;
1313
1314 if (winetest_debug > 1) trace("exercizeServer starting\n");
1315 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1316 HANDLE hFile=INVALID_HANDLE_VALUE;
1317 static const char obuf[] = "Bit Bucket";
1318 char ibuf[32];
1319 DWORD written;
1320 DWORD readden;
1321 int loop;
1322
1323 for (loop = 0; loop < 3; loop++) {
1324 DWORD err;
1325 if (winetest_debug > 1) trace("Client connecting...\n");
1326 /* Connect to the server */
1327 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
1328 NULL, OPEN_EXISTING, 0, 0);
1329 if (hFile != INVALID_HANDLE_VALUE)
1330 break;
1331 err = GetLastError();
1332 if (loop == 0)
1333 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
1334 else
1335 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
1336 if (winetest_debug > 1) trace("connect failed, retrying\n");
1337 Sleep(200);
1338 }
1339 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
1340
1341 /* Make sure it can echo */
1342 memset(ibuf, 0, sizeof(ibuf));
1343 if (winetest_debug > 1) trace("Client writing...\n");
1344 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1345 ok(written == sizeof(obuf), "write file len\n");
1346 if (winetest_debug > 1) trace("Client reading...\n");
1347 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1348 ok(readden == sizeof(obuf), "read file len\n");
1349 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1350
1351 if (winetest_debug > 1) trace("Client closing...\n");
1352 ok(CloseHandle(hFile), "CloseHandle\n");
1353 }
1354
1355 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1356 CloseHandle(hnp);
1357 if (winetest_debug > 1) trace("exercizeServer returning\n");
1358 }
1359
1360 static void test_NamedPipe_2(void)
1361 {
1362 HANDLE serverThread;
1363 DWORD serverThreadId;
1364 HANDLE alarmThread;
1365 DWORD alarmThreadId;
1366
1367 trace("test_NamedPipe_2 starting\n");
1368 /* Set up a twenty second timeout */
1369 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1370 SetLastError(0xdeadbeef);
1371 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1372 ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
1373
1374 /* The servers we're about to exercise do try to clean up carefully,
1375 * but to reduce the chance of a test failure due to a pipe handle
1376 * leak in the test code, we'll use a different pipe name for each server.
1377 */
1378
1379 /* Try server #1 */
1380 SetLastError(0xdeadbeef);
1381 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1382 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1383 exercizeServer(PIPENAME "serverThreadMain1", serverThread);
1384
1385 /* Try server #2 */
1386 SetLastError(0xdeadbeef);
1387 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1388 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1389 exercizeServer(PIPENAME "serverThreadMain2", serverThread);
1390
1391 /* Try server #3 */
1392 SetLastError(0xdeadbeef);
1393 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1394 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1395 exercizeServer(PIPENAME "serverThreadMain3", serverThread);
1396
1397 /* Try server #4 */
1398 SetLastError(0xdeadbeef);
1399 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1400 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1401 exercizeServer(PIPENAME "serverThreadMain4", serverThread);
1402
1403 /* Try server #5 */
1404 SetLastError(0xdeadbeef);
1405 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1406 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1407 exercizeServer(PIPENAME "serverThreadMain5", serverThread);
1408
1409 ok(SetEvent( alarm_event ), "SetEvent\n");
1410 CloseHandle( alarm_event );
1411 if (winetest_debug > 1) trace("test_NamedPipe_2 returning\n");
1412 }
1413
1414 static int test_DisconnectNamedPipe(void)
1415 {
1416 HANDLE hnp;
1417 HANDLE hFile;
1418 static const char obuf[] = "Bit Bucket";
1419 char ibuf[32];
1420 DWORD written;
1421 DWORD readden;
1422 DWORD ret;
1423
1424 SetLastError(0xdeadbeef);
1425 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1426 /* nMaxInstances */ 1,
1427 /* nOutBufSize */ 1024,
1428 /* nInBufSize */ 1024,
1429 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1430 /* lpSecurityAttrib */ NULL);
1431 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1432 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1433
1434 win_skip("Named pipes are not implemented\n");
1435 return 1;
1436 }
1437
1438 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1439 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1440 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1441 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1442
1443 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1444 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1445
1446 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1447 if (hFile != INVALID_HANDLE_VALUE) {
1448
1449 /* see what happens if server calls DisconnectNamedPipe
1450 * when there are bytes in the pipe
1451 */
1452
1453 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1454 ok(written == sizeof(obuf), "write file len\n");
1455 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1456 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1457 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1458 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1459 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1460 "ReadFile from disconnected pipe with bytes waiting\n");
1461
1462 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1463 "DisconnectNamedPipe worked twice\n");
1464 ret = WaitForSingleObject(hFile, 0);
1465 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1466
1467 ret = PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL);
1468 todo_wine
1469 ok(!ret && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "PeekNamedPipe returned %x (%u)\n",
1470 ret, GetLastError());
1471 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
1472 todo_wine
1473 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%u)\n",
1474 ret, GetLastError());
1475 ok(CloseHandle(hFile), "CloseHandle\n");
1476 }
1477
1478 ok(CloseHandle(hnp), "CloseHandle\n");
1479
1480 return 0;
1481 }
1482 static void test_CreatePipe(void)
1483 {
1484 SECURITY_ATTRIBUTES pipe_attr;
1485 HANDLE piperead, pipewrite;
1486 DWORD written;
1487 DWORD read;
1488 DWORD i, size;
1489 BYTE *buffer;
1490 char readbuf[32];
1491
1492 user_apc_ran = FALSE;
1493 if (pQueueUserAPC)
1494 ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1495
1496 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1497 pipe_attr.bInheritHandle = TRUE;
1498 pipe_attr.lpSecurityDescriptor = NULL;
1499 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1500 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 4096, 4096, 1);
1501 test_pipe_info(pipewrite, 0, 4096, 4096, 1);
1502
1503 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1504 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1505 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1506 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1507 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1508 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1509
1510 /* Now write another chunk*/
1511 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1512 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1513 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1514 /* and close the write end, read should still succeed*/
1515 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1516 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe with pending data failed\n");
1517 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1518 /* But now we need to get informed that the pipe is closed */
1519 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1520 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1521
1522 /* Try bigger chunks */
1523 size = 32768;
1524 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1525 for (i = 0; i < size; i++) buffer[i] = i;
1526 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1527 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1528 ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1529 /* and close the write end, read should still succeed*/
1530 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1531 memset( buffer, 0, size );
1532 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe with pending data failed\n");
1533 ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
1534 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1535 /* But now we need to get informed that the pipe is closed */
1536 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1537 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1538 HeapFree(GetProcessHeap(), 0, buffer);
1539
1540 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1541 SleepEx(0, TRUE); /* get rid of apc */
1542
1543 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 1) != 0, "CreatePipe failed\n");
1544 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 1, 1, 1);
1545 test_pipe_info(pipewrite, 0, 1, 1, 1);
1546 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1547 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1548 }
1549
1550 static void test_CloseHandle(void)
1551 {
1552 static const char testdata[] = "Hello World";
1553 DWORD state, numbytes;
1554 HANDLE hpipe, hfile;
1555 char buffer[32];
1556 BOOL ret;
1557
1558 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1559 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1560 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1561 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1562
1563 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1564 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1565
1566 numbytes = 0xdeadbeef;
1567 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1568 ok(ret, "WriteFile failed with %u\n", GetLastError());
1569 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1570
1571 numbytes = 0xdeadbeef;
1572 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1573 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1574 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1575
1576 ret = CloseHandle(hpipe);
1577 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1578
1579 numbytes = 0xdeadbeef;
1580 memset(buffer, 0, sizeof(buffer));
1581 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1582 ok(ret, "ReadFile failed with %u\n", GetLastError());
1583 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1584
1585 numbytes = 0xdeadbeef;
1586 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1587 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1588 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1589
1590 numbytes = 0xdeadbeef;
1591 memset(buffer, 0, sizeof(buffer));
1592 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1593 ok(ret, "ReadFile failed with %u\n", GetLastError());
1594 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1595
1596 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1597 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1598 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1599 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1600 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1601
1602 SetLastError(0xdeadbeef);
1603 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1604 ok(!ret, "ReadFile unexpectedly succeeded\n");
1605 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1606
1607 numbytes = 0xdeadbeef;
1608 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1609 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%u)\n",
1610 ret, GetLastError());
1611 ok(numbytes == 0xdeadbeef, "numbytes = %u\n", numbytes);
1612
1613 SetLastError(0xdeadbeef);
1614 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1615 ok(!ret, "WriteFile unexpectedly succeeded\n");
1616 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1617
1618 CloseHandle(hfile);
1619
1620 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1621 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1622 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1623 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1624
1625 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1626 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1627
1628 numbytes = 0xdeadbeef;
1629 ret = WriteFile(hpipe, testdata, 0, &numbytes, NULL);
1630 ok(ret, "WriteFile failed with %u\n", GetLastError());
1631 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1632
1633 ret = CloseHandle(hpipe);
1634 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1635
1636 numbytes = 0xdeadbeef;
1637 memset(buffer, 0, sizeof(buffer));
1638 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1639 ok(ret, "ReadFile failed with %u\n", GetLastError());
1640 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1641
1642 SetLastError(0xdeadbeef);
1643 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1644 ok(!ret, "ReadFile unexpectedly succeeded\n");
1645 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1646
1647 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1648 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1649 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1650 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1651 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1652
1653 SetLastError(0xdeadbeef);
1654 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1655 ok(!ret, "ReadFile unexpectedly succeeded\n");
1656 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1657
1658 SetLastError(0xdeadbeef);
1659 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1660 ok(!ret, "WriteFile unexpectedly succeeded\n");
1661 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1662
1663 CloseHandle(hfile);
1664
1665 /* repeat test with hpipe <-> hfile swapped */
1666
1667 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1668 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1669 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1670 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1671
1672 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1673 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1674
1675 numbytes = 0xdeadbeef;
1676 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1677 ok(ret, "WriteFile failed with %u\n", GetLastError());
1678 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1679
1680 numbytes = 0xdeadbeef;
1681 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1682 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1683 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1684
1685 ret = CloseHandle(hfile);
1686 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1687
1688 numbytes = 0xdeadbeef;
1689 memset(buffer, 0, sizeof(buffer));
1690 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1691 ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
1692 "ReadFile failed with %u\n", GetLastError());
1693 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1694
1695 numbytes = 0xdeadbeef;
1696 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1697 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1698 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1699
1700 numbytes = 0xdeadbeef;
1701 memset(buffer, 0, sizeof(buffer));
1702 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1703 ok(ret, "ReadFile failed with %u\n", GetLastError());
1704 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1705
1706 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1707 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1708 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1709 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1710 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1711
1712 SetLastError(0xdeadbeef);
1713 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1714 ok(!ret, "ReadFile unexpectedly succeeded\n");
1715 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1716
1717 numbytes = 0xdeadbeef;
1718 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1719 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%u)\n",
1720 ret, GetLastError());
1721 ok(numbytes == 0xdeadbeef, "numbytes = %u\n", numbytes);
1722
1723 SetLastError(0xdeadbeef);
1724 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1725 ok(!ret, "WriteFile unexpectedly succeeded\n");
1726 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1727
1728 CloseHandle(hpipe);
1729
1730 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1731 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1732 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1733 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1734
1735 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1736 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1737
1738 numbytes = 0xdeadbeef;
1739 ret = WriteFile(hfile, testdata, 0, &numbytes, NULL);
1740 ok(ret, "WriteFile failed with %u\n", GetLastError());
1741 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1742
1743 ret = CloseHandle(hfile);
1744 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1745
1746 numbytes = 0xdeadbeef;
1747 memset(buffer, 0, sizeof(buffer));
1748 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1749 ok(ret, "ReadFile failed with %u\n", GetLastError());
1750 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1751
1752 SetLastError(0xdeadbeef);
1753 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1754 ok(!ret, "ReadFile unexpectedly succeeded\n");
1755 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1756
1757 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1758 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1759 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1760 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1761 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1762
1763 SetLastError(0xdeadbeef);
1764 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1765 ok(!ret, "ReadFile unexpectedly succeeded\n");
1766 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1767
1768 SetLastError(0xdeadbeef);
1769 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1770 ok(!ret, "WriteFile unexpectedly succeeded\n");
1771 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1772
1773 CloseHandle(hpipe);
1774 }
1775
1776 struct named_pipe_client_params
1777 {
1778 DWORD security_flags;
1779 HANDLE token;
1780 BOOL revert;
1781 };
1782
1783 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1784
1785 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1786 {
1787 struct named_pipe_client_params *params = p;
1788 HANDLE pipe;
1789 BOOL ret;
1790 const char message[] = "Test";
1791 DWORD bytes_read, bytes_written;
1792 char dummy;
1793 TOKEN_PRIVILEGES *Privileges = NULL;
1794
1795 if (params->token)
1796 {
1797 if (params->revert)
1798 {
1799 /* modify the token so we can tell if the pipe impersonation
1800 * token reverts to the process token */
1801 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1802 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1803 }
1804 ret = SetThreadToken(NULL, params->token);
1805 ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1806 }
1807 else
1808 {
1809 DWORD Size = 0;
1810 HANDLE process_token;
1811
1812 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1813 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1814
1815 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1816 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1817 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1818 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1819 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1820
1821 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1822 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1823
1824 CloseHandle(process_token);
1825 }
1826
1827 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1828 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1829
1830 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1831 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1832
1833 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1834 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1835
1836 if (params->token)
1837 {
1838 if (params->revert)
1839 {
1840 ret = RevertToSelf();
1841 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1842 }
1843 else
1844 {
1845 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1846 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1847 }
1848 }
1849 else
1850 {
1851 HANDLE process_token;
1852
1853 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1854 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1855
1856 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1857 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1858
1859 HeapFree(GetProcessHeap(), 0, Privileges);
1860
1861 CloseHandle(process_token);
1862 }
1863
1864 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1865 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1866
1867 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1868 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1869
1870 CloseHandle(pipe);
1871
1872 return 0;
1873 }
1874
1875 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1876 {
1877 HANDLE ProcessToken;
1878 HANDLE Token = NULL;
1879 BOOL ret;
1880
1881 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1882 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1883
1884 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1885 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1886
1887 CloseHandle(ProcessToken);
1888
1889 return Token;
1890 }
1891
1892 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1893 {
1894 HANDLE hPipeServer;
1895 BOOL ret;
1896 DWORD dwTid;
1897 HANDLE hThread;
1898 char buffer[256];
1899 DWORD dwBytesRead;
1900 DWORD error;
1901 struct named_pipe_client_params params;
1902 char dummy = 0;
1903 DWORD dwBytesWritten;
1904 HANDLE hToken = NULL;
1905 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1906 DWORD size;
1907
1908 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1909 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1910
1911 params.security_flags = security_flags;
1912 params.token = hClientToken;
1913 params.revert = revert;
1914 hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1915 ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1916
1917 SetLastError(0xdeadbeef);
1918 ret = ImpersonateNamedPipeClient(hPipeServer);
1919 error = GetLastError();
1920 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1921 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1922
1923 ret = ConnectNamedPipe(hPipeServer, NULL);
1924 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1925
1926 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1927 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1928
1929 ret = ImpersonateNamedPipeClient(hPipeServer);
1930 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1931
1932 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1933 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1934
1935 (*test_func)(0, hToken);
1936
1937 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1938 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1939 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1940 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1941
1942 CloseHandle(hToken);
1943
1944 RevertToSelf();
1945
1946 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1947 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1948
1949 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1950 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1951
1952 ret = ImpersonateNamedPipeClient(hPipeServer);
1953 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1954
1955 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1956 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1957
1958 (*test_func)(1, hToken);
1959
1960 CloseHandle(hToken);
1961
1962 RevertToSelf();
1963
1964 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1965 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1966
1967 WaitForSingleObject(hThread, INFINITE);
1968
1969 ret = ImpersonateNamedPipeClient(hPipeServer);
1970 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1971
1972 RevertToSelf();
1973
1974 CloseHandle(hThread);
1975 CloseHandle(hPipeServer);
1976 }
1977
1978 static BOOL are_all_privileges_disabled(HANDLE hToken)
1979 {
1980 BOOL ret;
1981 TOKEN_PRIVILEGES *Privileges = NULL;
1982 DWORD Size = 0;
1983 BOOL all_privs_disabled = TRUE;
1984 DWORD i;
1985
1986 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1987 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1988 {
1989 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1990 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1991 if (!ret)
1992 {
1993 HeapFree(GetProcessHeap(), 0, Privileges);
1994 return FALSE;
1995 }
1996 }
1997 else
1998 return FALSE;
1999
2000 for (i = 0; i < Privileges->PrivilegeCount; i++)
2001 {
2002 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
2003 {
2004 all_privs_disabled = FALSE;
2005 break;
2006 }
2007 }
2008
2009 HeapFree(GetProcessHeap(), 0, Privileges);
2010
2011 return all_privs_disabled;
2012 }
2013
2014 static DWORD get_privilege_count(HANDLE hToken)
2015 {
2016 TOKEN_STATISTICS Statistics;
2017 DWORD Size = sizeof(Statistics);
2018 BOOL ret;
2019
2020 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
2021 ok(ret, "GetTokenInformation(TokenStatistics)\n");
2022 if (!ret) return -1;
2023
2024 return Statistics.PrivilegeCount;
2025 }
2026
2027 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
2028 {
2029 DWORD priv_count;
2030
2031 switch (call_index)
2032 {
2033 case 0:
2034 priv_count = get_privilege_count(hToken);
2035 todo_wine
2036 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
2037 break;
2038 case 1:
2039 priv_count = get_privilege_count(hToken);
2040 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2041 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2042 break;
2043 default:
2044 ok(0, "shouldn't happen\n");
2045 }
2046 }
2047
2048 static void test_no_sqos(int call_index, HANDLE hToken)
2049 {
2050 switch (call_index)
2051 {
2052 case 0:
2053 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2054 break;
2055 case 1:
2056 todo_wine
2057 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2058 break;
2059 default:
2060 ok(0, "shouldn't happen\n");
2061 }
2062 }
2063
2064 static void test_static_context(int call_index, HANDLE hToken)
2065 {
2066 switch (call_index)
2067 {
2068 case 0:
2069 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2070 break;
2071 case 1:
2072 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2073 break;
2074 default:
2075 ok(0, "shouldn't happen\n");
2076 }
2077 }
2078
2079 static void test_dynamic_context(int call_index, HANDLE hToken)
2080 {
2081 switch (call_index)
2082 {
2083 case 0:
2084 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2085 break;
2086 case 1:
2087 todo_wine
2088 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2089 break;
2090 default:
2091 ok(0, "shouldn't happen\n");
2092 }
2093 }
2094
2095 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
2096 {
2097 switch (call_index)
2098 {
2099 case 0:
2100 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2101 break;
2102 case 1:
2103 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
2104 break;
2105 default:
2106 ok(0, "shouldn't happen\n");
2107 }
2108 }
2109
2110 static void test_no_sqos_revert(int call_index, HANDLE hToken)
2111 {
2112 DWORD priv_count;
2113 switch (call_index)
2114 {
2115 case 0:
2116 priv_count = get_privilege_count(hToken);
2117 todo_wine
2118 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
2119 break;
2120 case 1:
2121 priv_count = get_privilege_count(hToken);
2122 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2123 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2124 break;
2125 default:
2126 ok(0, "shouldn't happen\n");
2127 }
2128 }
2129
2130 static void test_static_context_revert(int call_index, HANDLE hToken)
2131 {
2132 switch (call_index)
2133 {
2134 case 0:
2135 todo_wine
2136 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2137 break;
2138 case 1:
2139 todo_wine
2140 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2141 break;
2142 default:
2143 ok(0, "shouldn't happen\n");
2144 }
2145 }
2146
2147 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
2148 {
2149 switch (call_index)
2150 {
2151 case 0:
2152 todo_wine
2153 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2154 break;
2155 case 1:
2156 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
2157 break;
2158 default:
2159 ok(0, "shouldn't happen\n");
2160 }
2161 }
2162
2163 static void test_impersonation(void)
2164 {
2165 HANDLE hClientToken;
2166 HANDLE hProcessToken;
2167 BOOL ret;
2168
2169 if( !pDuplicateTokenEx ) {
2170 skip("DuplicateTokenEx not found\n");
2171 return;
2172 }
2173
2174 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
2175 if (!ret)
2176 {
2177 skip("couldn't open process token, skipping impersonation tests\n");
2178 return;
2179 }
2180
2181 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
2182 {
2183 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
2184 CloseHandle(hProcessToken);
2185 return;
2186 }
2187 CloseHandle(hProcessToken);
2188
2189 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
2190 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2191 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
2192 CloseHandle(hClientToken);
2193 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2194 test_ImpersonateNamedPipeClient(hClientToken,
2195 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
2196 test_static_context);
2197 CloseHandle(hClientToken);
2198 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2199 test_ImpersonateNamedPipeClient(hClientToken,
2200 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2201 FALSE, test_dynamic_context);
2202 CloseHandle(hClientToken);
2203 test_ImpersonateNamedPipeClient(NULL,
2204 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2205 FALSE, test_dynamic_context_no_token);
2206
2207 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2208 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
2209 CloseHandle(hClientToken);
2210 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2211 test_ImpersonateNamedPipeClient(hClientToken,
2212 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
2213 test_static_context_revert);
2214 CloseHandle(hClientToken);
2215 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2216 test_ImpersonateNamedPipeClient(hClientToken,
2217 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2218 TRUE, test_dynamic_context_revert);
2219 CloseHandle(hClientToken);
2220 }
2221
2222 struct overlapped_server_args
2223 {
2224 HANDLE pipe_created;
2225 };
2226
2227 static DWORD CALLBACK overlapped_server(LPVOID arg)
2228 {
2229 OVERLAPPED ol;
2230 HANDLE pipe;
2231 int ret, err;
2232 struct overlapped_server_args *a = arg;
2233 DWORD num;
2234 char buf[100];
2235
2236 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
2237 ok(pipe != NULL, "pipe NULL\n");
2238
2239 ol.hEvent = CreateEventA(0, 1, 0, 0);
2240 ok(ol.hEvent != NULL, "event NULL\n");
2241 ret = ConnectNamedPipe(pipe, &ol);
2242 err = GetLastError();
2243 ok(ret == 0, "ret %d\n", ret);
2244 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2245 SetEvent(a->pipe_created);
2246
2247 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2248 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2249
2250 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2251 ok(ret == 1, "ret %d\n", ret);
2252
2253 /* This should block */
2254 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
2255 ok(ret == 1, "ret %d\n", ret);
2256
2257 DisconnectNamedPipe(pipe);
2258
2259 ret = ConnectNamedPipe(pipe, &ol);
2260 err = GetLastError();
2261 ok(ret == 0, "ret %d\n", ret);
2262 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2263 CancelIo(pipe);
2264 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2265 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2266
2267 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2268 err = GetLastError();
2269 ok(ret == 0, "ret %d\n", ret);
2270 ok(err == ERROR_OPERATION_ABORTED, "gle %d\n", err);
2271
2272 CloseHandle(ol.hEvent);
2273 CloseHandle(pipe);
2274 return 1;
2275 }
2276
2277 static void test_overlapped(void)
2278 {
2279 DWORD tid, num;
2280 HANDLE thread, pipe;
2281 BOOL ret;
2282 struct overlapped_server_args args;
2283
2284 args.pipe_created = CreateEventA(0, 1, 0, 0);
2285 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
2286
2287 WaitForSingleObject(args.pipe_created, INFINITE);
2288 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
2289 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
2290
2291 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
2292 Sleep(1);
2293
2294 ret = WriteFile(pipe, "x", 1, &num, NULL);
2295 ok(ret, "WriteFile failed with error %d\n", GetLastError());
2296
2297 WaitForSingleObject(thread, INFINITE);
2298 CloseHandle(pipe);
2299 CloseHandle(args.pipe_created);
2300 CloseHandle(thread);
2301 }
2302
2303 static void test_overlapped_error(void)
2304 {
2305 HANDLE pipe, file, event;
2306 DWORD err, numbytes;
2307 OVERLAPPED overlapped;
2308 BOOL ret;
2309
2310 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2311 ok(event != NULL, "CreateEventA failed with %u\n", GetLastError());
2312
2313 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2314 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2315 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2316 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2317
2318 memset(&overlapped, 0, sizeof(overlapped));
2319 overlapped.hEvent = event;
2320 ret = ConnectNamedPipe(pipe, &overlapped);
2321 err = GetLastError();
2322 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2323 ok(err == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", err);
2324
2325 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2326 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2327 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2328
2329 numbytes = 0xdeadbeef;
2330 ret = GetOverlappedResult(pipe, &overlapped, &numbytes, TRUE);
2331 ok(ret == TRUE, "GetOverlappedResult failed\n");
2332 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
2333 ok(overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", overlapped.Internal);
2334
2335 CloseHandle(file);
2336 CloseHandle(pipe);
2337
2338 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2339 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2340 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2341 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2342
2343 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2344 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2345 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2346
2347 memset(&overlapped, 0, sizeof(overlapped));
2348 overlapped.hEvent = event;
2349 ret = ConnectNamedPipe(pipe, &overlapped);
2350 err = GetLastError();
2351 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2352 ok(err == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", err);
2353 ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", overlapped.Internal);
2354
2355 CloseHandle(file);
2356 CloseHandle(pipe);
2357
2358 CloseHandle(event);
2359 }
2360
2361 static void test_NamedPipeHandleState(void)
2362 {
2363 HANDLE server, client;
2364 BOOL ret;
2365 DWORD state, instances, maxCollectionCount, collectDataTimeout;
2366 char userName[MAX_PATH];
2367
2368 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2369 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2370 /* nMaxInstances */ 1,
2371 /* nOutBufSize */ 1024,
2372 /* nInBufSize */ 1024,
2373 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2374 /* lpSecurityAttrib */ NULL);
2375 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2376 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2377 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2378 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2379 0);
2380 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2381 if (ret)
2382 {
2383 ok(state == 0, "unexpected state %08x\n", state);
2384 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2385 }
2386 /* Some parameters have no meaning, and therefore can't be retrieved,
2387 * on a local pipe.
2388 */
2389 SetLastError(0xdeadbeef);
2390 ret = GetNamedPipeHandleStateA(server, &state, &instances,
2391 &maxCollectionCount, &collectDataTimeout, userName,
2392 sizeof(userName) / sizeof(userName[0]));
2393 todo_wine
2394 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2395 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2396 /* A byte-mode pipe server can't be changed to message mode. */
2397 state = PIPE_READMODE_MESSAGE;
2398 SetLastError(0xdeadbeef);
2399 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2400 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2401 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2402
2403 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2404 OPEN_EXISTING, 0, NULL);
2405 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2406
2407 state = PIPE_READMODE_BYTE;
2408 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2409 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2410 /* A byte-mode pipe client can't be changed to message mode, either. */
2411 state = PIPE_READMODE_MESSAGE;
2412 SetLastError(0xdeadbeef);
2413 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2414 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2415 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2416
2417 CloseHandle(client);
2418 CloseHandle(server);
2419
2420 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2421 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2422 /* nMaxInstances */ 1,
2423 /* nOutBufSize */ 1024,
2424 /* nInBufSize */ 1024,
2425 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2426 /* lpSecurityAttrib */ NULL);
2427 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2428 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2429 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2430 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2431 0);
2432 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2433 if (ret)
2434 {
2435 ok(state == 0, "unexpected state %08x\n", state);
2436 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2437 }
2438 /* In contrast to byte-mode pipes, a message-mode pipe server can be
2439 * changed to byte mode.
2440 */
2441 state = PIPE_READMODE_BYTE;
2442 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2443 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2444
2445 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2446 OPEN_EXISTING, 0, NULL);
2447 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2448
2449 state = PIPE_READMODE_MESSAGE;
2450 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2451 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2452 /* A message-mode pipe client can also be changed to byte mode.
2453 */
2454 state = PIPE_READMODE_BYTE;
2455 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2456 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2457
2458 CloseHandle(client);
2459 CloseHandle(server);
2460 }
2461
2462 static void test_GetNamedPipeInfo(void)
2463 {
2464 HANDLE server;
2465
2466 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2467 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2468 /* nMaxInstances */ 1,
2469 /* nOutBufSize */ 1024,
2470 /* nInBufSize */ 1024,
2471 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2472 /* lpSecurityAttrib */ NULL);
2473 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2474
2475 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_BYTE, 1024, 1024, 1);
2476
2477 CloseHandle(server);
2478
2479 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2480 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
2481 /* nMaxInstances */ 3,
2482 /* nOutBufSize */ 1024,
2483 /* nInBufSize */ 1024,
2484 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2485 /* lpSecurityAttrib */ NULL);
2486 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2487
2488 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 1024, 1024, 3);
2489
2490 CloseHandle(server);
2491
2492 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2493 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2494 /* nMaxInstances */ 1,
2495 /* nOutBufSize */ 0,
2496 /* nInBufSize */ 0,
2497 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2498 /* lpSecurityAttrib */ NULL);
2499 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2500
2501 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0, 0, 1);
2502
2503 CloseHandle(server);
2504
2505 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2506 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2507 /* nMaxInstances */ 1,
2508 /* nOutBufSize */ 0xf000,
2509 /* nInBufSize */ 0xf000,
2510 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2511 /* lpSecurityAttrib */ NULL);
2512 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2513
2514 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0xf000, 0xf000, 1);
2515
2516 CloseHandle(server);
2517 }
2518
2519 static void test_readfileex_pending(void)
2520 {
2521 HANDLE server, client, event;
2522 BOOL ret;
2523 DWORD err, wait, num_bytes;
2524 OVERLAPPED overlapped;
2525 char read_buf[1024];