Reactos
1/*
2 * Unit tests for named pipe functions in Wine
3 *
4 * Copyright (c) 2002 Dan Kegel
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdarg.h>
22#include <stdio.h>
23
24#include "ntstatus.h"
25#define WIN32_NO_STATUS
26#include "windef.h"
27#include "winbase.h"
28#include "winternl.h"
29#include "winioctl.h"
30#include "wine/test.h"
31
32#define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
33
34#define NB_SERVER_LOOPS 8
35
36static HANDLE alarm_event;
37static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
38 SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
39static BOOL (WINAPI *pCancelIoEx)(HANDLE handle, LPOVERLAPPED lpOverlapped);
40static BOOL (WINAPI *pCancelSynchronousIo)(HANDLE handle);
41static BOOL (WINAPI *pGetNamedPipeClientProcessId)(HANDLE,ULONG*);
42static BOOL (WINAPI *pGetNamedPipeServerProcessId)(HANDLE,ULONG*);
43static BOOL (WINAPI *pGetNamedPipeClientSessionId)(HANDLE,ULONG*);
44static BOOL (WINAPI *pGetNamedPipeServerSessionId)(HANDLE,ULONG*);
45static BOOL (WINAPI *pGetOverlappedResultEx)(HANDLE,OVERLAPPED *,DWORD *,DWORD,BOOL);
46
47static BOOL user_apc_ran;
48static void CALLBACK user_apc(ULONG_PTR param)
49{
50 user_apc_ran = TRUE;
51}
52
53
54enum rpcThreadOp
55{
56 RPC_READFILE
57};
58
59struct rpcThreadArgs
60{
61 ULONG_PTR returnValue;
62 DWORD lastError;
63 enum rpcThreadOp op;
64 ULONG_PTR args[5];
65};
66
67static DWORD CALLBACK rpcThreadMain(LPVOID arg)
68{
69 struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
70 if (winetest_debug > 1) trace("rpcThreadMain starting\n");
71 SetLastError( rpcargs->lastError );
72
73 switch (rpcargs->op)
74 {
75 case RPC_READFILE:
76 rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */
77 (LPVOID)rpcargs->args[1], /* buffer */
78 (DWORD)rpcargs->args[2], /* bytesToRead */
79 (LPDWORD)rpcargs->args[3], /* bytesRead */
80 (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
81 break;
82
83 default:
84 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
85 rpcargs->returnValue = 0;
86 break;
87 }
88
89 rpcargs->lastError = GetLastError();
90 if (winetest_debug > 1) trace("rpcThreadMain returning\n");
91 return 0;
92}
93
94/* Runs ReadFile(...) from a different thread */
95static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
96{
97 struct rpcThreadArgs rpcargs;
98 HANDLE thread;
99 DWORD threadId, ret;
100
101 rpcargs.returnValue = 0;
102 rpcargs.lastError = GetLastError();
103 rpcargs.op = RPC_READFILE;
104 rpcargs.args[0] = (ULONG_PTR)hFile;
105 rpcargs.args[1] = (ULONG_PTR)buffer;
106 rpcargs.args[2] = (ULONG_PTR)bytesToRead;
107 rpcargs.args[3] = (ULONG_PTR)bytesRead;
108 rpcargs.args[4] = (ULONG_PTR)overlapped;
109
110 thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
111 ok(thread != NULL, "CreateThread failed. %ld\n", GetLastError());
112 ret = WaitForSingleObject(thread, INFINITE);
113 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with %ld.\n", GetLastError());
114 CloseHandle(thread);
115
116 SetLastError(rpcargs.lastError);
117 return (BOOL)rpcargs.returnValue;
118}
119
120#define test_not_signaled(h) _test_not_signaled(__LINE__,h)
121static void _test_not_signaled(unsigned line, HANDLE handle)
122{
123 DWORD res = WaitForSingleObject(handle, 0);
124 ok_(__FILE__,line)(res == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (%lu)\n", res, GetLastError());
125}
126
127#define test_signaled(h) _test_signaled(__LINE__,h)
128static void _test_signaled(unsigned line, HANDLE handle)
129{
130 DWORD res = WaitForSingleObject(handle, 0);
131 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", res);
132}
133
134#define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
135static 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)
136{
137 DWORD flags = 0xdeadbeef, out_buf_size = 0xdeadbeef, in_buf_size = 0xdeadbeef, max_instances = 0xdeadbeef;
138 BOOL res;
139
140 res = GetNamedPipeInfo(pipe, &flags, &out_buf_size, &in_buf_size, &max_instances);
141 ok_(__FILE__,line)(res, "GetNamedPipeInfo failed: %x\n", res);
142 ok_(__FILE__,line)(flags == ex_flags, "flags = %lx, expected %lx\n", flags, ex_flags);
143 ok_(__FILE__,line)(out_buf_size == ex_out_buf_size, "out_buf_size = %lx, expected %lu\n", out_buf_size, ex_out_buf_size);
144 ok_(__FILE__,line)(in_buf_size == ex_in_buf_size, "in_buf_size = %lx, expected %lu\n", in_buf_size, ex_in_buf_size);
145 ok_(__FILE__,line)(max_instances == ex_max_instances, "max_instances = %lx, expected %lu\n", max_instances, ex_max_instances);
146}
147
148#define test_file_access(a,b) _test_file_access(__LINE__,a,b)
149static void _test_file_access(unsigned line, HANDLE handle, DWORD expected_access)
150{
151 FILE_ACCESS_INFORMATION info;
152 IO_STATUS_BLOCK io;
153 NTSTATUS status;
154
155 memset(&info, 0x11, sizeof(info));
156 status = NtQueryInformationFile(handle, &io, &info, sizeof(info), FileAccessInformation);
157 ok_(__FILE__,line)(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
158 ok_(__FILE__,line)(info.AccessFlags == expected_access, "got access %08lx expected %08lx\n",
159 info.AccessFlags, expected_access);
160}
161
162static void test_CreateNamedPipe(int pipemode)
163{
164 HANDLE hnp;
165 HANDLE hFile;
166 static const char obuf[] = "Bit Bucket";
167 static const char obuf2[] = "More bits";
168 char ibuf[32], *pbuf;
169 DWORD written;
170 DWORD readden;
171 DWORD avail;
172 DWORD left;
173 DWORD lpmode;
174 BOOL ret;
175
176 if (pipemode == PIPE_TYPE_BYTE)
177 trace("test_CreateNamedPipe starting in byte mode\n");
178 else
179 trace("test_CreateNamedPipe starting in message mode\n");
180
181 /* Wait for nonexistent pipe */
182 ret = WaitNamedPipeA(PIPENAME, 2000);
183 ok(ret == 0, "WaitNamedPipe returned %d for nonexistent pipe\n", ret);
184 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
185
186 /* Bad parameter checks */
187 hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
188 /* nMaxInstances */ 1,
189 /* nOutBufSize */ 1024,
190 /* nInBufSize */ 1024,
191 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
192 /* lpSecurityAttrib */ NULL);
193 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
194 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
195
196 if (pipemode == PIPE_TYPE_BYTE)
197 {
198 /* Bad parameter checks */
199 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
200 /* nMaxInstances */ 1,
201 /* nOutBufSize */ 1024,
202 /* nInBufSize */ 1024,
203 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
204 /* lpSecurityAttrib */ NULL);
205 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
206 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
207 }
208
209 hnp = CreateNamedPipeA(NULL,
210 PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
211 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
212 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
213 "CreateNamedPipe should fail if name is NULL\n");
214
215 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
216 ok(hFile == INVALID_HANDLE_VALUE
217 && GetLastError() == ERROR_FILE_NOT_FOUND,
218 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
219
220 /* Functional checks */
221
222 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
223 /* nMaxInstances */ 1,
224 /* nOutBufSize */ 1024,
225 /* nInBufSize */ 1024,
226 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
227 /* lpSecurityAttrib */ NULL);
228 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
229 test_signaled(hnp);
230
231 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
232 | FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES
233 | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA);
234
235 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
236 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%lu)\n",
237 ret, GetLastError());
238
239 ret = WaitNamedPipeA(PIPENAME, 2000);
240 ok(ret, "WaitNamedPipe failed (%ld)\n", GetLastError());
241
242 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
243 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%ld)\n", GetLastError());
244
245 ok(!WaitNamedPipeA(PIPENAME, 100), "WaitNamedPipe succeeded\n");
246
247 ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %lu\n", GetLastError());
248
249 /* Test ConnectNamedPipe() in both directions */
250 ok(!ConnectNamedPipe(hnp, NULL), "ConnectNamedPipe(server) succeeded\n");
251 ok(GetLastError() == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %lu\n", GetLastError());
252 ok(!ConnectNamedPipe(hFile, NULL), "ConnectNamedPipe(client) succeeded\n");
253 ok(GetLastError() == ERROR_INVALID_FUNCTION, "expected ERROR_INVALID_FUNCTION, got %lu\n", GetLastError());
254
255 /* don't try to do i/o if one side couldn't be opened, as it hangs */
256 if (hFile != INVALID_HANDLE_VALUE) {
257 HANDLE hFile2;
258
259 /* Make sure we can read and write a few bytes in both directions */
260 memset(ibuf, 0, sizeof(ibuf));
261 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
262 ok(written == sizeof(obuf), "write file len\n");
263 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
264 ok(readden == sizeof(obuf), "read got %ld bytes\n", readden);
265 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
266
267 memset(ibuf, 0, sizeof(ibuf));
268 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
269 ok(written == sizeof(obuf2), "write file len\n");
270 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
271 ok(readden == sizeof(obuf2), "read got %ld bytes\n", readden);
272 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
273
274 /* Now the same again, but with an additional call to PeekNamedPipe */
275 memset(ibuf, 0, sizeof(ibuf));
276 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
277 ok(written == sizeof(obuf), "write file len 1\n");
278 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &avail, &left), "Peek\n");
279 ok(avail == sizeof(obuf), "peek 1 got %ld bytes\n", avail);
280 if (pipemode == PIPE_TYPE_BYTE)
281 ok(left == 0, "peek 1 got %ld bytes left\n", left);
282 else
283 ok(left == sizeof(obuf), "peek 1 got %ld bytes left\n", left);
284 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
285 ok(readden == sizeof(obuf), "read 1 got %ld bytes\n", readden);
286 ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
287
288 memset(ibuf, 0, sizeof(ibuf));
289 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
290 ok(written == sizeof(obuf2), "write file len 2\n");
291 ok(PeekNamedPipe(hnp, NULL, 0, NULL, &avail, &left), "Peek\n");
292 ok(avail == sizeof(obuf2), "peek 2 got %ld bytes\n", avail);
293 if (pipemode == PIPE_TYPE_BYTE)
294 ok(left == 0, "peek 2 got %ld bytes left\n", left);
295 else
296 ok(left == sizeof(obuf2), "peek 2 got %ld bytes left\n", left);
297 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &avail, &left), "Peek\n");
298 ok(avail == sizeof(obuf2), "peek 2 got %ld bytes\n", avail);
299 if (pipemode == PIPE_TYPE_BYTE)
300 ok(left == 0, "peek 2 got %ld bytes left\n", left);
301 else
302 ok(left == sizeof(obuf2), "peek 2 got %ld bytes left\n", left);
303 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
304 ok(readden == sizeof(obuf2), "read 2 got %ld bytes\n", readden);
305 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
306
307 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
308 memset(ibuf, 0, sizeof(ibuf));
309 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
310 ok(written == sizeof(obuf2), "write file len\n");
311 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek\n");
312 ok(readden == 4, "peek got %ld bytes\n", readden);
313 ok(avail == sizeof(obuf2), "peek got %ld bytes available\n", avail);
314 if (pipemode == PIPE_TYPE_BYTE)
315 ok(left == -4, "peek got %ld bytes left\n", left);
316 else
317 ok(left == sizeof(obuf2)-4, "peek got %ld bytes left\n", left);
318 ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
319 ok(readden == 4, "read got %ld bytes\n", readden);
320 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
321 ok(readden == sizeof(obuf2) - 4, "read got %ld bytes\n", readden);
322 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
323
324 memset(ibuf, 0, sizeof(ibuf));
325 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
326 ok(written == sizeof(obuf), "write file len\n");
327 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek\n");
328 ok(readden == 4, "peek got %ld bytes\n", readden);
329 ok(avail == sizeof(obuf), "peek got %ld bytes available\n", avail);
330 if (pipemode == PIPE_TYPE_BYTE)
331 {
332 ok(left == -4, "peek got %ld bytes left\n", left);
333 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
334 }
335 else
336 {
337 ok(left == sizeof(obuf)-4, "peek got %ld bytes left\n", left);
338 SetLastError(0xdeadbeef);
339 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
340 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
341 }
342 ok(readden == 4, "read got %ld bytes\n", readden);
343 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
344 ok(readden == sizeof(obuf) - 4, "read got %ld bytes\n", readden);
345 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
346
347 /* Similar to above, but use a read buffer size small enough to read in three parts */
348 memset(ibuf, 0, sizeof(ibuf));
349 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
350 ok(written == sizeof(obuf2), "write file len\n");
351 if (pipemode == PIPE_TYPE_BYTE)
352 {
353 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
354 ok(readden == 4, "read got %ld bytes\n", readden);
355 ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
356 }
357 else
358 {
359 SetLastError(0xdeadbeef);
360 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
361 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
362 ok(readden == 4, "read got %ld bytes\n", readden);
363 SetLastError(0xdeadbeef);
364 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
365 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
366 }
367 ok(readden == 4, "read got %ld bytes\n", readden);
368 ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n");
369 ok(readden == sizeof(obuf2) - 8, "read got %ld bytes\n", readden);
370 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
371
372 /* Test reading of multiple writes */
373 memset(ibuf, 0, sizeof(ibuf));
374 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
375 ok(written == sizeof(obuf), "write file len 3a\n");
376 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
377 ok(written == sizeof(obuf2), "write file len 3b\n");
378 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek3\n");
379 ok(readden == 4, "peek3 got %ld bytes\n", readden);
380 if (pipemode == PIPE_TYPE_BYTE)
381 ok(left == -4, "peek3 got %ld bytes left\n", left);
382 else
383 ok(left == sizeof(obuf)-4, "peek3 got %ld bytes left\n", left);
384 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes available\n", avail);
385 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek3\n");
386 if (pipemode == PIPE_TYPE_BYTE) {
387 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes\n", readden);
388 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek3 got %ld bytes left\n", left);
389 }
390 else
391 {
392 ok(readden == sizeof(obuf), "peek3 got %ld bytes\n", readden);
393 ok(left == 0, "peek3 got %ld bytes left\n", left);
394 }
395 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes available\n", avail);
396 pbuf = ibuf;
397 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a 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 3b check\n");
401 }
402 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
403 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %ld bytes\n", readden);
404 pbuf = ibuf;
405 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
406 pbuf += sizeof(obuf);
407 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
408
409 /* Multiple writes in the reverse direction */
410 memset(ibuf, 0, sizeof(ibuf));
411 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
412 ok(written == sizeof(obuf), "write file len 4a\n");
413 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
414 ok(written == sizeof(obuf2), "write file len 4b\n");
415 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek3\n");
416 ok(readden == 4, "peek3 got %ld bytes\n", readden);
417 if (pipemode == PIPE_TYPE_BYTE)
418 ok(left == -4, "peek3 got %ld bytes left\n", left);
419 else
420 ok(left == sizeof(obuf)-4, "peek3 got %ld bytes left\n", left);
421 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes available\n", avail);
422 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek4\n");
423 if (pipemode == PIPE_TYPE_BYTE) {
424 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %ld bytes\n", readden);
425 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek4 got %ld bytes left\n", left);
426 }
427 else
428 {
429 ok(readden == sizeof(obuf), "peek4 got %ld bytes\n", readden);
430 ok(left == 0, "peek4 got %ld bytes left\n", left);
431 }
432 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %ld bytes available\n", avail);
433 pbuf = ibuf;
434 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
435 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
436 pbuf += sizeof(obuf);
437 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
438 }
439 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
440 if (pipemode == PIPE_TYPE_BYTE) {
441 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %ld bytes\n", readden);
442 }
443 else {
444 ok(readden == sizeof(obuf), "read 4 got %ld bytes\n", readden);
445 }
446 pbuf = ibuf;
447 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
448 if (pipemode == PIPE_TYPE_BYTE) {
449 pbuf += sizeof(obuf);
450 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
451 }
452
453 /* Test reading of multiple writes after a mode change
454 (CreateFile always creates a byte mode pipe) */
455 lpmode = PIPE_READMODE_MESSAGE;
456 if (pipemode == PIPE_TYPE_BYTE) {
457 /* trying to change the client end of a byte pipe to message mode should fail */
458 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
459 }
460 else {
461 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
462
463 memset(ibuf, 0, sizeof(ibuf));
464 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
465 ok(written == sizeof(obuf), "write file len 3a\n");
466 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
467 ok(written == sizeof(obuf2), "write file len 3b\n");
468 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek5\n");
469 ok(readden == sizeof(obuf), "peek5 got %ld bytes\n", readden);
470 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %ld bytes available\n", avail);
471 ok(left == 0, "peek5 got %ld bytes left\n", left);
472 pbuf = ibuf;
473 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
474 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
475 ok(readden == sizeof(obuf), "read 5 got %ld bytes\n", readden);
476 pbuf = ibuf;
477 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
478 if (readden <= sizeof(obuf))
479 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
480
481 /* Multiple writes in the reverse direction */
482 /* the write of obuf2 from write4 should still be in the buffer */
483 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
484 ok(readden == sizeof(obuf2), "peek6a got %ld bytes\n", readden);
485 ok(avail == sizeof(obuf2), "peek6a got %ld bytes available\n", avail);
486 if (avail > 0) {
487 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
488 ok(readden == sizeof(obuf2), "read 6a got %ld bytes\n", readden);
489 pbuf = ibuf;
490 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
491 }
492 memset(ibuf, 0, sizeof(ibuf));
493 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
494 ok(written == sizeof(obuf), "write file len 6a\n");
495 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
496 ok(written == sizeof(obuf2), "write file len 6b\n");
497 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
498 ok(readden == sizeof(obuf), "peek6 got %ld bytes\n", readden);
499
500 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %ld bytes available\n", avail);
501 pbuf = ibuf;
502 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
503 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
504 ok(readden == sizeof(obuf), "read 6b got %ld bytes\n", readden);
505 pbuf = ibuf;
506 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
507 if (readden <= sizeof(obuf))
508 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
509
510 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
511 memset(ibuf, 0, sizeof(ibuf));
512 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
513 ok(written == sizeof(obuf2), "write file len 7\n");
514 SetLastError(0xdeadbeef);
515 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
516 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
517 ok(readden == 4, "read got %ld bytes 7\n", readden);
518 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
519 ok(readden == sizeof(obuf2) - 4, "read got %ld bytes 7\n", readden);
520 ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n");
521
522 memset(ibuf, 0, sizeof(ibuf));
523 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
524 ok(written == sizeof(obuf), "write file len 8\n");
525 SetLastError(0xdeadbeef);
526 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
527 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
528 ok(readden == 4, "read got %ld bytes 8\n", readden);
529 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
530 ok(readden == sizeof(obuf) - 4, "read got %ld bytes 8\n", readden);
531 ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
532
533 /* The following test shows that when doing a partial read of a message, the rest
534 * is still in the pipe, and can be received from a second thread. This shows
535 * especially that the content is _not_ stored in thread-local-storage until it is
536 * completely transmitted. The same method works even across multiple processes. */
537 memset(ibuf, 0, sizeof(ibuf));
538 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
539 ok(written == sizeof(obuf), "write file len 9\n");
540 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
541 ok(written == sizeof(obuf2), "write file len 9\n");
542 SetLastError(0xdeadbeef);
543 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
544 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
545 ok(readden == 4, "read got %ld bytes 9\n", readden);
546 SetLastError(0xdeadbeef);
547 ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
548 ok(!ret, "RpcReadFile 9\n");
549 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
550 ok(readden == 4, "read got %ld bytes 9\n", readden);
551 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
552 ok(ret, "RpcReadFile 9\n");
553 ok(readden == sizeof(obuf) - 8, "read got %ld bytes 9\n", readden);
554 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
555 if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
556 {
557 memset(ibuf, 0, sizeof(ibuf));
558 SetLastError(0xdeadbeef);
559 ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
560 ok(!ret, "RpcReadFile 9\n");
561 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
562 ok(readden == 4, "read got %ld bytes 9\n", readden);
563 SetLastError(0xdeadbeef);
564 ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
565 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
566 ok(readden == 4, "read got %ld bytes 9\n", readden);
567 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
568 ok(ret, "RpcReadFile 9\n");
569 ok(readden == sizeof(obuf2) - 8, "read got %ld bytes 9\n", readden);
570 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
571 }
572
573 /* Now the reverse direction */
574 memset(ibuf, 0, sizeof(ibuf));
575 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
576 ok(written == sizeof(obuf2), "write file len 10\n");
577 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
578 ok(written == sizeof(obuf), "write file len 10\n");
579 SetLastError(0xdeadbeef);
580 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
581 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
582 ok(readden == 4, "read got %ld bytes 10\n", readden);
583 SetLastError(0xdeadbeef);
584 ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
585 ok(!ret, "RpcReadFile 10\n");
586 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
587 ok(readden == 4, "read got %ld bytes 10\n", readden);
588 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
589 ok(ret, "RpcReadFile 10\n");
590 ok(readden == sizeof(obuf2) - 8, "read got %ld bytes 10\n", readden);
591 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
592 if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
593 {
594 memset(ibuf, 0, sizeof(ibuf));
595 SetLastError(0xdeadbeef);
596 ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
597 ok(!ret, "RpcReadFile 10\n");
598 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
599 ok(readden == 4, "read got %ld bytes 10\n", readden);
600 SetLastError(0xdeadbeef);
601 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
602 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
603 ok(readden == 4, "read got %ld bytes 10\n", readden);
604 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
605 ok(ret, "RpcReadFile 10\n");
606 ok(readden == sizeof(obuf) - 8, "read got %ld bytes 10\n", readden);
607 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
608 }
609
610 }
611
612 /* Picky conformance tests */
613
614 /* Verify that you can't connect to pipe again
615 * until server calls DisconnectNamedPipe+ConnectNamedPipe
616 * or creates a new pipe
617 * case 1: other client not yet closed
618 */
619 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
620 ok(hFile2 == INVALID_HANDLE_VALUE,
621 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
622 ok(GetLastError() == ERROR_PIPE_BUSY,
623 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
624
625 ok(CloseHandle(hFile), "CloseHandle\n");
626
627 /* case 2: other client already closed */
628 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
629 ok(hFile == INVALID_HANDLE_VALUE,
630 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
631 ok(GetLastError() == ERROR_PIPE_BUSY,
632 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
633
634 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
635
636 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
637 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
638 ok(hFile == INVALID_HANDLE_VALUE,
639 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
640 ok(GetLastError() == ERROR_PIPE_BUSY,
641 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
642
643 /* to be complete, we'd call ConnectNamedPipe here and loop,
644 * but by default that's blocking, so we'd either have
645 * to turn on the uncommon nonblocking mode, or
646 * use another thread.
647 */
648 }
649
650 ok(CloseHandle(hnp), "CloseHandle\n");
651
652 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, pipemode | PIPE_WAIT,
653 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
654 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
655 test_signaled(hnp);
656
657 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_PROPERTIES
658 | FILE_READ_DATA);
659
660 CloseHandle(hnp);
661
662 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_OUTBOUND, pipemode | PIPE_WAIT,
663 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
664 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
665 test_signaled(hnp);
666
667 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
668 | FILE_WRITE_PROPERTIES | FILE_APPEND_DATA | FILE_WRITE_DATA);
669
670 hFile = CreateFileA(PIPENAME, 0, 0, NULL, OPEN_EXISTING, 0, 0);
671 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
672 test_file_access(hFile, SYNCHRONIZE | FILE_READ_ATTRIBUTES);
673 CloseHandle(hFile);
674
675 CloseHandle(hnp);
676
677 hnp = CreateNamedPipeA("\\\\.\\pipe\\a<>*?|\"/b", PIPE_ACCESS_DUPLEX,
678 PIPE_TYPE_BYTE, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
679 ok(hnp != INVALID_HANDLE_VALUE, "failed to create pipe, error %lu\n", GetLastError());
680 hFile = CreateFileA("\\\\.\\pipe\\a<>*?|\"/b", 0, 0, NULL, OPEN_EXISTING, 0, 0);
681 ok(hFile != INVALID_HANDLE_VALUE, "failed to open pipe, error %lu\n", GetLastError());
682 CloseHandle(hFile);
683 CloseHandle(hnp);
684
685 hnp = CreateNamedPipeA("\\\\.\\pipe\\trailingslash\\", PIPE_ACCESS_DUPLEX,
686 PIPE_TYPE_BYTE, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
687 ok(hnp != INVALID_HANDLE_VALUE, "failed to create pipe, error %lu\n", GetLastError());
688 hFile = CreateFileA("\\\\.\\pipe\\trailingslash", 0, 0, NULL, OPEN_EXISTING, 0, 0);
689 ok(hFile == INVALID_HANDLE_VALUE, "expected opening pipe to fail\n");
690 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %lu\n", GetLastError());
691 hFile = CreateFileA("\\\\.\\pipe\\trailingslash\\", 0, 0, NULL, OPEN_EXISTING, 0, 0);
692 ok(hFile != INVALID_HANDLE_VALUE, "failed to open pipe, error %lu\n", GetLastError());
693 CloseHandle(hFile);
694 CloseHandle(hnp);
695
696 if (winetest_debug > 1) trace("test_CreateNamedPipe returning\n");
697}
698
699static void test_CreateNamedPipe_instances_must_match(void)
700{
701 HANDLE hnp, hnp2;
702
703 /* Check no mismatch */
704 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
705 /* nMaxInstances */ 2,
706 /* nOutBufSize */ 1024,
707 /* nInBufSize */ 1024,
708 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
709 /* lpSecurityAttrib */ NULL);
710 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
711
712 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
713 /* nMaxInstances */ 2,
714 /* nOutBufSize */ 1024,
715 /* nInBufSize */ 1024,
716 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
717 /* lpSecurityAttrib */ NULL);
718 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
719
720 ok(CloseHandle(hnp), "CloseHandle\n");
721 ok(CloseHandle(hnp2), "CloseHandle\n");
722
723 /* Check nMaxInstances */
724 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
725 /* nMaxInstances */ 1,
726 /* nOutBufSize */ 1024,
727 /* nInBufSize */ 1024,
728 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
729 /* lpSecurityAttrib */ NULL);
730 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
731
732 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
733 /* nMaxInstances */ 1,
734 /* nOutBufSize */ 1024,
735 /* nInBufSize */ 1024,
736 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
737 /* lpSecurityAttrib */ NULL);
738 ok(hnp2 == INVALID_HANDLE_VALUE
739 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
740
741 ok(CloseHandle(hnp), "CloseHandle\n");
742
743 /* Check PIPE_ACCESS_* */
744 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
745 /* nMaxInstances */ 2,
746 /* nOutBufSize */ 1024,
747 /* nInBufSize */ 1024,
748 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
749 /* lpSecurityAttrib */ NULL);
750 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
751
752 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
753 /* nMaxInstances */ 2,
754 /* nOutBufSize */ 1024,
755 /* nInBufSize */ 1024,
756 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
757 /* lpSecurityAttrib */ NULL);
758 ok(hnp2 == INVALID_HANDLE_VALUE
759 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
760
761 ok(CloseHandle(hnp), "CloseHandle\n");
762
763 /* check everything else */
764 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
765 /* nMaxInstances */ 4,
766 /* nOutBufSize */ 1024,
767 /* nInBufSize */ 1024,
768 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
769 /* lpSecurityAttrib */ NULL);
770 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
771
772 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
773 /* nMaxInstances */ 3,
774 /* nOutBufSize */ 102,
775 /* nInBufSize */ 24,
776 /* nDefaultWait */ 1234,
777 /* lpSecurityAttrib */ NULL);
778 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
779
780 ok(CloseHandle(hnp), "CloseHandle\n");
781 ok(CloseHandle(hnp2), "CloseHandle\n");
782}
783
784static void test_ReadFile(void)
785{
786 HANDLE server, client;
787 OVERLAPPED overlapped;
788 DWORD size;
789 BOOL res;
790
791 static char buf[512];
792
793 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
794 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
795 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
796 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
797
798 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
799 OPEN_EXISTING, 0, 0);
800 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
801
802 ok(WriteFile(client, buf, sizeof(buf), &size, NULL), "WriteFile\n");
803
804 res = ReadFile(server, buf, 1, &size, NULL);
805 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%lu)\n", res, GetLastError());
806 ok(size == 1, "size = %lu\n", size);
807
808 /* pass both overlapped and ret read */
809 memset(&overlapped, 0, sizeof(overlapped));
810 res = ReadFile(server, buf, 1, &size, &overlapped);
811 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%lu)\n", res, GetLastError());
812 ok(size == 0, "size = %lu\n", size);
813 ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "Internal = %Ix\n", overlapped.Internal);
814 ok(overlapped.InternalHigh == 1, "InternalHigh = %Ix\n", overlapped.InternalHigh);
815
816 DisconnectNamedPipe(server);
817
818 memset(&overlapped, 0, sizeof(overlapped));
819 overlapped.InternalHigh = 0xdeadbeef;
820 res = ReadFile(server, buf, 1, &size, &overlapped);
821 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%lu)\n", res, GetLastError());
822 ok(size == 0, "size = %lu\n", size);
823 ok(overlapped.Internal == STATUS_PENDING, "Internal = %Ix\n", overlapped.Internal);
824 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %Ix\n", overlapped.InternalHigh);
825
826 memset(&overlapped, 0, sizeof(overlapped));
827 overlapped.InternalHigh = 0xdeadbeef;
828 res = WriteFile(server, buf, 1, &size, &overlapped);
829 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%lu)\n", res, GetLastError());
830 ok(size == 0, "size = %lu\n", size);
831 ok(overlapped.Internal == STATUS_PENDING, "Internal = %Ix\n", overlapped.Internal);
832 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %Ix\n", overlapped.InternalHigh);
833
834 CloseHandle(server);
835 CloseHandle(client);
836}
837
838/** implementation of alarm() */
839static DWORD CALLBACK alarmThreadMain(LPVOID arg)
840{
841 DWORD_PTR timeout = (DWORD_PTR) arg;
842 if (winetest_debug > 1) trace("alarmThreadMain\n");
843 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
844 {
845 ok(FALSE, "alarm\n");
846 ExitProcess(1);
847 }
848 return 1;
849}
850
851static HANDLE hnp = INVALID_HANDLE_VALUE;
852
853/** Trivial byte echo server - disconnects after each session */
854static DWORD CALLBACK serverThreadMain1(LPVOID arg)
855{
856 int i;
857
858 if (winetest_debug > 1) trace("serverThreadMain1 start\n");
859 /* Set up a simple echo server */
860 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
861 PIPE_TYPE_BYTE | PIPE_WAIT,
862 /* nMaxInstances */ 1,
863 /* nOutBufSize */ 1024,
864 /* nInBufSize */ 1024,
865 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
866 /* lpSecurityAttrib */ NULL);
867
868 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
869 for (i = 0; i < NB_SERVER_LOOPS; i++) {
870 char buf[512];
871 DWORD written;
872 DWORD readden;
873 BOOL success;
874
875 /* Wait for client to connect */
876 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
877 ok(ConnectNamedPipe(hnp, NULL)
878 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
879 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
880
881 /* Echo bytes once */
882 memset(buf, 0, sizeof(buf));
883
884 if (winetest_debug > 1) trace("Server reading...\n");
885 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
886 if (winetest_debug > 1) trace("Server done reading.\n");
887 ok(success, "ReadFile\n");
888 ok(readden, "short read\n");
889
890 if (winetest_debug > 1) trace("Server writing...\n");
891 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
892 if (winetest_debug > 1) trace("Server done writing.\n");
893 ok(written == readden, "write file len\n");
894
895 /* finish this connection, wait for next one */
896 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
897 if (winetest_debug > 1) trace("Server done flushing.\n");
898 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
899 if (winetest_debug > 1) trace("Server done disconnecting.\n");
900 }
901 return 0;
902}
903
904/** Trivial byte echo server - closes after each connection */
905static DWORD CALLBACK serverThreadMain2(LPVOID arg)
906{
907 int i;
908 HANDLE hnpNext = 0;
909
910 trace("serverThreadMain2\n");
911 /* Set up a simple echo server */
912 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
913 PIPE_TYPE_BYTE | PIPE_WAIT,
914 /* nMaxInstances */ 2,
915 /* nOutBufSize */ 1024,
916 /* nInBufSize */ 1024,
917 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
918 /* lpSecurityAttrib */ NULL);
919 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
920
921 for (i = 0; i < NB_SERVER_LOOPS; i++) {
922 char buf[512];
923 DWORD written;
924 DWORD readden;
925 DWORD ret;
926 BOOL success;
927
928
929 user_apc_ran = FALSE;
930 if (i == 0)
931 {
932 if (winetest_debug > 1) trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
933 ret = QueueUserAPC(&user_apc, GetCurrentThread(), 0);
934 ok(ret, "QueueUserAPC failed: %ld\n", GetLastError());
935 }
936
937 /* Wait for client to connect */
938 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
939 ok(ConnectNamedPipe(hnp, NULL)
940 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
941 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
942
943 /* Echo bytes once */
944 memset(buf, 0, sizeof(buf));
945
946 if (winetest_debug > 1) trace("Server reading...\n");
947 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
948 if (winetest_debug > 1) trace("Server done reading.\n");
949 ok(success, "ReadFile\n");
950
951 if (winetest_debug > 1) trace("Server writing...\n");
952 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
953 if (winetest_debug > 1) trace("Server done writing.\n");
954 ok(written == readden, "write file len\n");
955
956 /* finish this connection, wait for next one */
957 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
958 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
959
960 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
961
962 if (i == 0)
963 SleepEx(0, TRUE); /* get rid of apc */
964
965 /* Set up next echo server */
966 hnpNext =
967 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
968 PIPE_TYPE_BYTE | PIPE_WAIT,
969 /* nMaxInstances */ 2,
970 /* nOutBufSize */ 1024,
971 /* nInBufSize */ 1024,
972 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
973 /* lpSecurityAttrib */ NULL);
974
975 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
976
977 ok(CloseHandle(hnp), "CloseHandle\n");
978 hnp = hnpNext;
979 }
980 return 0;
981}
982
983/** Trivial byte echo server - uses overlapped named pipe calls */
984static DWORD CALLBACK serverThreadMain3(LPVOID arg)
985{
986 int i;
987 HANDLE hEvent;
988
989 if (winetest_debug > 1) trace("serverThreadMain3\n");
990 /* Set up a simple echo server */
991 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
992 PIPE_TYPE_BYTE | PIPE_WAIT,
993 /* nMaxInstances */ 1,
994 /* nOutBufSize */ 1024,
995 /* nInBufSize */ 1024,
996 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
997 /* lpSecurityAttrib */ NULL);
998 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
999
1000 hEvent = CreateEventW(NULL, /* security attribute */
1001 TRUE, /* manual reset event */
1002 FALSE, /* initial state */
1003 NULL); /* name */
1004 ok(hEvent != NULL, "CreateEvent\n");
1005
1006 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1007 char buf[512];
1008 DWORD written;
1009 DWORD readden;
1010 DWORD dummy;
1011 BOOL success;
1012 OVERLAPPED oOverlap;
1013 int letWFSOEwait = (i & 2);
1014 int letGORwait = (i & 1);
1015 DWORD err;
1016
1017 memset(&oOverlap, 0, sizeof(oOverlap));
1018 oOverlap.hEvent = hEvent;
1019
1020 /* Wait for client to connect */
1021 if (i == 0) {
1022 if (winetest_debug > 1) trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
1023 success = ConnectNamedPipe(hnp, NULL);
1024 err = GetLastError();
1025 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %ld\n", err);
1026 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1027 } else {
1028 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1029 success = ConnectNamedPipe(hnp, &oOverlap);
1030 err = GetLastError();
1031 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
1032 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe returned.\n");
1033 if (!success && (err == ERROR_IO_PENDING)) {
1034 if (letWFSOEwait)
1035 {
1036 DWORD ret;
1037 do {
1038 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1039 } while (ret == WAIT_IO_COMPLETION);
1040 ok(ret == 0, "wait ConnectNamedPipe returned %lx\n", ret);
1041 }
1042 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
1043 if (!letGORwait && !letWFSOEwait && !success) {
1044 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1045 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
1046 }
1047 }
1048 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
1049 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
1050 }
1051
1052 /* Echo bytes once */
1053 memset(buf, 0, sizeof(buf));
1054
1055 if (winetest_debug > 1) trace("Server reading...\n");
1056 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
1057 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1058 err = GetLastError();
1059 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
1060 if (winetest_debug > 1) trace("overlapped ReadFile returned.\n");
1061 if (!success && (err == ERROR_IO_PENDING)) {
1062 if (letWFSOEwait)
1063 {
1064 DWORD ret;
1065 do {
1066 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1067 } while (ret == WAIT_IO_COMPLETION);
1068 ok(ret == 0, "wait ReadFile returned %lx\n", ret);
1069 }
1070 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
1071 if (!letGORwait && !letWFSOEwait && !success) {
1072 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1073 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
1074 }
1075 }
1076 if (winetest_debug > 1) trace("Server done reading.\n");
1077 ok(success, "overlapped ReadFile\n");
1078
1079 if (winetest_debug > 1) trace("Server writing...\n");
1080 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
1081 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1082 err = GetLastError();
1083 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
1084 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1085 if (!success && (err == ERROR_IO_PENDING)) {
1086 if (letWFSOEwait)
1087 {
1088 DWORD ret;
1089 do {
1090 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1091 } while (ret == WAIT_IO_COMPLETION);
1092 ok(ret == 0, "wait WriteFile returned %lx\n", ret);
1093 }
1094 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
1095 if (!letGORwait && !letWFSOEwait && !success) {
1096 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1097 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
1098 }
1099 }
1100 if (winetest_debug > 1) trace("Server done writing.\n");
1101 ok(success, "overlapped WriteFile\n");
1102 ok(written == readden, "write file len\n");
1103
1104 /* finish this connection, wait for next one */
1105 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1106 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1107 }
1108 return 0;
1109}
1110
1111/** Trivial byte echo server - uses i/o completion ports */
1112static DWORD CALLBACK serverThreadMain4(LPVOID arg)
1113{
1114 int i;
1115 HANDLE hcompletion;
1116 BOOL ret;
1117
1118 if (winetest_debug > 1) trace("serverThreadMain4\n");
1119 /* Set up a simple echo server */
1120 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1121 PIPE_TYPE_BYTE | PIPE_WAIT,
1122 /* nMaxInstances */ 1,
1123 /* nOutBufSize */ 1024,
1124 /* nInBufSize */ 1024,
1125 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1126 /* lpSecurityAttrib */ NULL);
1127 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1128
1129 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
1130 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%li\n", GetLastError());
1131
1132 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1133 char buf[512];
1134 DWORD written;
1135 DWORD readden;
1136 DWORD dummy;
1137 BOOL success;
1138 OVERLAPPED oConnect;
1139 OVERLAPPED oRead;
1140 OVERLAPPED oWrite;
1141 OVERLAPPED *oResult;
1142 DWORD err;
1143 ULONG_PTR compkey;
1144
1145 memset(&oConnect, 0, sizeof(oConnect));
1146 memset(&oRead, 0, sizeof(oRead));
1147 memset(&oWrite, 0, sizeof(oWrite));
1148
1149 /* Wait for client to connect */
1150 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1151 success = ConnectNamedPipe(hnp, &oConnect);
1152 err = GetLastError();
1153 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
1154 "overlapped ConnectNamedPipe got %u err %lu\n", success, err );
1155 if (!success && err == ERROR_IO_PENDING) {
1156 if (winetest_debug > 1) trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
1157 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
1158 if (!success)
1159 {
1160 ok( GetLastError() == WAIT_TIMEOUT,
1161 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %lu\n", GetLastError());
1162 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
1163 }
1164 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%li\n", GetLastError());
1165 if (success)
1166 {
1167 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1168 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
1169 }
1170 }
1171 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
1172
1173 /* Echo bytes once */
1174 memset(buf, 0, sizeof(buf));
1175
1176 if (winetest_debug > 1) trace("Server reading...\n");
1177 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1178 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1179 err = GetLastError();
1180 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%li\n", err);
1181 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1182 &oResult, 10000);
1183 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%li\n", GetLastError());
1184 if (success)
1185 {
1186 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1187 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
1188 }
1189 if (winetest_debug > 1) trace("Server done reading.\n");
1190
1191 if (winetest_debug > 1) trace("Server writing...\n");
1192 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1193 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1194 err = GetLastError();
1195 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%lu\n", err);
1196 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1197 &oResult, 10000);
1198 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%li\n", GetLastError());
1199 if (success)
1200 {
1201 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1202 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
1203 ok(written == readden, "write file len\n");
1204 }
1205 if (winetest_debug > 1) trace("Server done writing.\n");
1206
1207 /* Client will finish this connection, the following ops will trigger broken pipe errors. */
1208
1209 /* Wait for the pipe to break. */
1210 while (PeekNamedPipe(hnp, NULL, 0, NULL, &written, &written));
1211
1212 if (winetest_debug > 1) trace("Server writing on disconnected pipe...\n");
1213 SetLastError(ERROR_SUCCESS);
1214 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1215 err = GetLastError();
1216 ok(!success && err == ERROR_NO_DATA,
1217 "overlapped WriteFile on disconnected pipe returned %u, err=%li\n", success, err);
1218
1219 /* No completion status is queued on immediate error. */
1220 SetLastError(ERROR_SUCCESS);
1221 oResult = (OVERLAPPED *)0xdeadbeef;
1222 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1223 &oResult, 0);
1224 err = GetLastError();
1225 ok(!success && err == WAIT_TIMEOUT && !oResult,
1226 "WriteFile GetQueuedCompletionStatus returned %u, err=%li, oResult %p\n",
1227 success, err, oResult);
1228
1229 if (winetest_debug > 1) trace("Server reading from disconnected pipe...\n");
1230 SetLastError(ERROR_SUCCESS);
1231 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1232 if (winetest_debug > 1) trace("Server ReadFile from disconnected pipe returned...\n");
1233 err = GetLastError();
1234 ok(!success && err == ERROR_BROKEN_PIPE,
1235 "overlapped ReadFile on disconnected pipe returned %u, err=%li\n", success, err);
1236
1237 SetLastError(ERROR_SUCCESS);
1238 oResult = (OVERLAPPED *)0xdeadbeef;
1239 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1240 &oResult, 0);
1241 err = GetLastError();
1242 ok(!success && err == WAIT_TIMEOUT && !oResult,
1243 "ReadFile GetQueuedCompletionStatus returned %u, err=%li, oResult %p\n",
1244 success, err, oResult);
1245
1246 /* finish this connection, wait for next one */
1247 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1248 success = DisconnectNamedPipe(hnp);
1249 ok(success, "DisconnectNamedPipe failed, err %lu\n", GetLastError());
1250 }
1251
1252 ret = CloseHandle(hnp);
1253 ok(ret, "CloseHandle named pipe failed, err=%li\n", GetLastError());
1254 ret = CloseHandle(hcompletion);
1255 ok(ret, "CloseHandle completion failed, err=%li\n", GetLastError());
1256
1257 return 0;
1258}
1259
1260static int completion_called;
1261static DWORD completion_errorcode;
1262static DWORD completion_num_bytes;
1263static LPOVERLAPPED completion_lpoverlapped;
1264
1265static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
1266{
1267 completion_called++;
1268 completion_errorcode = errorcode;
1269 completion_num_bytes = num_bytes;
1270 completion_lpoverlapped = lpoverlapped;
1271 SetEvent(lpoverlapped->hEvent);
1272}
1273
1274/** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
1275static DWORD CALLBACK serverThreadMain5(LPVOID arg)
1276{
1277 int i;
1278 HANDLE hEvent;
1279
1280 if (winetest_debug > 1) trace("serverThreadMain5\n");
1281 /* Set up a simple echo server */
1282 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1283 PIPE_TYPE_BYTE | PIPE_WAIT,
1284 /* nMaxInstances */ 1,
1285 /* nOutBufSize */ 1024,
1286 /* nInBufSize */ 1024,
1287 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1288 /* lpSecurityAttrib */ NULL);
1289 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1290
1291 hEvent = CreateEventW(NULL, /* security attribute */
1292 TRUE, /* manual reset event */
1293 FALSE, /* initial state */
1294 NULL); /* name */
1295 ok(hEvent != NULL, "CreateEvent\n");
1296
1297 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1298 char buf[512];
1299 DWORD readden;
1300 BOOL success;
1301 OVERLAPPED oOverlap;
1302 DWORD err;
1303
1304 memset(&oOverlap, 0, sizeof(oOverlap));
1305 oOverlap.hEvent = hEvent;
1306
1307 /* Wait for client to connect */
1308 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
1309 success = ConnectNamedPipe(hnp, NULL);
1310 err = GetLastError();
1311 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %ld\n", err);
1312 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1313
1314 /* Echo bytes once */
1315 memset(buf, 0, sizeof(buf));
1316
1317 if (winetest_debug > 1) trace("Server reading...\n");
1318 completion_called = 0;
1319 ResetEvent(hEvent);
1320 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
1321 if (winetest_debug > 1) trace("Server ReadFileEx returned...\n");
1322 ok(success, "ReadFileEx failed, err=%li\n", GetLastError());
1323 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1324 if (winetest_debug > 1) trace("ReadFileEx returned.\n");
1325 if (success) {
1326 DWORD ret;
1327 do {
1328 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1329 } while (ret == WAIT_IO_COMPLETION);
1330 ok(ret == 0, "wait ReadFileEx returned %lx\n", ret);
1331 }
1332 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1333 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %ld\n", completion_errorcode);
1334 ok(completion_num_bytes != 0, "read 0 bytes\n");
1335 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1336 readden = completion_num_bytes;
1337 if (winetest_debug > 1) trace("Server done reading.\n");
1338
1339 if (winetest_debug > 1) trace("Server writing...\n");
1340 completion_called = 0;
1341 ResetEvent(hEvent);
1342 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
1343 if (winetest_debug > 1) trace("Server WriteFileEx returned...\n");
1344 ok(success, "WriteFileEx failed, err=%li\n", GetLastError());
1345 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1346 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1347 if (success) {
1348 DWORD ret;
1349 do {
1350 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1351 } while (ret == WAIT_IO_COMPLETION);
1352 ok(ret == 0, "wait WriteFileEx returned %lx\n", ret);
1353 }
1354 if (winetest_debug > 1) trace("Server done writing.\n");
1355 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1356 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %ld\n", completion_errorcode);
1357 ok(completion_num_bytes == readden, "read %li bytes wrote %li\n", readden, completion_num_bytes);
1358 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1359
1360 /* finish this connection, wait for next one */
1361 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1362 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1363 }
1364 return 0;
1365}
1366
1367static void exerciseServer(const char *pipename, HANDLE serverThread)
1368{
1369 int i;
1370
1371 if (winetest_debug > 1) trace("exerciseServer starting\n");
1372 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1373 HANDLE hFile=INVALID_HANDLE_VALUE;
1374 static const char obuf[] = "Bit Bucket";
1375 char ibuf[32];
1376 DWORD written;
1377 DWORD readden;
1378 int loop;
1379
1380 for (loop = 0; loop < 3; loop++) {
1381 DWORD err;
1382 if (winetest_debug > 1) trace("Client connecting...\n");
1383 /* Connect to the server */
1384 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
1385 NULL, OPEN_EXISTING, 0, 0);
1386 if (hFile != INVALID_HANDLE_VALUE)
1387 break;
1388 err = GetLastError();
1389 if (loop == 0)
1390 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
1391 else
1392 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
1393 if (winetest_debug > 1) trace("connect failed, retrying\n");
1394 Sleep(200);
1395 }
1396 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
1397
1398 /* Make sure it can echo */
1399 memset(ibuf, 0, sizeof(ibuf));
1400 if (winetest_debug > 1) trace("Client writing...\n");
1401 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1402 ok(written == sizeof(obuf), "write file len\n");
1403 if (winetest_debug > 1) trace("Client reading...\n");
1404 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1405 ok(readden == sizeof(obuf), "read file len\n");
1406 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1407
1408 if (winetest_debug > 1) trace("Client closing...\n");
1409 ok(CloseHandle(hFile), "CloseHandle\n");
1410 }
1411
1412 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1413 CloseHandle(hnp);
1414 if (winetest_debug > 1) trace("exerciseServer returning\n");
1415}
1416
1417static void test_NamedPipe_2(void)
1418{
1419 HANDLE serverThread;
1420 DWORD serverThreadId;
1421 HANDLE alarmThread;
1422 DWORD alarmThreadId;
1423
1424 trace("test_NamedPipe_2 starting\n");
1425 /* Set up a twenty second timeout */
1426 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1427 SetLastError(0xdeadbeef);
1428 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1429 ok(alarmThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1430
1431 /* The servers we're about to exercise do try to clean up carefully,
1432 * but to reduce the chance of a test failure due to a pipe handle
1433 * leak in the test code, we'll use a different pipe name for each server.
1434 */
1435
1436 /* Try server #1 */
1437 SetLastError(0xdeadbeef);
1438 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1439 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1440 exerciseServer(PIPENAME "serverThreadMain1", serverThread);
1441
1442 /* Try server #2 */
1443 SetLastError(0xdeadbeef);
1444 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1445 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1446 exerciseServer(PIPENAME "serverThreadMain2", serverThread);
1447
1448 /* Try server #3 */
1449 SetLastError(0xdeadbeef);
1450 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1451 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1452 exerciseServer(PIPENAME "serverThreadMain3", serverThread);
1453
1454 /* Try server #4 */
1455 SetLastError(0xdeadbeef);
1456 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1457 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1458 exerciseServer(PIPENAME "serverThreadMain4", serverThread);
1459
1460 /* Try server #5 */
1461 SetLastError(0xdeadbeef);
1462 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1463 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1464 exerciseServer(PIPENAME "serverThreadMain5", serverThread);
1465
1466 ok(SetEvent( alarm_event ), "SetEvent\n");
1467 CloseHandle( alarm_event );
1468 if (winetest_debug > 1) trace("test_NamedPipe_2 returning\n");
1469}
1470
1471static int test_DisconnectNamedPipe(void)
1472{
1473 HANDLE hnp;
1474 HANDLE hFile;
1475 static const char obuf[] = "Bit Bucket";
1476 char ibuf[32];
1477 DWORD written;
1478 DWORD readden;
1479 DWORD ret;
1480
1481 SetLastError(0xdeadbeef);
1482 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1483 /* nMaxInstances */ 1,
1484 /* nOutBufSize */ 1024,
1485 /* nInBufSize */ 1024,
1486 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1487 /* lpSecurityAttrib */ NULL);
1488 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1489 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1490
1491 win_skip("Named pipes are not implemented\n");
1492 return 1;
1493 }
1494
1495 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1496 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1497 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1498 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1499
1500 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1501 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1502
1503 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1504 if (hFile != INVALID_HANDLE_VALUE) {
1505
1506 /* see what happens if server calls DisconnectNamedPipe
1507 * when there are bytes in the pipe
1508 */
1509
1510 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1511 ok(written == sizeof(obuf), "write file len\n");
1512 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1513 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1514 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1515 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1516 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1517 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL) == 0
1518 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1519 "ReadFile from disconnected pipe with bytes waiting\n");
1520 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1521 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1522 "ReadFile from disconnected pipe with bytes waiting\n");
1523
1524 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1525 "DisconnectNamedPipe worked twice\n");
1526 ret = WaitForSingleObject(hFile, 0);
1527 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %lX\n", ret);
1528
1529 ret = PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL);
1530 ok(!ret && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "PeekNamedPipe returned %lx (%lu)\n",
1531 ret, GetLastError());
1532 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
1533 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %lx (%lu)\n",
1534 ret, GetLastError());
1535 ok(CloseHandle(hFile), "CloseHandle\n");
1536 }
1537
1538 ok(CloseHandle(hnp), "CloseHandle\n");
1539
1540 return 0;
1541}
1542static void test_CreatePipe(void)
1543{
1544 SECURITY_ATTRIBUTES pipe_attr;
1545 HANDLE piperead, pipewrite;
1546 DWORD written;
1547 DWORD read;
1548 DWORD i, size;
1549 BYTE *buffer;
1550 char readbuf[32];
1551
1552 user_apc_ran = FALSE;
1553 ok(QueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1554
1555 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1556 pipe_attr.bInheritHandle = TRUE;
1557 pipe_attr.lpSecurityDescriptor = NULL;
1558 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1559 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 4096, 4096, 1);
1560 test_pipe_info(pipewrite, 0, 4096, 4096, 1);
1561 test_file_access(piperead, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
1562 | FILE_READ_ATTRIBUTES | FILE_READ_PROPERTIES | FILE_READ_DATA);
1563 test_file_access(pipewrite, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
1564 | FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_APPEND_DATA
1565 | FILE_WRITE_DATA);
1566
1567 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1568 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %ld bytes\n", written);
1569 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1570 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %ld bytes\n", read);
1571 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1572 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1573
1574 /* Now write another chunk*/
1575 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1576 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1577 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %ld bytes\n", written);
1578 /* and close the write end, read should still succeed*/
1579 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1580 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe with pending data failed\n");
1581 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %ld bytes\n", read);
1582 /* But now we need to get informed that the pipe is closed */
1583 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1584 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1585
1586 /* Try bigger chunks */
1587 size = 32768;
1588 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1589 for (i = 0; i < size; i++) buffer[i] = i;
1590 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1591 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1592 ok(written == size, "Write to anonymous pipe wrote %ld bytes\n", written);
1593 /* and close the write end, read should still succeed*/
1594 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1595 memset( buffer, 0, size );
1596 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe with pending data failed\n");
1597 ok(read == size, "Read from anonymous pipe got %ld bytes\n", read);
1598 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %lx\n", buffer[i], i );
1599 /* But now we need to get informed that the pipe is closed */
1600 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1601 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1602 HeapFree(GetProcessHeap(), 0, buffer);
1603
1604 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1605 SleepEx(0, TRUE); /* get rid of apc */
1606
1607 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 1) != 0, "CreatePipe failed\n");
1608 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 1, 1, 1);
1609 test_pipe_info(pipewrite, 0, 1, 1, 1);
1610 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1611 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1612}
1613
1614static void test_CloseHandle(void)
1615{
1616 static const char testdata[] = "Hello World";
1617 DWORD state, numbytes;
1618 HANDLE hpipe, hfile;
1619 char buffer[32];
1620 BOOL ret;
1621
1622 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1623 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1624 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1625 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
1626
1627 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1628 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
1629
1630 numbytes = 0xdeadbeef;
1631 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1632 ok(ret, "WriteFile failed with %lu\n", GetLastError());
1633 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1634
1635 numbytes = 0xdeadbeef;
1636 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1637 ok(ret, "PeekNamedPipe failed with %lu\n", GetLastError());
1638 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1639
1640 ret = CloseHandle(hpipe);
1641 ok(ret, "CloseHandle failed with %lu\n", GetLastError());
1642
1643 numbytes = 0xdeadbeef;
1644 memset(buffer, 0, sizeof(buffer));
1645 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1646 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1647 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1648
1649 numbytes = 0xdeadbeef;
1650 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1651 ok(ret, "PeekNamedPipe failed with %lu\n", GetLastError());
1652 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1653
1654 numbytes = 0xdeadbeef;
1655 memset(buffer, 0, sizeof(buffer));
1656 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1657 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1658 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1659
1660 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1661 ok(ret, "GetNamedPipeHandleState failed with %lu\n", GetLastError());
1662 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1663 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1664 ok(ret, "SetNamedPipeHandleState failed with %lu\n", GetLastError());
1665
1666 SetLastError(0xdeadbeef);
1667 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1668 ok(!ret, "ReadFile unexpectedly succeeded\n");
1669 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1670
1671 numbytes = 0xdeadbeef;
1672 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1673 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%lu)\n",
1674 ret, GetLastError());
1675 ok(numbytes == 0xdeadbeef, "numbytes = %lu\n", numbytes);
1676
1677 SetLastError(0xdeadbeef);
1678 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1679 ok(!ret, "WriteFile unexpectedly succeeded\n");
1680 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %lu\n", GetLastError());
1681
1682 CloseHandle(hfile);
1683
1684 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1685 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1686 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1687 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
1688
1689 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1690 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
1691
1692 numbytes = 0xdeadbeef;
1693 ret = WriteFile(hpipe, testdata, 0, &numbytes, NULL);
1694 ok(ret, "WriteFile failed with %lu\n", GetLastError());
1695 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1696
1697 ret = CloseHandle(hpipe);
1698 ok(ret, "CloseHandle failed with %lu\n", GetLastError());
1699
1700 numbytes = 0xdeadbeef;
1701 memset(buffer, 0, sizeof(buffer));
1702 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1703 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1704 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1705
1706 SetLastError(0xdeadbeef);
1707 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1708 ok(!ret, "ReadFile unexpectedly succeeded\n");
1709 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1710
1711 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1712 ok(ret, "GetNamedPipeHandleState failed with %lu\n", GetLastError());
1713 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1714 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1715 ok(ret, "SetNamedPipeHandleState failed with %lu\n", GetLastError());
1716
1717 SetLastError(0xdeadbeef);
1718 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1719 ok(!ret, "ReadFile unexpectedly succeeded\n");
1720 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1721
1722 SetLastError(0xdeadbeef);
1723 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1724 ok(!ret, "WriteFile unexpectedly succeeded\n");
1725 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %lu\n", GetLastError());
1726
1727 CloseHandle(hfile);
1728
1729 /* repeat test with hpipe <-> hfile swapped */
1730
1731 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1732 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1733 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1734 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
1735
1736 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1737 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
1738
1739 numbytes = 0xdeadbeef;
1740 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1741 ok(ret, "WriteFile failed with %lu\n", GetLastError());
1742 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1743
1744 numbytes = 0xdeadbeef;
1745 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1746 ok(ret, "PeekNamedPipe failed with %lu\n", GetLastError());
1747 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1748
1749 ret = CloseHandle(hfile);
1750 ok(ret, "CloseHandle failed with %lu\n", GetLastError());
1751
1752 numbytes = 0xdeadbeef;
1753 memset(buffer, 0, sizeof(buffer));
1754 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1755 ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
1756 "ReadFile failed with %lu\n", GetLastError());
1757 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1758
1759 numbytes = 0xdeadbeef;
1760 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1761 ok(ret, "PeekNamedPipe failed with %lu\n", GetLastError());
1762 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1763
1764 numbytes = 0xdeadbeef;
1765 memset(buffer, 0, sizeof(buffer));
1766 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1767 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1768 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1769
1770 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1771 ok(ret, "GetNamedPipeHandleState failed with %lu\n", GetLastError());
1772 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1773 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1774 ok(ret, "SetNamedPipeHandleState failed with %lu\n", GetLastError());
1775
1776 SetLastError(0xdeadbeef);
1777 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1778 ok(!ret, "ReadFile unexpectedly succeeded\n");
1779 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1780
1781 numbytes = 0xdeadbeef;
1782 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1783 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%lu)\n",
1784 ret, GetLastError());
1785 ok(numbytes == 0xdeadbeef, "numbytes = %lu\n", numbytes);
1786
1787 SetLastError(0xdeadbeef);
1788 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1789 ok(!ret, "WriteFile unexpectedly succeeded\n");
1790 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %lu\n", GetLastError());
1791
1792 CloseHandle(hpipe);
1793
1794 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1795 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1796 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1797 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
1798
1799 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1800 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
1801
1802 numbytes = 0xdeadbeef;
1803 ret = WriteFile(hfile, testdata, 0, &numbytes, NULL);
1804 ok(ret, "WriteFile failed with %lu\n", GetLastError());
1805 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1806
1807 ret = CloseHandle(hfile);
1808 ok(ret, "CloseHandle failed with %lu\n", GetLastError());
1809
1810 numbytes = 0xdeadbeef;
1811 memset(buffer, 0, sizeof(buffer));
1812 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1813 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1814 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1815
1816 SetLastError(0xdeadbeef);
1817 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1818 ok(!ret, "ReadFile unexpectedly succeeded\n");
1819 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1820
1821 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1822 ok(ret, "GetNamedPipeHandleState failed with %lu\n", GetLastError());
1823 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1824 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1825 ok(ret, "SetNamedPipeHandleState failed with %lu\n", GetLastError());
1826
1827 SetLastError(0xdeadbeef);
1828 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1829 ok(!ret, "ReadFile unexpectedly succeeded\n");
1830 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1831
1832 SetLastError(0xdeadbeef);
1833 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1834 ok(!ret, "WriteFile unexpectedly succeeded\n");
1835 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %lu\n", GetLastError());
1836
1837 CloseHandle(hpipe);
1838}
1839
1840struct named_pipe_client_params
1841{
1842 DWORD security_flags;
1843 HANDLE token;
1844 BOOL revert;
1845};
1846
1847#define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1848
1849static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1850{
1851 struct named_pipe_client_params *params = p;
1852 HANDLE pipe;
1853 BOOL ret;
1854 const char message[] = "Test";
1855 DWORD bytes_read, bytes_written;
1856 char dummy;
1857 TOKEN_PRIVILEGES *Privileges = NULL;
1858
1859 if (params->token)
1860 {
1861 if (params->revert)
1862 {
1863 /* modify the token so we can tell if the pipe impersonation
1864 * token reverts to the process token */
1865 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1866 ok(ret, "AdjustTokenPrivileges failed with error %ld\n", GetLastError());
1867 }
1868 ret = SetThreadToken(NULL, params->token);
1869 ok(ret, "SetThreadToken failed with error %ld\n", GetLastError());
1870 }
1871 else
1872 {
1873 DWORD Size = 0;
1874 HANDLE process_token;
1875
1876 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1877 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
1878
1879 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1880 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %ld\n", GetLastError());
1881 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1882 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1883 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %ld\n", GetLastError());
1884
1885 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1886 ok(ret, "AdjustTokenPrivileges failed with error %ld\n", GetLastError());
1887
1888 CloseHandle(process_token);
1889 }
1890
1891 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1892 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %ld\n", GetLastError());
1893
1894 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1895 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
1896
1897 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1898 ok(ret, "ReadFile failed with error %ld\n", GetLastError());
1899
1900 if (params->token)
1901 {
1902 if (params->revert)
1903 {
1904 ret = RevertToSelf();
1905 ok(ret, "RevertToSelf failed with error %ld\n", GetLastError());
1906 }
1907 else
1908 {
1909 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1910 ok(ret, "AdjustTokenPrivileges failed with error %ld\n", GetLastError());
1911 }
1912 }
1913 else
1914 {
1915 HANDLE process_token;
1916
1917 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1918 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
1919
1920 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1921 ok(ret, "AdjustTokenPrivileges failed with error %ld\n", GetLastError());
1922
1923 HeapFree(GetProcessHeap(), 0, Privileges);
1924
1925 CloseHandle(process_token);
1926 }
1927
1928 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1929 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
1930
1931 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1932 ok(ret, "ReadFile failed with error %ld\n", GetLastError());
1933
1934 CloseHandle(pipe);
1935
1936 return 0;
1937}
1938
1939static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1940{
1941 HANDLE ProcessToken;
1942 HANDLE Token = NULL;
1943 BOOL ret;
1944
1945 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1946 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
1947
1948 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1949 ok(ret, "DuplicateToken failed with error %ld\n", GetLastError());
1950
1951 CloseHandle(ProcessToken);
1952
1953 return Token;
1954}
1955
1956static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1957{
1958 HANDLE hPipeServer;
1959 BOOL ret;
1960 DWORD dwTid;
1961 HANDLE hThread;
1962 char buffer[256];
1963 DWORD dwBytesRead;
1964 DWORD error;
1965 struct named_pipe_client_params params;
1966 char dummy = 0;
1967 DWORD dwBytesWritten;
1968 HANDLE hToken = NULL;
1969 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1970 DWORD size;
1971
1972 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1973 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %ld\n", GetLastError());
1974
1975 params.security_flags = security_flags;
1976 params.token = hClientToken;
1977 params.revert = revert;
1978 hThread = CreateThread(NULL, 0, named_pipe_client_func, ¶ms, 0, &dwTid);
1979 ok(hThread != NULL, "CreateThread failed with error %ld\n", GetLastError());
1980
1981 SetLastError(0xdeadbeef);
1982 ret = ImpersonateNamedPipeClient(hPipeServer);
1983 error = GetLastError();
1984 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1985 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %ld\n", GetLastError());
1986
1987 ret = ConnectNamedPipe(hPipeServer, NULL);
1988 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %ld\n", GetLastError());
1989
1990 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1991 ok(ret, "ReadFile failed with error %ld\n", GetLastError());
1992
1993 ret = ImpersonateNamedPipeClient(hPipeServer);
1994 ok(ret, "ImpersonateNamedPipeClient failed with error %ld\n", GetLastError());
1995
1996 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1997 ok(ret, "OpenThreadToken failed with error %ld\n", GetLastError());
1998
1999 (*test_func)(0, hToken);
2000
2001 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
2002 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
2003 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %ld\n", GetLastError());
2004 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
2005
2006 CloseHandle(hToken);
2007
2008 RevertToSelf();
2009
2010 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
2011 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
2012
2013 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
2014 ok(ret, "ReadFile failed with error %ld\n", GetLastError());
2015
2016 ret = ImpersonateNamedPipeClient(hPipeServer);
2017 ok(ret, "ImpersonateNamedPipeClient failed with error %ld\n", GetLastError());
2018
2019 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
2020 ok(ret, "OpenThreadToken failed with error %ld\n", GetLastError());
2021
2022 (*test_func)(1, hToken);
2023
2024 CloseHandle(hToken);
2025
2026 RevertToSelf();
2027
2028 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
2029 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
2030
2031 WaitForSingleObject(hThread, INFINITE);
2032
2033 ret = ImpersonateNamedPipeClient(hPipeServer);
2034 ok(ret, "ImpersonateNamedPipeClient failed with error %ld\n", GetLastError());
2035
2036 RevertToSelf();
2037
2038 CloseHandle(hThread);
2039 CloseHandle(hPipeServer);
2040}
2041
2042static BOOL are_all_privileges_disabled(HANDLE hToken)
2043{
2044 BOOL ret;
2045 TOKEN_PRIVILEGES *Privileges = NULL;
2046 DWORD Size = 0;
2047 BOOL all_privs_disabled = TRUE;
2048 DWORD i;
2049
2050 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
2051 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2052 {
2053 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
2054 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
2055 if (!ret)
2056 {
2057 HeapFree(GetProcessHeap(), 0, Privileges);
2058 return FALSE;
2059 }
2060 }
2061 else
2062 return FALSE;
2063
2064 for (i = 0; i < Privileges->PrivilegeCount; i++)
2065 {
2066 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
2067 {
2068 all_privs_disabled = FALSE;
2069 break;
2070 }
2071 }
2072
2073 HeapFree(GetProcessHeap(), 0, Privileges);
2074
2075 return all_privs_disabled;
2076}
2077
2078static DWORD get_privilege_count(HANDLE hToken)
2079{
2080 TOKEN_STATISTICS Statistics;
2081 DWORD Size = sizeof(Statistics);
2082 BOOL ret;
2083
2084 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
2085 ok(ret, "GetTokenInformation(TokenStatistics)\n");
2086 if (!ret) return -1;
2087
2088 return Statistics.PrivilegeCount;
2089}
2090
2091static void test_no_sqos_no_token(int call_index, HANDLE hToken)
2092{
2093 DWORD priv_count;
2094
2095 switch (call_index)
2096 {
2097 case 0:
2098 priv_count = get_privilege_count(hToken);
2099 todo_wine
2100 ok(priv_count == 0, "privilege count should have been 0 instead of %ld\n", priv_count);
2101 break;
2102 case 1:
2103 priv_count = get_privilege_count(hToken);
2104 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2105 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2106 break;
2107 default:
2108 ok(0, "shouldn't happen\n");
2109 }
2110}
2111
2112static void test_no_sqos(int call_index, HANDLE hToken)
2113{
2114 switch (call_index)
2115 {
2116 case 0:
2117 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2118 break;
2119 case 1:
2120 todo_wine
2121 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2122 break;
2123 default:
2124 ok(0, "shouldn't happen\n");
2125 }
2126}
2127
2128static void test_static_context(int call_index, HANDLE hToken)
2129{
2130 switch (call_index)
2131 {
2132 case 0:
2133 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2134 break;
2135 case 1:
2136 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2137 break;
2138 default:
2139 ok(0, "shouldn't happen\n");
2140 }
2141}
2142
2143static void test_dynamic_context(int call_index, HANDLE hToken)
2144{
2145 switch (call_index)
2146 {
2147 case 0:
2148 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2149 break;
2150 case 1:
2151 todo_wine
2152 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2153 break;
2154 default:
2155 ok(0, "shouldn't happen\n");
2156 }
2157}
2158
2159static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
2160{
2161 switch (call_index)
2162 {
2163 case 0:
2164 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2165 break;
2166 case 1:
2167 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
2168 break;
2169 default:
2170 ok(0, "shouldn't happen\n");
2171 }
2172}
2173
2174static void test_no_sqos_revert(int call_index, HANDLE hToken)
2175{
2176 DWORD priv_count;
2177 switch (call_index)
2178 {
2179 case 0:
2180 priv_count = get_privilege_count(hToken);
2181 todo_wine
2182 ok(priv_count == 0, "privilege count should have been 0 instead of %ld\n", priv_count);
2183 break;
2184 case 1:
2185 priv_count = get_privilege_count(hToken);
2186 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2187 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2188 break;
2189 default:
2190 ok(0, "shouldn't happen\n");
2191 }
2192}
2193
2194static void test_static_context_revert(int call_index, HANDLE hToken)
2195{
2196 switch (call_index)
2197 {
2198 case 0:
2199 todo_wine
2200 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2201 break;
2202 case 1:
2203 todo_wine
2204 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2205 break;
2206 default:
2207 ok(0, "shouldn't happen\n");
2208 }
2209}
2210
2211static void test_dynamic_context_revert(int call_index, HANDLE hToken)
2212{
2213 switch (call_index)
2214 {
2215 case 0:
2216 todo_wine
2217 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2218 break;
2219 case 1:
2220 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
2221 break;
2222 default:
2223 ok(0, "shouldn't happen\n");
2224 }
2225}
2226
2227static void test_impersonation(void)
2228{
2229 HANDLE hClientToken;
2230 HANDLE hProcessToken;
2231 BOOL ret;
2232
2233 if( !pDuplicateTokenEx ) {
2234 skip("DuplicateTokenEx not found\n");
2235 return;
2236 }
2237
2238 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
2239 if (!ret)
2240 {
2241 skip("couldn't open process token, skipping impersonation tests\n");
2242 return;
2243 }
2244
2245 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
2246 {
2247 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
2248 CloseHandle(hProcessToken);
2249 return;
2250 }
2251 CloseHandle(hProcessToken);
2252
2253 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
2254 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2255 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
2256 CloseHandle(hClientToken);
2257 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2258 test_ImpersonateNamedPipeClient(hClientToken,
2259 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
2260 test_static_context);
2261 CloseHandle(hClientToken);
2262 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2263 test_ImpersonateNamedPipeClient(hClientToken,
2264 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2265 FALSE, test_dynamic_context);
2266 CloseHandle(hClientToken);
2267 test_ImpersonateNamedPipeClient(NULL,
2268 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2269 FALSE, test_dynamic_context_no_token);
2270
2271 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2272 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
2273 CloseHandle(hClientToken);
2274 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2275 test_ImpersonateNamedPipeClient(hClientToken,
2276 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
2277 test_static_context_revert);
2278 CloseHandle(hClientToken);
2279 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2280 test_ImpersonateNamedPipeClient(hClientToken,
2281 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2282 TRUE, test_dynamic_context_revert);
2283 CloseHandle(hClientToken);
2284}
2285
2286struct overlapped_server_args
2287{
2288 HANDLE pipe_created;
2289};
2290
2291static DWORD CALLBACK overlapped_server(LPVOID arg)
2292{
2293 OVERLAPPED ol;
2294 HANDLE pipe;
2295 int ret, err;
2296 struct overlapped_server_args *a = arg;
2297 DWORD num;
2298 char buf[100];
2299
2300 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
2301 ok(pipe != NULL, "pipe NULL\n");
2302
2303 ol.hEvent = CreateEventA(0, 1, 0, 0);
2304 ok(ol.hEvent != NULL, "event NULL\n");
2305 ret = ConnectNamedPipe(pipe, &ol);
2306 err = GetLastError();
2307 ok(ret == 0, "ret %d\n", ret);
2308 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2309 SetEvent(a->pipe_created);
2310
2311 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2312 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2313
2314 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2315 ok(ret == 1, "ret %d\n", ret);
2316
2317 /* This should block */
2318 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
2319 ok(ret == 1, "ret %d\n", ret);
2320
2321 DisconnectNamedPipe(pipe);
2322
2323 ret = ConnectNamedPipe(pipe, &ol);
2324 err = GetLastError();
2325 ok(ret == 0, "ret %d\n", ret);
2326 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2327 CancelIo(pipe);
2328 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2329 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2330
2331 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2332 err = GetLastError();
2333 ok(ret == 0, "ret %d\n", ret);
2334 ok(err == ERROR_OPERATION_ABORTED, "gle %d\n", err);
2335
2336 CloseHandle(ol.hEvent);
2337 CloseHandle(pipe);
2338 return 1;
2339}
2340
2341static void test_overlapped(void)
2342{
2343 DWORD tid, num;
2344 HANDLE thread, pipe;
2345 BOOL ret;
2346 struct overlapped_server_args args;
2347
2348 args.pipe_created = CreateEventA(0, 1, 0, 0);
2349 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
2350
2351 WaitForSingleObject(args.pipe_created, INFINITE);
2352 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
2353 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
2354
2355 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
2356 Sleep(1);
2357
2358 ret = WriteFile(pipe, "x", 1, &num, NULL);
2359 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
2360
2361 WaitForSingleObject(thread, INFINITE);
2362 CloseHandle(pipe);
2363 CloseHandle(args.pipe_created);
2364 CloseHandle(thread);
2365}
2366
2367static void test_overlapped_error(void)
2368{
2369 HANDLE pipe, file, event;
2370 DWORD err, numbytes;
2371 OVERLAPPED overlapped;
2372 BOOL ret;
2373
2374 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2375 ok(event != NULL, "CreateEventA failed with %lu\n", GetLastError());
2376
2377 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2378 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2379 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2380 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
2381
2382 memset(&overlapped, 0, sizeof(overlapped));
2383 overlapped.hEvent = event;
2384 ret = ConnectNamedPipe(pipe, &overlapped);
2385 err = GetLastError();
2386 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2387 ok(err == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %lu\n", err);
2388
2389 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2390 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2391 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
2392
2393 numbytes = 0xdeadbeef;
2394 ret = GetOverlappedResult(pipe, &overlapped, &numbytes, TRUE);
2395 ok(ret == TRUE, "GetOverlappedResult failed\n");
2396 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
2397 ok(overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08Ix\n", overlapped.Internal);
2398
2399 CloseHandle(file);
2400 CloseHandle(pipe);
2401
2402 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2403 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2404 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2405 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
2406
2407 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2408 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2409 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
2410
2411 memset(&overlapped, 0, sizeof(overlapped));
2412 overlapped.hEvent = event;
2413 ret = ConnectNamedPipe(pipe, &overlapped);
2414 err = GetLastError();
2415 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2416 ok(err == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %lu\n", err);
2417 ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08Ix\n", overlapped.Internal);
2418
2419 CloseHandle(file);
2420 CloseHandle(pipe);
2421
2422 CloseHandle(event);
2423}
2424
2425static void test_NamedPipeHandleState(void)
2426{
2427 HANDLE server, client;
2428 BOOL ret;
2429 DWORD state, instances, maxCollectionCount, collectDataTimeout;
2430 char userName[MAX_PATH];
2431
2432 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2433 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2434 /* nMaxInstances */ 1,
2435 /* nOutBufSize */ 1024,
2436 /* nInBufSize */ 1024,
2437 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2438 /* lpSecurityAttrib */ NULL);
2439 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2440 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2441 ok(ret, "GetNamedPipeHandleState failed: %ld\n", GetLastError());
2442 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2443 0);
2444 ok(ret, "GetNamedPipeHandleState failed: %ld\n", GetLastError());
2445 if (ret)
2446 {
2447 ok(state == 0, "unexpected state %08lx\n", state);
2448 ok(instances == 1, "expected 1 instances, got %ld\n", instances);
2449 }
2450 /* Some parameters have no meaning, and therefore can't be retrieved,
2451 * on a local pipe.
2452 */
2453 SetLastError(0xdeadbeef);
2454 ret = GetNamedPipeHandleStateA(server, &state, &instances, &maxCollectionCount,
2455 &collectDataTimeout, userName, ARRAY_SIZE(userName));
2456 todo_wine
2457 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2458 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
2459 /* A byte-mode pipe server can't be changed to message mode. */
2460 state = PIPE_READMODE_MESSAGE;
2461 SetLastError(0xdeadbeef);
2462 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2463 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2464 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
2465
2466 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2467 OPEN_EXISTING, 0, NULL);
2468 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2469
2470 state = PIPE_READMODE_BYTE;
2471 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2472 ok(ret, "SetNamedPipeHandleState failed: %ld\n", GetLastError());
2473 /* A byte-mode pipe client can't be changed to message mode, either. */
2474 state = PIPE_READMODE_MESSAGE;
2475 SetLastError(0xdeadbeef);
2476 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2477 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2478 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
2479
2480 CloseHandle(client);
2481 CloseHandle(server);
2482
2483 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2484 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2485 /* nMaxInstances */ 1,
2486 /* nOutBufSize */ 1024,
2487 /* nInBufSize */ 1024,
2488 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2489 /* lpSecurityAttrib */ NULL);
2490 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2491 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2492 ok(ret, "GetNamedPipeHandleState failed: %ld\n", GetLastError());
2493 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2494 0);
2495 ok(ret, "GetNamedPipeHandleState failed: %ld\n", GetLastError());
2496 if (ret)
2497 {
2498 ok(state == 0, "unexpected state %08lx\n", state);
2499 ok(instances == 1, "expected 1 instances, got %ld\n", instances);
2500 }
2501 /* In contrast to byte-mode pipes, a message-mode pipe server can be
2502 * changed to byte mode.
2503 */
2504 state = PIPE_READMODE_BYTE;
2505 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2506 ok(ret, "SetNamedPipeHandleState failed: %ld\n", GetLastError());
2507
2508 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2509 OPEN_EXISTING, 0, NULL);
2510 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2511
2512 state = PIPE_READMODE_MESSAGE;
2513 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2514 ok(ret, "SetNamedPipeHandleState failed: %ld\n", GetLastError());
2515 /* A message-mode pipe client can also be changed to byte mode.
2516 */
2517 state = PIPE_READMODE_BYTE;
2518 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2519 ok(ret, "SetNamedPipeHandleState failed: %ld\n", GetLastError());
2520
2521 CloseHandle(client);
2522 CloseHandle(server);
2523}
2524
2525static void test_GetNamedPipeInfo(void)
2526{
2527 HANDLE server;
2528
2529 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2530 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2531 /* nMaxInstances */ 1,
2532 /* nOutBufSize */ 1024,
2533 /* nInBufSize */ 1024,
2534 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2535 /* lpSecurityAttrib */ NULL);
2536 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2537
2538 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_BYTE, 1024, 1024, 1);
2539
2540 CloseHandle(server);
2541
2542 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2543 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
2544 /* nMaxInstances */ 3,
2545 /* nOutBufSize */ 1024,
2546 /* nInBufSize */ 1024,
2547 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2548 /* lpSecurityAttrib */ NULL);
2549 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2550
2551 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 1024, 1024, 3);
2552
2553 CloseHandle(server);
2554
2555 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2556 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2557 /* nMaxInstances */ 1,
2558 /* nOutBufSize */ 0,
2559 /* nInBufSize */ 0,
2560 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2561 /* lpSecurityAttrib */ NULL);
2562 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2563
2564 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0, 0, 1);
2565
2566 CloseHandle(server);
2567
2568 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2569 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2570 /* nMaxInstances */ 1,
2571 /* nOutBufSize */ 0xf000,
2572 /* nInBufSize */ 0xf000,
2573 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2574 /* lpSecurityAttrib */ NULL);
2575 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2576
2577 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0xf000, 0xf000, 1);
2578
2579 CloseHandle(server);
2580}
2581
2582static void test_readfileex_pending(void)
2583{
2584 HANDLE server, client, event;
2585 BOOL ret;
2586 DWORD err, wait, num_bytes;
2587 OVERLAPPED overlapped;
2588 char read_buf[1024];
2589 char write_buf[1024];
2590 const char test_string[] = "test";
2591 int i;
2592
2593 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2594 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2595 /* nMaxInstances */ 1,
2596 /* nOutBufSize */ 1024,
2597 /* nInBufSize */ 1024,
2598 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2599 /* lpSecurityAttrib */ NULL);
2600 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2601
2602 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2603 ok(event != NULL, "CreateEventA failed\n");
2604
2605 memset(&overlapped, 0, sizeof(overlapped));
2606 overlapped.hEvent = event;
2607
2608 ret = ConnectNamedPipe(server, &overlapped);
2609 err = GetLastError();
2610 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2611 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %li\n", err);
2612
2613 wait = WaitForSingleObject(event, 0);
2614 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %lx\n", wait);
2615
2616 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2617 OPEN_EXISTING, 0, NULL);
2618 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2619
2620 wait = WaitForSingleObject(event, 0);
2621 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", wait);
2622
2623 /* Start a read that can't complete immediately. */
2624 completion_called = 0;
2625 ResetEvent(event);
2626 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
2627 ok(ret == TRUE, "ReadFileEx failed, err=%li\n", GetLastError());
2628 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
2629
2630 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
2631 ok(ret == TRUE, "WriteFile failed\n");
2632 ok(num_bytes == strlen(test_string), "only %li bytes written\n", num_bytes);
2633
2634 ok(completion_called == 0, "completion routine called during WriteFile\n");
2635
2636 wait = WaitForSingleObjectEx(event, 0, TRUE);
2637 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %lx\n", wait);
2638
2639 ok(completion_called == 1, "completion not called after writing pipe\n");
2640 ok(completion_errorcode == 0, "completion called with error %lx\n", completion_errorcode);
2641 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %ld bytes\n", completion_num_bytes);
2642 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2643 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
2644
2645 /* Make writes until the pipe is full and the write fails */
2646 memset(write_buf, 0xaa, sizeof(write_buf));
2647 for (i=0; i<256; i++)
2648 {
2649 completion_called = 0;
2650 ResetEvent(event);
2651 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
2652 err = GetLastError();
2653
2654 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
2655
2656 wait = WaitForSingleObjectEx(event, 0, TRUE);
2657
2658 if (wait == WAIT_TIMEOUT)
2659 /* write couldn't complete immediately, presumably the pipe is full */
2660 break;
2661
2662 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", wait);
2663
2664 ok(ret == TRUE, "WriteFileEx failed, err=%li\n", err);
2665 ok(completion_errorcode == 0, "completion called with error %lx\n", completion_errorcode);
2666 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2667 }
2668
2669 ok(ret == TRUE, "WriteFileEx failed, err=%li\n", err);
2670 ok(completion_called == 0, "completion routine called but wait timed out\n");
2671 ok(completion_errorcode == 0, "completion called with error %lx\n", completion_errorcode);
2672 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2673
2674 /* free up some space in the pipe */
2675 for (i=0; i<256; i++)
2676 {
2677 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
2678 ok(ret == TRUE, "ReadFile failed\n");
2679
2680 ok(completion_called == 0, "completion routine called during ReadFile\n");
2681
2682 wait = WaitForSingleObjectEx(event, 0, TRUE);
2683 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0 || wait == WAIT_TIMEOUT,
2684 "WaitForSingleObject returned %lx\n", wait);
2685 if (wait != WAIT_TIMEOUT) break;
2686 }
2687
2688 ok(completion_called == 1, "completion routine not called\n");
2689 ok(completion_errorcode == 0, "completion called with error %lx\n", completion_errorcode);
2690 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2691
2692 num_bytes = 0xdeadbeef;
2693 SetLastError(0xdeadbeef);
2694 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
2695 ok(!ret, "ReadFile should fail\n");
2696 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %lu\n", GetLastError());
2697 ok(num_bytes == 0, "expected 0, got %lu\n", num_bytes);
2698
2699 overlapped.Offset = 0;
2700 overlapped.OffsetHigh = 0;
2701 overlapped.Internal = -1;
2702 overlapped.InternalHigh = -1;
2703 overlapped.hEvent = event;
2704 num_bytes = 0xdeadbeef;
2705 SetLastError(0xdeadbeef);
2706 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
2707 ok(!ret, "ReadFile should fail\n");
2708 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %ld\n", GetLastError());
2709 ok(num_bytes == 0, "bytes %lu\n", num_bytes);
2710 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#Ix\n", overlapped.Internal);
2711 ok(overlapped.InternalHigh == -1, "expected -1, got %Iu\n", overlapped.InternalHigh);
2712
2713 wait = WaitForSingleObject(event, 100);
2714 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %lx\n", wait);
2715
2716 num_bytes = 0xdeadbeef;
2717 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
2718 ok(ret, "WriteFile failed\n");
2719 ok(num_bytes == 1, "bytes %lu\n", num_bytes);
2720
2721 wait = WaitForSingleObject(event, 100);
2722 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", wait);
2723
2724 ok(num_bytes == 1, "bytes %lu\n", num_bytes);
2725 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", overlapped.Internal);
2726 ok(overlapped.InternalHigh == 0, "expected 0, got %Iu\n", overlapped.InternalHigh);
2727
2728 /* read the pending byte and clear the pipe */
2729 num_bytes = 0xdeadbeef;
2730 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
2731 ok(ret, "ReadFile failed\n");
2732 ok(num_bytes == 1, "bytes %lu\n", num_bytes);
2733
2734 CloseHandle(client);
2735 CloseHandle(server);
2736 CloseHandle(event);
2737}
2738
2739#define test_peek_pipe(a,b,c,d) _test_peek_pipe(__LINE__,a,b,c,d)
2740static void _test_peek_pipe(unsigned line, HANDLE pipe, DWORD expected_read, DWORD expected_avail, DWORD expected_message_length)
2741{
2742 DWORD bytes_read = 0xdeadbeed, avail = 0xdeadbeef, left = 0xdeadbeed;
2743 char buf[12000];
2744 FILE_PIPE_PEEK_BUFFER *peek_buf = (void*)buf;
2745 IO_STATUS_BLOCK io;
2746 NTSTATUS status;
2747 BOOL r;
2748
2749 r = PeekNamedPipe(pipe, buf, sizeof(buf), &bytes_read, &avail, &left);
2750 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %lu\n", GetLastError());
2751 ok_(__FILE__,line)(bytes_read == expected_read, "bytes_read = %lu, expected %lu\n", bytes_read, expected_read);
2752 ok_(__FILE__,line)(avail == expected_avail, "avail = %lu, expected %lu\n", avail, expected_avail);
2753 ok_(__FILE__,line)(left == expected_message_length - expected_read, "left = %ld, expected %ld\n",
2754 left, expected_message_length - expected_read);
2755
2756 status = NtFsControlFile(pipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0, buf, sizeof(buf));
2757 ok_(__FILE__,line)(!status || status == STATUS_PENDING, "NtFsControlFile(FSCTL_PIPE_PEEK) failed: %lx\n", status);
2758 ok_(__FILE__,line)(io.Information == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[expected_read]),
2759 "io.Information = %Iu\n", io.Information);
2760 ok_(__FILE__,line)(peek_buf->ReadDataAvailable == expected_avail, "ReadDataAvailable = %lu, expected %lu\n",
2761 peek_buf->ReadDataAvailable, expected_avail);
2762 ok_(__FILE__,line)(peek_buf->MessageLength == expected_message_length, "MessageLength = %lu, expected %lu\n",
2763 peek_buf->MessageLength, expected_message_length);
2764
2765 if (expected_read)
2766 {
2767 r = PeekNamedPipe(pipe, buf, 1, &bytes_read, &avail, &left);
2768 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %lu\n", GetLastError());
2769 ok_(__FILE__,line)(bytes_read == 1, "bytes_read = %lu, expected %lu\n", bytes_read, expected_read);
2770 ok_(__FILE__,line)(avail == expected_avail, "avail = %lu, expected %lu\n", avail, expected_avail);
2771 ok_(__FILE__,line)(left == expected_message_length-1, "left = %ld, expected %ld\n", left, expected_message_length-1);
2772 }
2773}
2774
2775#define overlapped_read_sync(a,b,c,d,e) _overlapped_read_sync(__LINE__,a,b,c,d,e)
2776static void _overlapped_read_sync(unsigned line, HANDLE reader, void *buf, DWORD buf_size, DWORD expected_result, BOOL partial_read)
2777{
2778 DWORD read_bytes = 0xdeadbeef;
2779 OVERLAPPED overlapped;
2780 BOOL res;
2781
2782 memset(&overlapped, 0, sizeof(overlapped));
2783 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2784 res = ReadFile(reader, buf, buf_size, &read_bytes, &overlapped);
2785 if (partial_read)
2786 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x (%lu)\n", res, GetLastError());
2787 else
2788 ok_(__FILE__,line)(res, "ReadFile failed: %lu\n", GetLastError());
2789 if(partial_read)
2790 ok_(__FILE__,line)(!read_bytes, "read_bytes %lu expected 0\n", read_bytes);
2791 else
2792 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %lu expected %lu\n", read_bytes, expected_result);
2793
2794 read_bytes = 0xdeadbeef;
2795 res = GetOverlappedResult(reader, &overlapped, &read_bytes, FALSE);
2796 if (partial_read)
2797 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA,
2798 "GetOverlappedResult returned: %x (%lu)\n", res, GetLastError());
2799 else
2800 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %lu\n", GetLastError());
2801 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %lu expected %lu\n", read_bytes, expected_result);
2802 CloseHandle(overlapped.hEvent);
2803}
2804
2805#define overlapped_read_async(a,b,c,d) _overlapped_read_async(__LINE__,a,b,c,d)
2806static void _overlapped_read_async(unsigned line, HANDLE reader, void *buf, DWORD buf_size, OVERLAPPED *overlapped)
2807{
2808 DWORD read_bytes = 0xdeadbeef;
2809 BOOL res;
2810
2811 memset(overlapped, 0, sizeof(*overlapped));
2812 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2813 res = ReadFile(reader, buf, buf_size, &read_bytes, overlapped);
2814 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "ReadFile returned %x(%lu)\n", res, GetLastError());
2815 ok_(__FILE__,line)(!read_bytes, "read_bytes %lu expected 0\n", read_bytes);
2816
2817 _test_not_signaled(line, overlapped->hEvent);
2818}
2819
2820#define overlapped_write_sync(a,b,c) _overlapped_write_sync(__LINE__,a,b,c)
2821static void _overlapped_write_sync(unsigned line, HANDLE writer, void *buf, DWORD size)
2822{
2823 DWORD written_bytes = 0xdeadbeef;
2824 OVERLAPPED overlapped;
2825 BOOL res;
2826
2827 memset(&overlapped, 0, sizeof(overlapped));
2828 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2829 res = WriteFile(writer, buf, size, &written_bytes, &overlapped);
2830 ok_(__FILE__,line)(res, "WriteFile returned %x(%lu)\n", res, GetLastError());
2831 ok_(__FILE__,line)(written_bytes == size, "WriteFile returned written_bytes = %lu\n", written_bytes);
2832
2833 written_bytes = 0xdeadbeef;
2834 res = GetOverlappedResult(writer, &overlapped, &written_bytes, FALSE);
2835 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %lu\n", GetLastError());
2836 ok_(__FILE__,line)(written_bytes == size, "GetOverlappedResult returned written_bytes %lu expected %lu\n", written_bytes, size);
2837
2838 CloseHandle(overlapped.hEvent);
2839}
2840
2841#define overlapped_write_async(a,b,c,d) _overlapped_write_async(__LINE__,a,b,c,d)
2842static void _overlapped_write_async(unsigned line, HANDLE writer, void *buf, DWORD size, OVERLAPPED *overlapped)
2843{
2844 DWORD written_bytes = 0xdeadbeef;
2845 BOOL res;
2846
2847 memset(overlapped, 0, sizeof(*overlapped));
2848 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2849 res = WriteFile(writer, buf, size, &written_bytes, overlapped);
2850 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%lu)\n", res, GetLastError());
2851 ok_(__FILE__,line)(!written_bytes, "written_bytes = %lu\n", written_bytes);
2852
2853 _test_not_signaled(line, overlapped->hEvent);
2854}
2855
2856#define test_flush_sync(a) _test_flush_sync(__LINE__,a)
2857static void _test_flush_sync(unsigned line, HANDLE pipe)
2858{
2859 BOOL res;
2860
2861 res = FlushFileBuffers(pipe);
2862 ok_(__FILE__,line)(res, "FlushFileBuffers failed: %lu\n", GetLastError());
2863}
2864
2865static DWORD expected_flush_error;
2866
2867static DWORD CALLBACK flush_proc(HANDLE pipe)
2868{
2869 BOOL res;
2870
2871 res = FlushFileBuffers(pipe);
2872 if (expected_flush_error == ERROR_SUCCESS)
2873 {
2874 ok(res, "FlushFileBuffers failed: %lu\n", GetLastError());
2875 }
2876 else
2877 {
2878 ok(!res, "FlushFileBuffers should have failed\n");
2879 ok(GetLastError() == expected_flush_error,
2880 "FlushFileBuffers set error %lu, expected %lu\n", GetLastError(), expected_flush_error);
2881 }
2882 return 0;
2883}
2884
2885#define test_flush_async(a,b) _test_flush_async(__LINE__,a,b)
2886static HANDLE _test_flush_async(unsigned line, HANDLE pipe, DWORD error)
2887{
2888 HANDLE thread;
2889 DWORD tid;
2890
2891 expected_flush_error = error;
2892 thread = CreateThread(NULL, 0, flush_proc, pipe, 0, &tid);
2893 ok_(__FILE__,line)(thread != NULL, "CreateThread failed: %lu\n", GetLastError());
2894
2895 Sleep(50);
2896 _test_not_signaled(line, thread);
2897 return thread;
2898}
2899
2900#define test_flush_done(a) _test_flush_done(__LINE__,a)
2901static void _test_flush_done(unsigned line, HANDLE thread)
2902{
2903 DWORD res = WaitForSingleObject(thread, 1000);
2904 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu (%lu)\n", res, GetLastError());
2905 CloseHandle(thread);
2906}
2907
2908#define test_overlapped_result(a,b,c,d) _test_overlapped_result(__LINE__,a,b,c,d)
2909static void _test_overlapped_result(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD expected_result, BOOL partial_read)
2910{
2911 DWORD result = 0xdeadbeef;
2912 BOOL res;
2913
2914 _test_signaled(line, overlapped->hEvent);
2915
2916 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2917 if (partial_read)
2918 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "GetOverlappedResult returned: %x (%lu)\n", res, GetLastError());
2919 else
2920 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %lu\n", GetLastError());
2921 ok_(__FILE__,line)(result == expected_result, "read_bytes = %lu, expected %lu\n", result, expected_result);
2922 CloseHandle(overlapped->hEvent);
2923}
2924
2925#define test_overlapped_failure(a,b,c) _test_overlapped_failure(__LINE__,a,b,c)
2926static void _test_overlapped_failure(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD error)
2927{
2928 DWORD result;
2929 BOOL res;
2930
2931 _test_signaled(line, overlapped->hEvent);
2932
2933 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2934 ok_(__FILE__,line)(!res && GetLastError() == error, "GetOverlappedResult returned: %x (%lu), expected error %lu\n",
2935 res, GetLastError(), error);
2936 ok_(__FILE__,line)(!result, "result = %lu\n", result);
2937 CloseHandle(overlapped->hEvent);
2938}
2939
2940#define cancel_overlapped(a,b) _cancel_overlapped(__LINE__,a,b)
2941static void _cancel_overlapped(unsigned line, HANDLE handle, OVERLAPPED *overlapped)
2942{
2943 BOOL res;
2944
2945 res = pCancelIoEx(handle, overlapped);
2946 ok_(__FILE__,line)(res, "CancelIoEx failed: %lu\n", GetLastError());
2947
2948 _test_overlapped_failure(line, handle, overlapped, ERROR_OPERATION_ABORTED);
2949}
2950
2951static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL msg_mode, BOOL msg_read)
2952{
2953 OVERLAPPED read_overlapped, read_overlapped2, write_overlapped, write_overlapped2;
2954 char buf[10000], read_buf[10000];
2955 HANDLE flush_thread;
2956 BOOL res;
2957
2958 memset(buf, 0xaa, sizeof(buf));
2959
2960 /* test pending read with overlapped event */
2961 overlapped_read_async(reader, read_buf, 1000, &read_overlapped);
2962 test_flush_sync(writer);
2963 test_peek_pipe(reader, 0, 0, 0);
2964
2965 /* write more data than needed for read */
2966 overlapped_write_sync(writer, buf, 4000);
2967 test_overlapped_result(reader, &read_overlapped, 1000, msg_read);
2968 test_peek_pipe(reader, 3000, 3000, msg_mode ? 3000 : 0);
2969
2970 /* test pending write with overlapped event */
2971 overlapped_write_async(writer, buf, buf_size, &write_overlapped);
2972 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size), 3000 + buf_size, msg_mode ? 3000 : 0);
2973
2974 /* write one more byte */
2975 overlapped_write_async(writer, buf, 1, &write_overlapped2);
2976 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
2977 test_not_signaled(write_overlapped.hEvent);
2978 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size + 1), 3000 + buf_size + 1,
2979 msg_mode ? 3000 : 0);
2980
2981 /* empty write will not block */
2982 overlapped_write_sync(writer, buf, 0);
2983 test_not_signaled(write_overlapped.hEvent);
2984 test_not_signaled(write_overlapped2.hEvent);
2985 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size + 1), 3000 + buf_size + 1,
2986 msg_mode ? 3000 : 0);
2987
2988 /* read remaining data from the first write */
2989 overlapped_read_sync(reader, read_buf, 3000, 3000, FALSE);
2990 test_overlapped_result(writer, &write_overlapped, buf_size, FALSE);
2991 test_not_signaled(write_overlapped2.hEvent);
2992 test_not_signaled(flush_thread);
2993 test_peek_pipe(reader, buf_size + (msg_mode ? 0 : 1), buf_size + 1, msg_mode ? buf_size : 0);
2994
2995 /* read one byte so that the next write fits the buffer */
2996 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
2997 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
2998 test_peek_pipe(reader, buf_size + (msg_mode ? -1 : 0), buf_size, msg_mode ? buf_size - 1 : 0);
2999
3000 /* read the whole buffer */
3001 overlapped_read_sync(reader, read_buf, buf_size, buf_size-msg_read, FALSE);
3002 test_peek_pipe(reader, msg_read ? 1 : 0, msg_read ? 1 : 0, msg_read ? 1 : 0);
3003
3004 if(msg_read)
3005 {
3006 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3007 test_peek_pipe(reader, 0, 0, 0);
3008 }
3009
3010 if(msg_mode)
3011 {
3012 /* we still have an empty message in queue */
3013 overlapped_read_sync(reader, read_buf, 1000, 0, FALSE);
3014 test_peek_pipe(reader, 0, 0, 0);
3015 }
3016 test_flush_done(flush_thread);
3017
3018 /* pipe is empty, the next read will block */
3019 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
3020 overlapped_read_async(reader, read_buf, 1000, &read_overlapped2);
3021
3022 /* write one byte */
3023 overlapped_write_sync(writer, buf, 1);
3024 test_overlapped_result(reader, &read_overlapped, 0, msg_read);
3025 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
3026 test_peek_pipe(reader, 0, 0, 0);
3027
3028 /* write a message larger than buffer */
3029 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3030 test_peek_pipe(reader, buf_size + 2000, buf_size + 2000, msg_mode ? buf_size + 2000 : 0);
3031
3032 /* read so that pending write is still larger than the buffer */
3033 overlapped_read_sync(reader, read_buf, 1999, 1999, msg_read);
3034 test_not_signaled(write_overlapped.hEvent);
3035 test_peek_pipe(reader, buf_size + 1, buf_size + 1, msg_mode ? buf_size + 1 : 0);
3036
3037 /* read one more byte */
3038 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
3039 test_overlapped_result(writer, &write_overlapped, buf_size+2000, FALSE);
3040 test_peek_pipe(reader, buf_size, buf_size, msg_mode ? buf_size : 0);
3041
3042 /* read remaining data */
3043 overlapped_read_sync(reader, read_buf, buf_size+1, buf_size, FALSE);
3044 test_peek_pipe(reader, 0, 0, 0);
3045
3046 /* simple pass of empty message */
3047 overlapped_write_sync(writer, buf, 0);
3048 test_peek_pipe(reader, 0, 0, 0);
3049 if(msg_mode)
3050 overlapped_read_sync(reader, read_buf, 1, 0, FALSE);
3051
3052 /* pipe is empty, the next read will block */
3053 test_flush_sync(writer);
3054 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
3055 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
3056
3057 /* 0 length write wakes one read in msg mode */
3058 overlapped_write_sync(writer, buf, 0);
3059 if(msg_mode)
3060 test_overlapped_result(reader, &read_overlapped, 0, FALSE);
3061 else
3062 test_not_signaled(read_overlapped.hEvent);
3063 test_not_signaled(read_overlapped2.hEvent);
3064 overlapped_write_sync(writer, buf, 1);
3065 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
3066
3067 overlapped_write_sync(writer, buf, 20);
3068 test_peek_pipe(reader, 20, 20, msg_mode ? 20 : 0);
3069 overlapped_write_sync(writer, buf, 15);
3070 test_peek_pipe(reader, msg_mode ? 20 : 35, 35, msg_mode ? 20 : 0);
3071 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
3072 test_peek_pipe(reader, msg_mode ? 10 : 25, 25, msg_mode ? 10 : 0);
3073 overlapped_read_sync(reader, read_buf, 10, 10, FALSE);
3074 test_peek_pipe(reader, 15, 15, msg_mode ? 15 : 0);
3075 overlapped_read_sync(reader, read_buf, 15, 15, FALSE);
3076
3077 if(!pCancelIoEx) {
3078 win_skip("CancelIoEx not available\n");
3079 return;
3080 }
3081
3082 /* add one more pending read, then cancel the first one */
3083 overlapped_read_async(reader, read_buf, 1, &read_overlapped);
3084 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
3085 cancel_overlapped(reader, &read_overlapped2);
3086 test_not_signaled(read_overlapped.hEvent);
3087 overlapped_write_sync(writer, buf, 1);
3088 test_overlapped_result(reader, &read_overlapped, 1, FALSE);
3089
3090 /* Test that canceling the same operation twice gives a sensible error */
3091 SetLastError(0xdeadbeef);
3092 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
3093 res = pCancelIoEx(reader, &read_overlapped2);
3094 ok(res, "CancelIoEx failed with error %ld\n", GetLastError());
3095 res = pCancelIoEx(reader, &read_overlapped2);
3096 ok(!res, "CancelIOEx succeeded unexpectedly\n");
3097 ok(GetLastError() == ERROR_NOT_FOUND,
3098 "In CancelIoEx failure, expected ERROR_NOT_FOUND, got %ld\n", GetLastError());
3099 test_overlapped_failure(reader, &read_overlapped2, ERROR_OPERATION_ABORTED);
3100
3101 /* make two async writes, cancel the first one and make sure that we read from the second one */
3102 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3103 overlapped_write_async(writer, buf, 1, &write_overlapped2);
3104 test_peek_pipe(reader, buf_size + 2000 + (msg_mode ? 0 : 1),
3105 buf_size + 2001, msg_mode ? buf_size + 2000 : 0);
3106 cancel_overlapped(writer, &write_overlapped);
3107 test_peek_pipe(reader, 1, 1, msg_mode ? 1 : 0);
3108 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3109 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
3110 test_peek_pipe(reader, 0, 0, 0);
3111
3112 /* same as above, but partially read written data before canceling */
3113 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3114 overlapped_write_async(writer, buf, 1, &write_overlapped2);
3115 test_peek_pipe(reader, buf_size + 2000 + (msg_mode ? 0 : 1),
3116 buf_size + 2001, msg_mode ? buf_size + 2000 : 0);
3117 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
3118 test_not_signaled(write_overlapped.hEvent);
3119 cancel_overlapped(writer, &write_overlapped);
3120 test_peek_pipe(reader, 1, 1, msg_mode ? 1 : 0);
3121 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3122 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
3123 test_peek_pipe(reader, 0, 0, 0);
3124
3125 /* empty queue by canceling write and make sure that flush is signaled */
3126 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3127 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
3128 test_not_signaled(flush_thread);
3129 cancel_overlapped(writer, &write_overlapped);
3130 test_peek_pipe(reader, 0, 0, 0);
3131 test_flush_done(flush_thread);
3132}
3133
3134#define overlapped_transact(a,b,c,d,e,f) _overlapped_transact(__LINE__,a,b,c,d,e,f)
3135static void _overlapped_transact(unsigned line, HANDLE caller, void *write_buf, DWORD write_size,
3136 void *read_buf, DWORD read_size, OVERLAPPED *overlapped)
3137{
3138 BOOL res;
3139
3140 memset(overlapped, 0, sizeof(*overlapped));
3141 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3142 res = TransactNamedPipe(caller, write_buf, write_size, read_buf, read_size, NULL, overlapped);
3143 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING,
3144 "TransactNamedPipe returned: %x(%lu)\n", res, GetLastError());
3145}
3146
3147#define overlapped_transact_failure(a,b,c,d,e,f) _overlapped_transact_failure(__LINE__,a,b,c,d,e,f)
3148static void _overlapped_transact_failure(unsigned line, HANDLE caller, void *write_buf, DWORD write_size,
3149 void *read_buf, DWORD read_size, DWORD expected_error)
3150{
3151 OVERLAPPED overlapped;
3152 BOOL res;
3153
3154 memset(&overlapped, 0, sizeof(overlapped));
3155 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3156 res = TransactNamedPipe(caller, write_buf, write_size, read_buf, read_size, NULL, &overlapped);
3157 ok_(__FILE__,line)(!res, "TransactNamedPipe succeeded\n");
3158
3159 if (GetLastError() == ERROR_IO_PENDING) /* win8+ */
3160 {
3161 _test_overlapped_failure(line, caller, &overlapped, expected_error);
3162 }
3163 else
3164 {
3165 ok_(__FILE__,line)(GetLastError() == expected_error,
3166 "TransactNamedPipe returned error %lu, expected %lu\n",
3167 GetLastError(), expected_error);
3168 CloseHandle(overlapped.hEvent);
3169 }
3170}
3171
3172static void child_process_write_pipe(HANDLE pipe)
3173{
3174 OVERLAPPED overlapped;
3175 char buf[10000];
3176
3177 memset(buf, 'x', sizeof(buf));
3178 overlapped_write_async(pipe, buf, sizeof(buf), &overlapped);
3179
3180 /* sleep until parent process terminates this process */
3181 Sleep(INFINITE);
3182}
3183
3184static HANDLE create_writepipe_process(HANDLE pipe)
3185{
3186 STARTUPINFOA si = { sizeof(si) };
3187 PROCESS_INFORMATION info;
3188 char **argv, buf[MAX_PATH];
3189 BOOL res;
3190
3191 winetest_get_mainargs(&argv);
3192 sprintf(buf, "\"%s\" pipe writepipe %Ix", argv[0], (UINT_PTR)pipe);
3193 res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0L, NULL, NULL, &si, &info);
3194 ok(res, "CreateProcess failed: %lu\n", GetLastError());
3195 CloseHandle(info.hThread);
3196
3197 return info.hProcess;
3198}
3199
3200static void create_overlapped_pipe(DWORD mode, HANDLE *client, HANDLE *server)
3201{
3202 SECURITY_ATTRIBUTES sec_attr = { sizeof(sec_attr), NULL, TRUE };
3203 DWORD read_mode = mode & (PIPE_READMODE_BYTE | PIPE_READMODE_MESSAGE);
3204 OVERLAPPED overlapped;
3205 BOOL res;
3206
3207 *server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3208 PIPE_WAIT | mode, 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
3209 ok(*server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError());
3210 test_signaled(*server);
3211
3212 memset(&overlapped, 0, sizeof(overlapped));
3213 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3214 res = ConnectNamedPipe(*server, &overlapped);
3215 ok(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%lu)\n", res, GetLastError());
3216 test_not_signaled(*server);
3217 test_not_signaled(overlapped.hEvent);
3218
3219 *client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, &sec_attr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
3220 ok(*client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
3221
3222 res = SetNamedPipeHandleState(*client, &read_mode, NULL, NULL);
3223 ok(res, "SetNamedPipeHandleState failed: %lu\n", GetLastError());
3224
3225 test_signaled(*client);
3226 test_not_signaled(*server);
3227 test_overlapped_result(*server, &overlapped, 0, FALSE);
3228}
3229
3230static void test_overlapped_transport(BOOL msg_mode, BOOL msg_read_mode)
3231{
3232 OVERLAPPED overlapped, overlapped2;
3233 HANDLE server, client, flush;
3234 DWORD read_bytes;
3235 HANDLE process;
3236 char buf[60000];
3237 BOOL res;
3238
3239 DWORD create_flags =
3240 (msg_mode ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) |
3241 (msg_read_mode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
3242
3243 create_overlapped_pipe(create_flags, &client, &server);
3244
3245 trace("testing %s, %s server->client writes...\n",
3246 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3247 test_blocking_rw(server, client, 5000, msg_mode, msg_read_mode);
3248 trace("testing %s, %s client->server writes...\n",
3249 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3250 test_blocking_rw(client, server, 6000, msg_mode, msg_read_mode);
3251
3252 CloseHandle(client);
3253 CloseHandle(server);
3254
3255 /* close client with pending writes */
3256 memset(buf, 0xaa, sizeof(buf));
3257 create_overlapped_pipe(create_flags, &client, &server);
3258 overlapped_write_async(server, buf, 7000, &overlapped);
3259 flush = test_flush_async(server, ERROR_BROKEN_PIPE);
3260 CloseHandle(client);
3261 test_overlapped_failure(server, &overlapped, ERROR_BROKEN_PIPE);
3262 test_flush_done(flush);
3263 CloseHandle(server);
3264
3265 /* close server with pending writes */
3266 create_overlapped_pipe(create_flags, &client, &server);
3267 overlapped_write_async(client, buf, 7000, &overlapped);
3268 flush = test_flush_async(client, ERROR_BROKEN_PIPE);
3269 CloseHandle(server);
3270 test_overlapped_failure(client, &overlapped, ERROR_BROKEN_PIPE);
3271 test_flush_done(flush);
3272 CloseHandle(client);
3273
3274 /* disconnect with pending writes */
3275 create_overlapped_pipe(create_flags, &client, &server);
3276 overlapped_write_async(client, buf, 7000, &overlapped);
3277 overlapped_write_async(server, buf, 7000, &overlapped2);
3278 flush = test_flush_async(client, ERROR_PIPE_NOT_CONNECTED);
3279 res = DisconnectNamedPipe(server);
3280 ok(res, "DisconnectNamedPipe failed: %lu\n", GetLastError());
3281 test_overlapped_failure(client, &overlapped, ERROR_PIPE_NOT_CONNECTED);
3282 test_overlapped_failure(client, &overlapped2, ERROR_PIPE_NOT_CONNECTED);
3283 test_flush_done(flush);
3284 CloseHandle(server);
3285 CloseHandle(client);
3286
3287 /* terminate process with pending write */
3288 create_overlapped_pipe(create_flags, &client, &server);
3289 process = create_writepipe_process(client);
3290 /* successfully read part of write that is pending in child process */
3291 res = ReadFile(server, buf, 10, &read_bytes, NULL);
3292 if(!msg_read_mode)
3293 ok(res, "ReadFile failed: %lu\n", GetLastError());
3294 else
3295 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %lu\n", res, GetLastError());
3296 ok(read_bytes == 10, "read_bytes = %lu\n", read_bytes);
3297 TerminateProcess(process, 0);
3298 wait_child_process(process);
3299 /* after terminating process, there is no pending write and pipe buffer is empty */
3300 overlapped_read_async(server, buf, 10, &overlapped);
3301 overlapped_write_sync(client, buf, 1);
3302 test_overlapped_result(server, &overlapped, 1, FALSE);
3303 CloseHandle(process);
3304 CloseHandle(server);
3305 CloseHandle(client);
3306}
3307
3308static void test_transact(HANDLE caller, HANDLE callee, DWORD write_buf_size, DWORD read_buf_size)
3309{
3310 OVERLAPPED overlapped, overlapped2, read_overlapped, write_overlapped;
3311 char buf[10000], read_buf[10000];
3312
3313 memset(buf, 0xaa, sizeof(buf));
3314
3315 /* simple transact call */
3316 overlapped_transact(caller, (BYTE*)"abc", 3, read_buf, 100, &overlapped);
3317 overlapped_write_sync(callee, (BYTE*)"test", 4);
3318 test_overlapped_result(caller, &overlapped, 4, FALSE);
3319 ok(!memcmp(read_buf, "test", 4), "unexpected read_buf\n");
3320 overlapped_read_sync(callee, read_buf, 1000, 3, FALSE);
3321 ok(!memcmp(read_buf, "abc", 3), "unexpected read_buf\n");
3322
3323 /* transact fails if there is already data in read buffer */
3324 overlapped_write_sync(callee, buf, 1);
3325 overlapped_transact_failure(caller, buf, 2, read_buf, 1, ERROR_PIPE_BUSY);
3326 overlapped_read_sync(caller, read_buf, 1000, 1, FALSE);
3327
3328 /* transact doesn't block on write */
3329 overlapped_write_async(caller, buf, write_buf_size+2000, &write_overlapped);
3330 overlapped_transact(caller, buf, 2, read_buf, 1, &overlapped);
3331 test_not_signaled(overlapped.hEvent);
3332 overlapped_write_sync(callee, buf, 1);
3333 test_overlapped_result(caller, &overlapped, 1, FALSE);
3334 overlapped_read_sync(callee, read_buf, sizeof(read_buf), write_buf_size+2000, FALSE);
3335 test_overlapped_result(caller, &write_overlapped, write_buf_size+2000, FALSE);
3336 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 2, FALSE);
3337
3338 /* transact with already pending read */
3339 overlapped_read_async(callee, read_buf, 10, &read_overlapped);
3340 overlapped_transact(caller, buf, 5, read_buf, 6, &overlapped);
3341 test_overlapped_result(callee, &read_overlapped, 5, FALSE);
3342 test_not_signaled(overlapped.hEvent);
3343 overlapped_write_sync(callee, buf, 10);
3344 test_overlapped_result(caller, &overlapped, 6, TRUE);
3345 overlapped_read_sync(caller, read_buf, sizeof(read_buf), 4, FALSE);
3346
3347 /* 0-size messages */
3348 overlapped_transact(caller, buf, 5, read_buf, 0, &overlapped);
3349 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 5, FALSE);
3350 overlapped_write_sync(callee, buf, 0);
3351 test_overlapped_result(caller, &overlapped, 0, FALSE);
3352
3353 overlapped_transact(caller, buf, 0, read_buf, 0, &overlapped);
3354 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 0, FALSE);
3355 test_not_signaled(overlapped.hEvent);
3356 overlapped_write_sync(callee, buf, 0);
3357 test_overlapped_result(caller, &overlapped, 0, FALSE);
3358
3359 /* reply transact with another transact */
3360 overlapped_transact(caller, buf, 3, read_buf, 100, &overlapped);
3361 overlapped_read_sync(callee, read_buf, 1000, 3, FALSE);
3362 overlapped_transact(callee, buf, 4, read_buf, 100, &overlapped2);
3363 test_overlapped_result(caller, &overlapped, 4, FALSE);
3364 overlapped_write_sync(caller, buf, 1);
3365 test_overlapped_result(caller, &overlapped2, 1, FALSE);
3366
3367 if (!pCancelIoEx) return;
3368
3369 /* cancel keeps written data */
3370 overlapped_write_async(caller, buf, write_buf_size+2000, &write_overlapped);
3371 overlapped_transact(caller, buf, 2, read_buf, 1, &overlapped);
3372 test_not_signaled(overlapped.hEvent);
3373 cancel_overlapped(caller, &overlapped);
3374 overlapped_read_sync(callee, read_buf, sizeof(read_buf), write_buf_size+2000, FALSE);
3375 test_overlapped_result(caller, &write_overlapped, write_buf_size+2000, FALSE);
3376 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 2, FALSE);
3377}
3378
3379static void test_TransactNamedPipe(void)
3380{
3381 HANDLE client, server;
3382 BYTE buf[10];
3383
3384 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3385 overlapped_transact_failure(client, buf, 2, buf, 1, ERROR_BAD_PIPE);
3386 CloseHandle(client);
3387 CloseHandle(server);
3388
3389 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE, &client, &server);
3390 overlapped_transact_failure(client, buf, 2, buf, 1, ERROR_BAD_PIPE);
3391 CloseHandle(client);
3392 CloseHandle(server);
3393
3394 trace("testing server->client transaction...\n");
3395 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, &client, &server);
3396 test_transact(server, client, 5000, 6000);
3397 CloseHandle(client);
3398 CloseHandle(server);
3399
3400 trace("testing client->server transaction...\n");
3401 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, &client, &server);
3402 test_transact(client, server, 6000, 5000);
3403 CloseHandle(client);
3404 CloseHandle(server);
3405}
3406
3407static HANDLE create_overlapped_server( OVERLAPPED *overlapped )
3408{
3409 HANDLE pipe;
3410 BOOL ret;
3411
3412 pipe = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_READMODE_BYTE | PIPE_WAIT,
3413 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
3414 ok(pipe != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3415 ret = ConnectNamedPipe(pipe, overlapped);
3416 ok(!ret && GetLastError() == ERROR_IO_PENDING, "got %lu\n", GetLastError());
3417 return pipe;
3418}
3419
3420static void child_process_check_pid(DWORD server_pid)
3421{
3422 DWORD current = GetProcessId(GetCurrentProcess());
3423 HANDLE pipe;
3424 ULONG pid;
3425 BOOL ret;
3426
3427 pipe = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3428 ok(pipe != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3429
3430 pid = 0;
3431 ret = pGetNamedPipeClientProcessId(pipe, &pid);
3432 ok(ret, "got %lu\n", GetLastError());
3433 ok(pid == current, "got %04lx\n", pid);
3434
3435 pid = 0;
3436 ret = pGetNamedPipeServerProcessId(pipe, &pid);
3437 ok(ret, "got %lu\n", GetLastError());
3438 ok(pid == server_pid, "got %04lx expected %04lx\n", pid, server_pid);
3439 CloseHandle(pipe);
3440}
3441
3442static HANDLE create_check_id_process(const char *verb, DWORD id)
3443{
3444 STARTUPINFOA si = {sizeof(si)};
3445 PROCESS_INFORMATION info;
3446 char **argv, buf[MAX_PATH];
3447 BOOL ret;
3448
3449 winetest_get_mainargs(&argv);
3450 sprintf(buf, "\"%s\" pipe %s %lx", argv[0], verb, id);
3451 ret = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &info);
3452 ok(ret, "got %lu\n", GetLastError());
3453 CloseHandle(info.hThread);
3454 return info.hProcess;
3455}
3456
3457static void test_namedpipe_process_id(void)
3458{
3459 HANDLE client, server, process;
3460 DWORD current = GetProcessId(GetCurrentProcess());
3461 OVERLAPPED overlapped;
3462 ULONG pid;
3463 BOOL ret;
3464
3465#if defined(__REACTOS__) && DLL_EXPORT_VERSION >= 0x600
3466 /* FIXME: GetNamedPipeClientProcessId is a STUB on ReactOS. */
3467 if (is_reactos() || !pGetNamedPipeClientProcessId)
3468#else
3469 if (!pGetNamedPipeClientProcessId)
3470#endif
3471 {
3472 win_skip("GetNamedPipeClientProcessId not available\n");
3473 return;
3474 }
3475
3476 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3477
3478 SetLastError(0xdeadbeef);
3479 ret = pGetNamedPipeClientProcessId(server, NULL);
3480 ok(!ret, "success\n");
3481 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
3482
3483 pid = 0;
3484 ret = pGetNamedPipeClientProcessId(server, &pid);
3485 ok(ret, "got %lu\n", GetLastError());
3486 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3487
3488 pid = 0;
3489 ret = pGetNamedPipeClientProcessId(client, &pid);
3490 ok(ret, "got %lu\n", GetLastError());
3491 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3492
3493 SetLastError(0xdeadbeef);
3494 ret = pGetNamedPipeServerProcessId(server, NULL);
3495 ok(!ret, "success\n");
3496 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
3497
3498 pid = 0;
3499 ret = pGetNamedPipeServerProcessId(client, &pid);
3500 ok(ret, "got %lu\n", GetLastError());
3501 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3502
3503 pid = 0;
3504 ret = pGetNamedPipeServerProcessId(server, &pid);
3505 ok(ret, "got %lu\n", GetLastError());
3506 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3507
3508 /* closed client handle */
3509 CloseHandle(client);
3510 pid = 0;
3511 ret = pGetNamedPipeClientProcessId(server, &pid);
3512 ok(ret, "got %lu\n", GetLastError());
3513 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3514
3515 pid = 0;
3516 ret = pGetNamedPipeServerProcessId(server, &pid);
3517 ok(ret, "got %lu\n", GetLastError());
3518 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3519 CloseHandle(server);
3520
3521 /* disconnected server */
3522 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3523 DisconnectNamedPipe(server);
3524
3525 SetLastError(0xdeadbeef);
3526 ret = pGetNamedPipeClientProcessId(server, &pid);
3527 todo_wine ok(!ret, "success\n");
3528 todo_wine ok(GetLastError() == ERROR_NOT_FOUND, "got %lu\n", GetLastError());
3529
3530 pid = 0;
3531 ret = pGetNamedPipeServerProcessId(server, &pid);
3532 ok(ret, "got %lu\n", GetLastError());
3533 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3534
3535 SetLastError(0xdeadbeef);
3536 ret = pGetNamedPipeClientProcessId(client, &pid);
3537 todo_wine ok(!ret, "success\n");
3538 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %lu\n", GetLastError());
3539
3540 SetLastError(0xdeadbeef);
3541 ret = pGetNamedPipeServerProcessId(client, &pid);
3542 todo_wine ok(!ret, "success\n");
3543 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %lu\n", GetLastError());
3544 CloseHandle(client);
3545 CloseHandle(server);
3546
3547 /* closed server handle */
3548 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3549 CloseHandle(server);
3550
3551 pid = 0;
3552 ret = pGetNamedPipeClientProcessId(client, &pid);
3553 ok(ret, "got %lu\n", GetLastError());
3554 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3555
3556 pid = 0;
3557 ret = pGetNamedPipeServerProcessId(client, &pid);
3558 ok(ret, "got %lu\n", GetLastError());
3559 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3560 CloseHandle(client);
3561
3562 /* different process */
3563 memset(&overlapped, 0, sizeof(overlapped));
3564 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3565 server = create_overlapped_server( &overlapped );
3566 ok(server != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3567
3568 process = create_check_id_process("checkpid", GetProcessId(GetCurrentProcess()));
3569 wait_child_process(process);
3570
3571 CloseHandle(overlapped.hEvent);
3572 CloseHandle(process);
3573 CloseHandle(server);
3574}
3575
3576static void child_process_check_session_id(DWORD server_id)
3577{
3578 DWORD current;
3579 HANDLE pipe;
3580 ULONG id;
3581 BOOL ret;
3582
3583 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), ¤t);
3584
3585 pipe = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3586 ok(pipe != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3587
3588 id = 0;
3589 ret = pGetNamedPipeClientSessionId(pipe, &id);
3590 ok(ret, "got %lu\n", GetLastError());
3591 ok(id == current, "got %04lx\n", id);
3592
3593 id = 0;
3594 ret = pGetNamedPipeServerSessionId(pipe, &id);
3595 ok(ret, "got %lu\n", GetLastError());
3596 ok(id == server_id, "got %04lx expected %04lx\n", id, server_id);
3597 CloseHandle(pipe);
3598}
3599
3600static void test_namedpipe_session_id(void)
3601{
3602 HANDLE client, server, process;
3603 OVERLAPPED overlapped;
3604 DWORD current;
3605 ULONG id;
3606 BOOL ret;
3607
3608#if defined(__REACTOS__) && DLL_EXPORT_VERSION >= 0x600
3609 /* FIXME: GetNamedPipeClientSessionId is a STUB on ReactOS. */
3610 if (is_reactos() || !pGetNamedPipeClientSessionId)
3611#else
3612 if (!pGetNamedPipeClientSessionId)
3613#endif
3614 {
3615 win_skip("GetNamedPipeClientSessionId not available\n");
3616 return;
3617 }
3618
3619 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), ¤t);
3620
3621 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3622
3623 if (0) /* crashes on recent Windows */
3624 {
3625 SetLastError(0xdeadbeef);
3626 ret = pGetNamedPipeClientSessionId(server, NULL);
3627 ok(!ret, "success\n");
3628 }
3629
3630 id = 0;
3631 ret = pGetNamedPipeClientSessionId(server, &id);
3632 ok(ret, "got %lu\n", GetLastError());
3633 ok(id == current, "got %lu expected %lu\n", id, current);
3634
3635 id = 0;
3636 ret = pGetNamedPipeClientSessionId(client, &id);
3637 ok(ret, "got %lu\n", GetLastError());
3638 ok(id == current, "got %lu expected %lu\n", id, current);
3639
3640 SetLastError(0xdeadbeef);
3641 ret = pGetNamedPipeServerSessionId(server, NULL);
3642 ok(!ret, "success\n");
3643 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
3644
3645 id = 0;
3646 ret = pGetNamedPipeServerSessionId(client, &id);
3647 ok(ret, "got %lu\n", GetLastError());
3648 ok(id == current, "got %lu expected %lu\n", id, current);
3649
3650 id = 0;
3651 ret = pGetNamedPipeServerSessionId(server, &id);
3652 ok(ret, "got %lu\n", GetLastError());
3653 ok(id == current, "got %lu expected %lu\n", id, current);
3654
3655 /* closed client handle */
3656 CloseHandle(client);
3657
3658 id = 0;
3659 ret = pGetNamedPipeClientSessionId(server, &id);
3660 ok(ret, "got %lu\n", GetLastError());
3661 ok(id == current, "got %04lx expected %04lx\n", id, current);
3662
3663 id = 0;
3664 ret = pGetNamedPipeServerSessionId(server, &id);
3665 ok(ret, "got %lu\n", GetLastError());
3666 ok(id == current, "got %04lx expected %04lx\n", id, current);
3667 CloseHandle(server);
3668
3669 /* disconnected server */
3670 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3671 DisconnectNamedPipe(server);
3672
3673 SetLastError(0xdeadbeef);
3674 ret = pGetNamedPipeClientSessionId(server, &id);
3675 todo_wine ok(!ret, "success\n");
3676 todo_wine ok(GetLastError() == ERROR_NOT_FOUND, "got %lu\n", GetLastError());
3677
3678 id = 0;
3679 ret = pGetNamedPipeServerSessionId(server, &id);
3680 ok(ret, "got %lu\n", GetLastError());
3681 ok(id == current, "got %04lx expected %04lx\n", id, current);
3682
3683 SetLastError(0xdeadbeef);
3684 ret = pGetNamedPipeClientSessionId(client, &id);
3685 todo_wine ok(!ret, "success\n");
3686 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %lu\n", GetLastError());
3687
3688 SetLastError(0xdeadbeef);
3689 ret = pGetNamedPipeServerSessionId(client, &id);
3690 todo_wine ok(!ret, "success\n");
3691 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %lu\n", GetLastError());
3692 CloseHandle(client);
3693 CloseHandle(server);
3694
3695 /* closed server handle */
3696 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3697 CloseHandle(server);
3698
3699 id = 0;
3700 ret = pGetNamedPipeClientSessionId(client, &id);
3701 ok(ret, "got %lu\n", GetLastError());
3702 ok(id == current, "got %04lx expected %04lx\n", id, current);
3703
3704 id = 0;
3705 ret = pGetNamedPipeServerSessionId(client, &id);
3706 ok(ret, "got %lu\n", GetLastError());
3707 ok(id == current, "got %04lx expected %04lx\n", id, current);
3708 CloseHandle(client);
3709
3710 /* different process */
3711 memset(&overlapped, 0, sizeof(overlapped));
3712 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3713 server = create_overlapped_server( &overlapped );
3714 ok(server != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3715
3716 process = create_check_id_process("checksessionid", current);
3717 wait_child_process(process);
3718
3719 CloseHandle(overlapped.hEvent);
3720 CloseHandle(process);
3721 CloseHandle(server);
3722}
3723
3724static void test_multiple_instances(void)
3725{
3726 HANDLE server[4], client;
3727 int i;
3728 BOOL ret;
3729 OVERLAPPED ov;
3730
3731 if(!pCancelIoEx)
3732 {
3733 win_skip("Skipping multiple instance tests on too old Windows\n");
3734 return;
3735 }
3736
3737 for (i = 0; i < ARRAY_SIZE(server); i++)
3738 {
3739 server[i] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3740 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3741 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3742 ok(server[i] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3743 }
3744
3745 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3746 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3747
3748 /* Show that this has connected to server[0] not any other one */
3749
3750 memset(&ov, 0, sizeof(ov));
3751 ret = ConnectNamedPipe(server[2], &ov);
3752 ok(ret == FALSE, "got %d\n", ret);
3753 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3754
3755 memset(&ov, 0, sizeof(ov));
3756 ret = ConnectNamedPipe(server[0], &ov);
3757 ok(ret == FALSE, "got %d\n", ret);
3758 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3759
3760 CloseHandle(client);
3761
3762 /* The next connected server is server[1], doesn't matter that server[2] has pending listeners */
3763
3764 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3765 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3766
3767 memset(&ov, 0, sizeof(ov));
3768 ret = ConnectNamedPipe(server[2], &ov);
3769 ok(ret == FALSE, "got %d\n", ret);
3770 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3771
3772 memset(&ov, 0, sizeof(ov));
3773 ret = ConnectNamedPipe(server[1], &ov);
3774 ok(ret == FALSE, "got %d\n", ret);
3775 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3776
3777 CloseHandle(client);
3778
3779 /* server[2] is connected next */
3780
3781 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3782 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3783
3784 memset(&ov, 0, sizeof(ov));
3785 ret = ConnectNamedPipe(server[2], &ov);
3786 ok(ret == FALSE, "got %d\n", ret);
3787 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3788
3789 CloseHandle(client);
3790
3791 /* Disconnect in order server[0] and server[2] */
3792
3793 DisconnectNamedPipe(server[0]);
3794 DisconnectNamedPipe(server[2]);
3795
3796 /* Put into listening state server[2] and server[0] */
3797
3798 memset(&ov, 0, sizeof(ov));
3799 ret = ConnectNamedPipe(server[2], &ov);
3800 ok(ret == FALSE, "got %d\n", ret);
3801 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3802
3803 memset(&ov, 0, sizeof(ov));
3804 ret = ConnectNamedPipe(server[0], &ov);
3805 ok(ret == FALSE, "got %d\n", ret);
3806 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3807
3808 /* server[3] is connected next */
3809
3810 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3811 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3812
3813 memset(&ov, 0, sizeof(ov));
3814 ret = ConnectNamedPipe(server[3], &ov);
3815 ok(ret == FALSE, "got %d\n", ret);
3816 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3817
3818 CloseHandle(client);
3819
3820 /* server[2], which stasted listening first, will be connected next */
3821
3822 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3823 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3824
3825 memset(&ov, 0, sizeof(ov));
3826 ret = ConnectNamedPipe(server[2], &ov);
3827 ok(ret == FALSE, "got %d\n", ret);
3828 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3829
3830 memset(&ov, 0, sizeof(ov));
3831 ret = ConnectNamedPipe(server[0], &ov);
3832 ok(ret == FALSE, "got %d\n", ret);
3833 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3834
3835 CloseHandle(client);
3836
3837 /* Finally server[0] is connected */
3838
3839 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3840 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3841
3842 memset(&ov, 0, sizeof(ov));
3843 ret = ConnectNamedPipe(server[0], &ov);
3844 ok(ret == FALSE, "got %d\n", ret);
3845 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3846
3847 CloseHandle(client);
3848
3849 /* No more listening pipes available */
3850 DisconnectNamedPipe(server[0]);
3851 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3852 ok(client == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY, "got %p(%lu)\n", client, GetLastError());
3853
3854 for (i = 0; i < ARRAY_SIZE(server); i++)
3855 {
3856 DisconnectNamedPipe(server[i]);
3857 CloseHandle(server[i]);
3858 }
3859}
3860
3861static DWORD WINAPI wait_pipe_proc(void *arg)
3862{
3863 BOOL ret;
3864 ret = WaitNamedPipeA(PIPENAME, 1000);
3865 ok(ret, "WaitNamedPipe failed (%lu)\n", GetLastError());
3866 return 0;
3867}
3868
3869static HANDLE async_wait_pipe(void)
3870{
3871 HANDLE thread;
3872 BOOL ret;
3873
3874 thread = CreateThread(NULL, 0, wait_pipe_proc, NULL, 0, NULL);
3875 ok(thread != NULL, "CreateThread failed: %lu\n", GetLastError());
3876
3877 ret = WaitNamedPipeA(PIPENAME, 1);
3878 ok(!ret && GetLastError() == ERROR_SEM_TIMEOUT, "WaitNamedPipe failed %x(%lu)\n", ret, GetLastError());
3879
3880 return thread;
3881}
3882
3883static void test_wait_pipe(void)
3884{
3885 HANDLE server[2], client, wait;
3886 OVERLAPPED ov;
3887 DWORD res;
3888 BOOL ret;
3889
3890 ret = WaitNamedPipeA(PIPENAME, 0);
3891 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "WaitNamedPipe failed %x(%lu)\n", ret, GetLastError());
3892
3893 server[0] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3894 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3895 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3896 ok(server[0] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3897
3898 ret = WaitNamedPipeA(PIPENAME, 1);
3899 ok(ret, "WaitNamedPipe failed (%lu)\n", GetLastError());
3900
3901 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3902 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3903
3904 /* Creating a new pipe server wakes waiters */
3905 wait = async_wait_pipe();
3906 server[1] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3907 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3908 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3909 ok(server[1] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3910
3911 res = WaitForSingleObject(wait, 100);
3912 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", res);
3913
3914 CloseHandle(wait);
3915 CloseHandle(server[1]);
3916
3917 CloseHandle(client);
3918 ret = DisconnectNamedPipe(server[0]);
3919 ok(ret, "DisconnectNamedPipe failed (%lu)\n", GetLastError());
3920
3921 /* Putting pipe server into waiting listening state wakes waiters */
3922 wait = async_wait_pipe();
3923 memset(&ov, 0, sizeof(ov));
3924 ov.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3925 ret = ConnectNamedPipe(server[0], &ov);
3926 ok(ret == FALSE, "got %d\n", ret);
3927 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3928
3929 res = WaitForSingleObject(wait, 100);
3930 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", res);
3931 CloseHandle(server[0]);
3932
3933 res = WaitForSingleObject(ov.hEvent, 0);
3934 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", res);
3935 CloseHandle(ov.hEvent);
3936}
3937
3938static void test_nowait(DWORD pipe_type)
3939{
3940 HANDLE piperead, pipewrite, file;
3941 OVERLAPPED ol, ol2;
3942 DWORD read, write;
3943 char readbuf[32768];
3944 static const char teststring[] = "bits";
3945
3946 /* CreateNamedPipe with PIPE_NOWAIT, and read from empty pipe */
3947 piperead = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3948 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
3949 /* nMaxInstances */ 1,
3950 /* nOutBufSize */ 512,
3951 /* nInBufSize */ 512,
3952 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
3953 /* lpSecurityAttrib */ NULL);
3954 ok(piperead != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
3955 pipewrite = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3956 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
3957 memset(&ol, 0, sizeof(ol));
3958 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3959 SetLastError(0xdeadbeef);
3960 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol) == FALSE, "ReadFile should fail\n");
3961 ok(GetLastError() == ERROR_NO_DATA, "got %ld should be ERROR_NO_DATA\n", GetLastError());
3962 if (GetLastError() == ERROR_IO_PENDING)
3963 CancelIo(piperead);
3964
3965 /* test a small write/read */
3966 ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, NULL), "WriteFile should succeed\n");
3967 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol), "ReadFile should succeed\n");
3968 ok(read == write, "read/write bytes should match\n");
3969 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
3970 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
3971 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
3972
3973
3974 /* create write side with PIPE_NOWAIT, read side PIPE_WAIT, and test writes */
3975 pipewrite = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3976 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
3977 /* nMaxInstances */ 1,
3978 /* nOutBufSize */ 512,
3979 /* nInBufSize */ 512,
3980 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
3981 /* lpSecurityAttrib */ NULL);
3982 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
3983 piperead = CreateFileA(PIPENAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
3984 ok(piperead != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
3985 memset(&ol, 0, sizeof(ol));
3986 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3987 memset(&ol2, 0, sizeof(ol2));
3988 ol2.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3989
3990 /* write one byte larger than the buffer size, should fail */
3991 SetLastError(0xdeadbeef);
3992 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
3993 /* WriteFile only documents that 'write < sizeof(readbuf)' for this case, but Windows
3994 * doesn't seem to do partial writes ('write == 0' always)
3995 */
3996 ok(write < sizeof(readbuf), "WriteFile should fail to write the whole buffer\n");
3997 ok(write == 0, "WriteFile doesn't do partial writes here\n");
3998 if (GetLastError() == ERROR_IO_PENDING)
3999 CancelIo(piperead);
4000
4001 /* overlapped read of 32768, non-blocking write of 512 */
4002 SetLastError(0xdeadbeef);
4003 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n");
4004 ok(GetLastError() == ERROR_IO_PENDING, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4005 ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, &ol), "WriteFile should succeed\n");
4006 ok(write == sizeof(teststring), "got %ld\n", write);
4007 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
4008 ok(read == sizeof(teststring), "got %ld\n", read);
4009 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4010 CancelIo(piperead);
4011
4012 /* overlapped read of 32768, non-blocking write of 513 */
4013 SetLastError(0xdeadbeef);
4014 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n");
4015 ok(GetLastError() == ERROR_IO_PENDING, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4016 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
4017 ok(write == 513, "got %ld, write should be %d\n", write, 513);
4018 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
4019 ok(read == 513, "got %ld, read should be %d\n", read, 513);
4020 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4021 CancelIo(piperead);
4022
4023 /* overlapped read of 1 byte, non-blocking write of 513 bytes */
4024 SetLastError(0xdeadbeef);
4025 ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n");
4026 ok(GetLastError() == ERROR_IO_PENDING, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4027 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
4028 ok(write == 513, "got %ld, write should be %d\n", write, 513);
4029 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
4030 ok(read == 1, "got %ld, read should be %d\n", read, 1);
4031 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4032 CancelIo(piperead);
4033 /* read the remaining 512 bytes */
4034 SetLastError(0xdeadbeef);
4035 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2), "ReadFile should succeed\n");
4036 ok(read == 512, "got %ld, write should be %d\n", write, 512);
4037 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4038 CancelIo(piperead);
4039
4040 /* overlapped read of 1 byte, non-blocking write of 514 bytes */
4041 SetLastError(0xdeadbeef);
4042 ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n");
4043 ok(GetLastError() == ERROR_IO_PENDING, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4044 ok(WriteFile(pipewrite, readbuf, 514, &write, &ol), "WriteFile should succeed\n");
4045 if (pipe_type == PIPE_TYPE_MESSAGE)
4046 {
4047 todo_wine
4048 ok(write == 0, "got %ld\n", write);
4049 todo_wine
4050 ok(!GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should fail\n");
4051 todo_wine
4052 ok(GetLastError() == ERROR_IO_INCOMPLETE, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4053 todo_wine
4054 ok(read == 0, "got %ld, read should be %d\n", read, 1);
4055 }
4056 else
4057 {
4058 ok(write == 1, "got %ld\n", write);
4059 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should fail\n");
4060 ok(read == 1, "got %ld, read should be %d\n", read, 1);
4061 }
4062 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4063 CancelIo(piperead);
4064
4065 /* write the exact buffer size, should succeed */
4066 SetLastError(0xdeadbeef);
4067 ok(WriteFile(pipewrite, readbuf, 512, &write, &ol), "WriteFile should succeed\n");
4068 ok(write == 512, "WriteFile should write the whole buffer\n");
4069 if (GetLastError() == ERROR_IO_PENDING)
4070 CancelIo(piperead);
4071
4072 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
4073 ok(CloseHandle(ol2.hEvent), "CloseHandle for the event failed\n");
4074 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
4075 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
4076
4077
4078 /* CreateNamedPipe with PIPE_NOWAIT, test ConnectNamedPipe */
4079 pipewrite = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
4080 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
4081 /* nMaxInstances */ 1,
4082 /* nOutBufSize */ 512,
4083 /* nInBufSize */ 512,
4084 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
4085 /* lpSecurityAttrib */ NULL);
4086 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
4087 memset(&ol, 0, sizeof(ol));
4088 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
4089 SetLastError(0xdeadbeef);
4090 ok(ConnectNamedPipe(pipewrite, &ol) == FALSE, "ConnectNamedPipe should fail\n");
4091 ok(GetLastError() == ERROR_PIPE_LISTENING, "got %ld should be ERROR_PIPE_LISTENING\n", GetLastError());
4092 if (GetLastError() == ERROR_IO_PENDING)
4093 CancelIo(pipewrite);
4094
4095 /* connect and disconnect, then test ConnectNamedPipe again */
4096 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
4097 ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
4098 ok(CloseHandle(file), "CloseHandle failed\n");
4099 SetLastError(0xdeadbeef);
4100 ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n");
4101 ok(GetLastError() == ERROR_NO_DATA, "got %ld should be ERROR_NO_DATA\n", GetLastError());
4102 if (GetLastError() == ERROR_IO_PENDING)
4103 CancelIo(pipewrite);
4104
4105 /* call DisconnectNamedPipe and test ConnectNamedPipe again */
4106 ok(DisconnectNamedPipe(pipewrite) == TRUE, "DisconnectNamedPipe should succeed\n");
4107 SetLastError(0xdeadbeef);
4108 ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n");
4109 ok(GetLastError() == ERROR_PIPE_LISTENING, "got %ld should be ERROR_PIPE_LISTENING\n", GetLastError());
4110 if (GetLastError() == ERROR_IO_PENDING)
4111 CancelIo(pipewrite);
4112 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
4113 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
4114}
4115
4116static void test_GetOverlappedResultEx(void)
4117{
4118 HANDLE client, server;
4119 OVERLAPPED ovl;
4120 char buffer[8000];
4121 DWORD ret_size;
4122 BOOL ret;
4123
4124 if (!pGetOverlappedResultEx)
4125 {
4126 win_skip("GetOverlappedResultEx() is not available\n");
4127 return;
4128 }
4129
4130 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
4131
4132 overlapped_write_async(client, buffer, sizeof(buffer), &ovl);
4133
4134 user_apc_ran = FALSE;
4135 QueueUserAPC(user_apc, GetCurrentThread(), 0);
4136
4137 SetLastError(0xdeadbeef);
4138 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 0, FALSE);
4139 ok(!ret, "expected failure\n");
4140 ok(GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %lu\n", GetLastError());
4141 ok(!user_apc_ran, "APC should not have run\n");
4142
4143 SetLastError(0xdeadbeef);
4144 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 0, TRUE);
4145 ok(!ret, "expected failure\n");
4146 ok(GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %lu\n", GetLastError());
4147 ok(!user_apc_ran, "APC should not have run\n");
4148
4149 SetLastError(0xdeadbeef);
4150 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 10, FALSE);
4151 ok(!ret, "expected failure\n");
4152 ok(GetLastError() == WAIT_TIMEOUT, "wrong error %lu\n", GetLastError());
4153 ok(!user_apc_ran, "APC should not have run\n");
4154
4155 SetLastError(0xdeadbeef);
4156 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 10, TRUE);
4157 ok(!ret, "expected failure\n");
4158 ok(GetLastError() == WAIT_IO_COMPLETION, "wrong error %lu\n", GetLastError());
4159 ok(user_apc_ran, "APC should have run\n");
4160
4161 CloseHandle(ovl.hEvent);
4162
4163 CloseHandle(client);
4164 CloseHandle(server);
4165}
4166
4167static void child_process_exit_process_async(DWORD parent_pid, HANDLE parent_pipe)
4168{
4169 OVERLAPPED overlapped = {0};
4170 static char buffer[1];
4171 HANDLE parent, pipe;
4172 BOOL ret;
4173
4174 parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, parent_pid);
4175 ok(!!parent, "got parent %p\n", parent);
4176
4177 ret = DuplicateHandle(parent, parent_pipe, GetCurrentProcess(), &pipe, 0,
4178 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
4179 ok(ret, "got error %lu\n", GetLastError());
4180
4181 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
4182
4183 ret = ReadFile(pipe, buffer, sizeof(buffer), NULL, &overlapped);
4184 ok(!ret, "expected failure\n");
4185 ok(GetLastError() == ERROR_IO_PENDING, "got error %lu\n", GetLastError());
4186
4187 /* exit without closing the pipe handle */
4188}
4189
4190static void test_exit_process_async(void)
4191{
4192 HANDLE client, server, port;
4193 OVERLAPPED *overlapped;
4194 PROCESS_INFORMATION pi;
4195 STARTUPINFOA si = {0};
4196 char cmdline[300];
4197 ULONG_PTR key;
4198 char **argv;
4199 DWORD size;
4200 BOOL ret;
4201
4202 winetest_get_mainargs(&argv);
4203
4204 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
4205 port = CreateIoCompletionPort(client, NULL, 123, 0);
4206
4207 sprintf(cmdline, "%s pipe exit_process_async %lx %p", argv[0], GetCurrentProcessId(), client);
4208 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
4209 ok(ret, "got error %lu\n", GetLastError());
4210 ret = WaitForSingleObject(pi.hProcess, 1000);
4211 ok(!ret, "wait timed out\n");
4212 CloseHandle(pi.hThread);
4213 CloseHandle(pi.hProcess);
4214
4215 key = 0xdeadbeef;
4216 size = 0xdeadbeef;
4217 ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped, 1000);
4218 ok(!ret, "expected failure\n");
4219 ok(GetLastError() == ERROR_OPERATION_ABORTED, "got error %lu\n", GetLastError());
4220 ok(!size, "got size %lu\n", size);
4221 ok(key == 123, "got key %Iu\n", key);
4222
4223 CloseHandle(port);
4224 CloseHandle(server);
4225}
4226
4227static DWORD CALLBACK synchronousIoThreadMain(void *arg)
4228{
4229 HANDLE pipe;
4230 BOOL ret;
4231
4232 pipe = arg;
4233 SetLastError(0xdeadbeef);
4234 ret = ConnectNamedPipe(pipe, NULL);
4235 ok(!ret, "expected failure\n");
4236 ok(GetLastError() == ERROR_OPERATION_ABORTED, "got error %lu\n", GetLastError());
4237 return 0;
4238}
4239
4240static DWORD CALLBACK synchronousIoThreadMain2(void *arg)
4241{
4242 OVERLAPPED ov;
4243 HANDLE pipe;
4244 BOOL ret;
4245
4246 pipe = arg;
4247 memset(&ov, 0, sizeof(ov));
4248 ov.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
4249 SetLastError(0xdeadbeef);
4250 ret = ConnectNamedPipe(pipe, &ov);
4251 ok(!ret, "expected failure\n");
4252 ok(GetLastError() == ERROR_IO_PENDING, "got error %lu\n", GetLastError());
4253 ret = WaitForSingleObject(ov.hEvent, 1000);
4254 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", ret);
4255 CloseHandle(ov.hEvent);
4256 return 0;
4257}
4258
4259static void test_CancelSynchronousIo(void)
4260{
4261 BOOL res;
4262 DWORD wait;
4263 HANDLE file;
4264 HANDLE pipe;
4265 HANDLE thread;
4266
4267 /* bogus values */
4268 SetLastError(0xdeadbeef);
4269 res = pCancelSynchronousIo((HANDLE)0xdeadbeef);
4270 ok(!res, "CancelSynchronousIo succeeded unexpectedly\n");
4271 ok(GetLastError() == ERROR_INVALID_HANDLE,
4272 "In CancelSynchronousIo failure, expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
4273
4274 SetLastError(0xdeadbeef);
4275 res = pCancelSynchronousIo(GetCurrentThread());
4276 ok(!res, "CancelSynchronousIo succeeded unexpectedly\n");
4277 ok(GetLastError() == ERROR_NOT_FOUND,
4278 "In CancelSynchronousIo failure, expected ERROR_NOT_FOUND, got %ld\n", GetLastError());
4279
4280 /* synchronous i/o */
4281 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
4282 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
4283 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
4284 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
4285 thread = CreateThread(NULL, 0, synchronousIoThreadMain, pipe, 0, NULL);
4286 /* wait for I/O to start, which transitions the pipe handle from signaled to nonsignaled state. */
4287 while ((wait = WaitForSingleObject(pipe, 0)) == WAIT_OBJECT_0) Sleep(1);
4288 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (error %lu)\n", wait, GetLastError());
4289 SetLastError(0xdeadbeef);
4290 res = pCancelSynchronousIo(thread);
4291 ok(res, "CancelSynchronousIo failed with error %ld\n", GetLastError());
4292 ok(GetLastError() == 0xdeadbeef,
4293 "In CancelSynchronousIo failure, expected 0xdeadbeef got %ld\n", GetLastError());
4294 wait = WaitForSingleObject(thread, 1000);
4295 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", wait);
4296 CloseHandle(thread);
4297 CloseHandle(pipe);
4298
4299 /* asynchronous i/o */
4300 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
4301 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
4302 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
4303 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
4304 thread = CreateThread(NULL, 0, synchronousIoThreadMain2, pipe, 0, NULL);
4305 /* wait for I/O to start, which transitions the pipe handle from signaled to nonsignaled state. */
4306 while ((wait = WaitForSingleObject(pipe, 0)) == WAIT_OBJECT_0) Sleep(1);
4307 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (error %lu)\n", wait, GetLastError());
4308 SetLastError(0xdeadbeef);
4309 res = pCancelSynchronousIo(thread);
4310 ok(!res, "CancelSynchronousIo succeeded unexpectedly\n");
4311 ok(GetLastError() == ERROR_NOT_FOUND,
4312 "In CancelSynchronousIo failure, expected ERROR_NOT_FOUND, got %ld\n", GetLastError());
4313 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
4314 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed (%ld)\n", GetLastError());
4315 WaitForSingleObject(thread, INFINITE);
4316 CloseHandle(thread);
4317 CloseHandle(file);
4318 CloseHandle(pipe);
4319}
4320
4321START_TEST(pipe)
4322{
4323 char **argv;
4324 int argc;
4325 HMODULE hmod;
4326
4327 hmod = GetModuleHandleA("advapi32.dll");
4328 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
4329 hmod = GetModuleHandleA("kernel32.dll");
4330 pCancelIoEx = (void *) GetProcAddress(hmod, "CancelIoEx");
4331 pCancelSynchronousIo = (void *) GetProcAddress(hmod, "CancelSynchronousIo");
4332 pGetNamedPipeClientProcessId = (void *) GetProcAddress(hmod, "GetNamedPipeClientProcessId");
4333 pGetNamedPipeServerProcessId = (void *) GetProcAddress(hmod, "GetNamedPipeServerProcessId");
4334 pGetNamedPipeClientSessionId = (void *) GetProcAddress(hmod, "GetNamedPipeClientSessionId");
4335 pGetNamedPipeServerSessionId = (void *) GetProcAddress(hmod, "GetNamedPipeServerSessionId");
4336 pGetOverlappedResultEx = (void *)GetProcAddress(hmod, "GetOverlappedResultEx");
4337
4338 argc = winetest_get_mainargs(&argv);
4339
4340 if (argc > 3)
4341 {
4342 if (!strcmp(argv[2], "writepipe"))
4343 {
4344 ULONG handle;
4345 sscanf(argv[3], "%lx", &handle);
4346 child_process_write_pipe(ULongToHandle(handle));
4347 return;
4348 }
4349 if (!strcmp(argv[2], "checkpid"))
4350 {
4351 DWORD pid = GetProcessId(GetCurrentProcess());
4352 sscanf(argv[3], "%lx", &pid);
4353 child_process_check_pid(pid);
4354 return;
4355 }
4356 if (!strcmp(argv[2], "checksessionid"))
4357 {
4358 DWORD id;
4359 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), &id);
4360 sscanf(argv[3], "%lx", &id);
4361 child_process_check_session_id(id);
4362 return;
4363 }
4364 if (!strcmp(argv[2], "exit_process_async"))
4365 {
4366 HANDLE handle;
4367 DWORD pid;
4368 sscanf(argv[3], "%lx", &pid);
4369 sscanf(argv[4], "%p", &handle);
4370 child_process_exit_process_async(pid, handle);
4371 return;
4372 }
4373 }
4374
4375 if (test_DisconnectNamedPipe())
4376 return;
4377 test_CreateNamedPipe_instances_must_match();
4378 test_NamedPipe_2();
4379 test_CreateNamedPipe(PIPE_TYPE_BYTE);
4380 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
4381 test_CreatePipe();
4382 test_ReadFile();
4383 test_CloseHandle();
4384 test_impersonation();
4385 test_overlapped();
4386 test_overlapped_error();
4387 test_NamedPipeHandleState();
4388 test_GetNamedPipeInfo();
4389 test_readfileex_pending();
4390 test_overlapped_transport(TRUE, FALSE);
4391 test_overlapped_transport(TRUE, TRUE);
4392 test_overlapped_transport(FALSE, FALSE);
4393 test_TransactNamedPipe();
4394 test_namedpipe_process_id();
4395 test_namedpipe_session_id();
4396 test_multiple_instances();
4397 test_wait_pipe();
4398 test_nowait(PIPE_TYPE_BYTE);
4399 test_nowait(PIPE_TYPE_MESSAGE);
4400 test_GetOverlappedResultEx();
4401#ifdef __REACTOS__
4402 if (is_reactos() || GetNTVersion() <= _WIN32_WINNT_WS03) {
4403 skip("These next tests crash or hang on ReactOS and Windows Server 2003.\n");
4404 return;
4405 }
4406#endif
4407 test_exit_process_async();
4408 test_CancelSynchronousIo();
4409}