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