kernel32: Implement GetNamedPipeHandleState.
[wine/wine-gecko.git] / dlls / kernel32 / tests / pipe.c
blob20c2c61f57e8e5c5814b2f3c0fe00afae22f7839
1 /*
2 * Unit tests for named pipe functions in Wine
4 * Copyright (c) 2002 Dan Kegel
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "wine/test.h"
31 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
33 #define NB_SERVER_LOOPS 8
35 static HANDLE alarm_event;
36 static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
37 SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
38 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
40 static BOOL user_apc_ran;
41 static void CALLBACK user_apc(ULONG_PTR param)
43 user_apc_ran = TRUE;
46 static void test_CreateNamedPipe(int pipemode)
48 HANDLE hnp;
49 HANDLE hFile;
50 static const char obuf[] = "Bit Bucket";
51 static const char obuf2[] = "More bits";
52 char ibuf[32], *pbuf;
53 DWORD written;
54 DWORD readden;
55 DWORD avail;
56 DWORD lpmode;
57 BOOL ret;
59 if (pipemode == PIPE_TYPE_BYTE)
60 trace("test_CreateNamedPipe starting in byte mode\n");
61 else
62 trace("test_CreateNamedPipe starting in message mode\n");
64 /* Wait for non existing pipe */
65 ret = WaitNamedPipeA(PIPENAME, 2000);
66 ok(ret == 0, "WaitNamedPipe returned %d for non existing pipe\n", ret);
67 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
69 /* Bad parameter checks */
70 hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
71 /* nMaxInstances */ 1,
72 /* nOutBufSize */ 1024,
73 /* nInBufSize */ 1024,
74 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
75 /* lpSecurityAttrib */ NULL);
76 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
77 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
79 if (pipemode == PIPE_TYPE_BYTE)
81 /* Bad parameter checks */
82 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
83 /* nMaxInstances */ 1,
84 /* nOutBufSize */ 1024,
85 /* nInBufSize */ 1024,
86 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
87 /* lpSecurityAttrib */ NULL);
88 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
89 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
92 hnp = CreateNamedPipeA(NULL,
93 PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
94 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
95 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
96 "CreateNamedPipe should fail if name is NULL\n");
98 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
99 ok(hFile == INVALID_HANDLE_VALUE
100 && GetLastError() == ERROR_FILE_NOT_FOUND,
101 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
103 /* Functional checks */
105 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
106 /* nMaxInstances */ 1,
107 /* nOutBufSize */ 1024,
108 /* nInBufSize */ 1024,
109 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
110 /* lpSecurityAttrib */ NULL);
111 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
113 ret = WaitNamedPipeA(PIPENAME, 2000);
114 ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
116 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
117 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
119 ok(!WaitNamedPipeA(PIPENAME, 1000), "WaitNamedPipe succeeded\n");
121 ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
123 /* don't try to do i/o if one side couldn't be opened, as it hangs */
124 if (hFile != INVALID_HANDLE_VALUE) {
125 HANDLE hFile2;
127 /* Make sure we can read and write a few bytes in both directions */
128 memset(ibuf, 0, sizeof(ibuf));
129 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
130 ok(written == sizeof(obuf), "write file len 1\n");
131 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
132 ok(readden == sizeof(obuf), "peek 1 got %d bytes\n", readden);
133 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
134 ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
135 ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
137 memset(ibuf, 0, sizeof(ibuf));
138 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
139 ok(written == sizeof(obuf2), "write file len 2\n");
140 ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
141 ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
142 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &readden, NULL), "Peek\n");
143 ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
144 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
145 ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
146 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
148 /* Test reading of multiple writes */
149 memset(ibuf, 0, sizeof(ibuf));
150 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
151 ok(written == sizeof(obuf), "write file len 3a\n");
152 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
153 ok(written == sizeof(obuf2), "write file len 3b\n");
154 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
155 if (pipemode == PIPE_TYPE_BYTE) {
156 if (readden != sizeof(obuf)) /* Linux only returns the first message */
157 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
158 else
159 todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
161 else
163 if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both messages */
164 ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
165 else
166 todo_wine ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
168 if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
169 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
170 pbuf = ibuf;
171 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
172 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
173 pbuf += sizeof(obuf);
174 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
176 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
177 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
178 pbuf = ibuf;
179 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
180 pbuf += sizeof(obuf);
181 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
183 /* Multiple writes in the reverse direction */
184 memset(ibuf, 0, sizeof(ibuf));
185 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
186 ok(written == sizeof(obuf), "write file len 4a\n");
187 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
188 ok(written == sizeof(obuf2), "write file len 4b\n");
189 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
190 if (pipemode == PIPE_TYPE_BYTE) {
191 if (readden != sizeof(obuf)) /* Linux only returns the first message */
192 /* should return all 23 bytes */
193 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
194 else
195 todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
197 else
199 if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both messages */
200 ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
201 else
202 todo_wine ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
204 if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
205 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
206 pbuf = ibuf;
207 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
208 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
209 pbuf += sizeof(obuf);
210 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
212 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
213 if (pipemode == PIPE_TYPE_BYTE) {
214 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
216 else {
217 todo_wine {
218 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
221 pbuf = ibuf;
222 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
223 if (pipemode == PIPE_TYPE_BYTE) {
224 pbuf += sizeof(obuf);
225 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
228 /* Test reading of multiple writes after a mode change
229 (CreateFile always creates a byte mode pipe) */
230 lpmode = PIPE_READMODE_MESSAGE;
231 if (pipemode == PIPE_TYPE_BYTE) {
232 /* trying to change the client end of a byte pipe to message mode should fail */
233 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
235 else {
236 todo_wine {
237 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
240 memset(ibuf, 0, sizeof(ibuf));
241 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
242 ok(written == sizeof(obuf), "write file len 3a\n");
243 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
244 ok(written == sizeof(obuf2), "write file len 3b\n");
245 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
246 if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both writes */
247 ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
248 else
249 todo_wine ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
250 if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
251 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
252 else
253 todo_wine ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
254 pbuf = ibuf;
255 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
256 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
257 todo_wine {
258 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
260 pbuf = ibuf;
261 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
263 /* Multiple writes in the reverse direction */
264 /* the write of obuf2 from write4 should still be in the buffer */
265 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
266 todo_wine {
267 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
268 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
270 if (avail > 0) {
271 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
272 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
273 pbuf = ibuf;
274 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
276 memset(ibuf, 0, sizeof(ibuf));
277 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
278 ok(written == sizeof(obuf), "write file len 6a\n");
279 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
280 ok(written == sizeof(obuf2), "write file len 6b\n");
281 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
282 if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both writes */
283 ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
284 else
285 todo_wine ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
286 if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
287 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
288 pbuf = ibuf;
289 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
290 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
291 todo_wine {
292 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
294 pbuf = ibuf;
295 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
298 /* Picky conformance tests */
300 /* Verify that you can't connect to pipe again
301 * until server calls DisconnectNamedPipe+ConnectNamedPipe
302 * or creates a new pipe
303 * case 1: other client not yet closed
305 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
306 ok(hFile2 == INVALID_HANDLE_VALUE,
307 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
308 ok(GetLastError() == ERROR_PIPE_BUSY,
309 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
311 ok(CloseHandle(hFile), "CloseHandle\n");
313 /* case 2: other client already closed */
314 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
315 ok(hFile == INVALID_HANDLE_VALUE,
316 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
317 ok(GetLastError() == ERROR_PIPE_BUSY,
318 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
320 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
322 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
323 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
324 ok(hFile == INVALID_HANDLE_VALUE,
325 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
326 ok(GetLastError() == ERROR_PIPE_BUSY,
327 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
329 /* to be complete, we'd call ConnectNamedPipe here and loop,
330 * but by default that's blocking, so we'd either have
331 * to turn on the uncommon nonblocking mode, or
332 * use another thread.
336 ok(CloseHandle(hnp), "CloseHandle\n");
338 trace("test_CreateNamedPipe returning\n");
341 static void test_CreateNamedPipe_instances_must_match(void)
343 HANDLE hnp, hnp2;
345 /* Check no mismatch */
346 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
347 /* nMaxInstances */ 2,
348 /* nOutBufSize */ 1024,
349 /* nInBufSize */ 1024,
350 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
351 /* lpSecurityAttrib */ NULL);
352 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
354 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
355 /* nMaxInstances */ 2,
356 /* nOutBufSize */ 1024,
357 /* nInBufSize */ 1024,
358 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
359 /* lpSecurityAttrib */ NULL);
360 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
362 ok(CloseHandle(hnp), "CloseHandle\n");
363 ok(CloseHandle(hnp2), "CloseHandle\n");
365 /* Check nMaxInstances */
366 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
367 /* nMaxInstances */ 1,
368 /* nOutBufSize */ 1024,
369 /* nInBufSize */ 1024,
370 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
371 /* lpSecurityAttrib */ NULL);
372 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
374 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
375 /* nMaxInstances */ 1,
376 /* nOutBufSize */ 1024,
377 /* nInBufSize */ 1024,
378 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
379 /* lpSecurityAttrib */ NULL);
380 ok(hnp2 == INVALID_HANDLE_VALUE
381 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
383 ok(CloseHandle(hnp), "CloseHandle\n");
385 /* Check PIPE_ACCESS_* */
386 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
387 /* nMaxInstances */ 2,
388 /* nOutBufSize */ 1024,
389 /* nInBufSize */ 1024,
390 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
391 /* lpSecurityAttrib */ NULL);
392 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
394 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
395 /* nMaxInstances */ 2,
396 /* nOutBufSize */ 1024,
397 /* nInBufSize */ 1024,
398 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
399 /* lpSecurityAttrib */ NULL);
400 ok(hnp2 == INVALID_HANDLE_VALUE
401 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
403 ok(CloseHandle(hnp), "CloseHandle\n");
405 /* check everything else */
406 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
407 /* nMaxInstances */ 4,
408 /* nOutBufSize */ 1024,
409 /* nInBufSize */ 1024,
410 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
411 /* lpSecurityAttrib */ NULL);
412 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
414 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
415 /* nMaxInstances */ 3,
416 /* nOutBufSize */ 102,
417 /* nInBufSize */ 24,
418 /* nDefaultWait */ 1234,
419 /* lpSecurityAttrib */ NULL);
420 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
422 ok(CloseHandle(hnp), "CloseHandle\n");
423 ok(CloseHandle(hnp2), "CloseHandle\n");
426 /** implementation of alarm() */
427 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
429 DWORD_PTR timeout = (DWORD_PTR) arg;
430 trace("alarmThreadMain\n");
431 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
433 ok(FALSE, "alarm\n");
434 ExitProcess(1);
436 return 1;
439 static HANDLE hnp = INVALID_HANDLE_VALUE;
441 /** Trivial byte echo server - disconnects after each session */
442 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
444 int i;
446 trace("serverThreadMain1 start\n");
447 /* Set up a simple echo server */
448 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
449 PIPE_TYPE_BYTE | PIPE_WAIT,
450 /* nMaxInstances */ 1,
451 /* nOutBufSize */ 1024,
452 /* nInBufSize */ 1024,
453 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
454 /* lpSecurityAttrib */ NULL);
456 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
457 for (i = 0; i < NB_SERVER_LOOPS; i++) {
458 char buf[512];
459 DWORD written;
460 DWORD readden;
461 BOOL success;
463 /* Wait for client to connect */
464 trace("Server calling ConnectNamedPipe...\n");
465 ok(ConnectNamedPipe(hnp, NULL)
466 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
467 trace("ConnectNamedPipe returned.\n");
469 /* Echo bytes once */
470 memset(buf, 0, sizeof(buf));
472 trace("Server reading...\n");
473 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
474 trace("Server done reading.\n");
475 ok(success, "ReadFile\n");
476 ok(readden, "short read\n");
478 trace("Server writing...\n");
479 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
480 trace("Server done writing.\n");
481 ok(written == readden, "write file len\n");
483 /* finish this connection, wait for next one */
484 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
485 trace("Server done flushing.\n");
486 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
487 trace("Server done disconnecting.\n");
489 return 0;
492 /** Trivial byte echo server - closes after each connection */
493 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
495 int i;
496 HANDLE hnpNext = 0;
498 trace("serverThreadMain2\n");
499 /* Set up a simple echo server */
500 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
501 PIPE_TYPE_BYTE | PIPE_WAIT,
502 /* nMaxInstances */ 2,
503 /* nOutBufSize */ 1024,
504 /* nInBufSize */ 1024,
505 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
506 /* lpSecurityAttrib */ NULL);
507 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
509 for (i = 0; i < NB_SERVER_LOOPS; i++) {
510 char buf[512];
511 DWORD written;
512 DWORD readden;
513 DWORD ret;
514 BOOL success;
517 user_apc_ran = FALSE;
518 if (i == 0 && pQueueUserAPC) {
519 trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
520 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
521 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
524 /* Wait for client to connect */
525 trace("Server calling ConnectNamedPipe...\n");
526 ok(ConnectNamedPipe(hnp, NULL)
527 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
528 trace("ConnectNamedPipe returned.\n");
530 /* Echo bytes once */
531 memset(buf, 0, sizeof(buf));
533 trace("Server reading...\n");
534 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
535 trace("Server done reading.\n");
536 ok(success, "ReadFile\n");
538 trace("Server writing...\n");
539 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
540 trace("Server done writing.\n");
541 ok(written == readden, "write file len\n");
543 /* finish this connection, wait for next one */
544 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
545 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
547 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
549 if (i == 0 && pQueueUserAPC)
550 SleepEx(0, TRUE); /* get rid of apc */
552 /* Set up next echo server */
553 hnpNext =
554 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
555 PIPE_TYPE_BYTE | PIPE_WAIT,
556 /* nMaxInstances */ 2,
557 /* nOutBufSize */ 1024,
558 /* nInBufSize */ 1024,
559 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
560 /* lpSecurityAttrib */ NULL);
562 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
564 ok(CloseHandle(hnp), "CloseHandle\n");
565 hnp = hnpNext;
567 return 0;
570 /** Trivial byte echo server - uses overlapped named pipe calls */
571 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
573 int i;
574 HANDLE hEvent;
576 trace("serverThreadMain3\n");
577 /* Set up a simple echo server */
578 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
579 PIPE_TYPE_BYTE | PIPE_WAIT,
580 /* nMaxInstances */ 1,
581 /* nOutBufSize */ 1024,
582 /* nInBufSize */ 1024,
583 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
584 /* lpSecurityAttrib */ NULL);
585 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
587 hEvent = CreateEventW(NULL, /* security attribute */
588 TRUE, /* manual reset event */
589 FALSE, /* initial state */
590 NULL); /* name */
591 ok(hEvent != NULL, "CreateEvent\n");
593 for (i = 0; i < NB_SERVER_LOOPS; i++) {
594 char buf[512];
595 DWORD written;
596 DWORD readden;
597 DWORD dummy;
598 BOOL success;
599 OVERLAPPED oOverlap;
600 int letWFSOEwait = (i & 2);
601 int letGORwait = (i & 1);
602 DWORD err;
604 memset(&oOverlap, 0, sizeof(oOverlap));
605 oOverlap.hEvent = hEvent;
607 /* Wait for client to connect */
608 if (i == 0) {
609 trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
610 success = ConnectNamedPipe(hnp, NULL);
611 err = GetLastError();
612 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
613 trace("ConnectNamedPipe operation complete.\n");
614 } else {
615 trace("Server calling overlapped ConnectNamedPipe...\n");
616 success = ConnectNamedPipe(hnp, &oOverlap);
617 err = GetLastError();
618 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
619 trace("overlapped ConnectNamedPipe returned.\n");
620 if (!success && (err == ERROR_IO_PENDING)) {
621 if (letWFSOEwait)
623 DWORD ret;
624 do {
625 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
626 } while (ret == WAIT_IO_COMPLETION);
627 ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
629 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
630 if (!letGORwait && !letWFSOEwait && !success) {
631 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
632 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
635 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
636 trace("overlapped ConnectNamedPipe operation complete.\n");
639 /* Echo bytes once */
640 memset(buf, 0, sizeof(buf));
642 trace("Server reading...\n");
643 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
644 trace("Server ReadFile returned...\n");
645 err = GetLastError();
646 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
647 trace("overlapped ReadFile returned.\n");
648 if (!success && (err == ERROR_IO_PENDING)) {
649 if (letWFSOEwait)
651 DWORD ret;
652 do {
653 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
654 } while (ret == WAIT_IO_COMPLETION);
655 ok(ret == 0, "wait ReadFile returned %x\n", ret);
657 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
658 if (!letGORwait && !letWFSOEwait && !success) {
659 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
660 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
663 trace("Server done reading.\n");
664 ok(success, "overlapped ReadFile\n");
666 trace("Server writing...\n");
667 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
668 trace("Server WriteFile returned...\n");
669 err = GetLastError();
670 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
671 trace("overlapped WriteFile returned.\n");
672 if (!success && (err == ERROR_IO_PENDING)) {
673 if (letWFSOEwait)
675 DWORD ret;
676 do {
677 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
678 } while (ret == WAIT_IO_COMPLETION);
679 ok(ret == 0, "wait WriteFile returned %x\n", ret);
681 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
682 if (!letGORwait && !letWFSOEwait && !success) {
683 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
684 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
687 trace("Server done writing.\n");
688 ok(success, "overlapped WriteFile\n");
689 ok(written == readden, "write file len\n");
691 /* finish this connection, wait for next one */
692 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
693 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
695 return 0;
698 /** Trivial byte echo server - uses i/o completion ports */
699 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
701 int i;
702 HANDLE hcompletion;
703 BOOL ret;
705 trace("serverThreadMain4\n");
706 /* Set up a simple echo server */
707 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
708 PIPE_TYPE_BYTE | PIPE_WAIT,
709 /* nMaxInstances */ 1,
710 /* nOutBufSize */ 1024,
711 /* nInBufSize */ 1024,
712 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
713 /* lpSecurityAttrib */ NULL);
714 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
716 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
717 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
719 for (i = 0; i < NB_SERVER_LOOPS; i++) {
720 char buf[512];
721 DWORD written;
722 DWORD readden;
723 DWORD dummy;
724 BOOL success;
725 OVERLAPPED oConnect;
726 OVERLAPPED oRead;
727 OVERLAPPED oWrite;
728 OVERLAPPED *oResult;
729 DWORD err;
730 ULONG_PTR compkey;
732 memset(&oConnect, 0, sizeof(oConnect));
733 memset(&oRead, 0, sizeof(oRead));
734 memset(&oWrite, 0, sizeof(oWrite));
736 /* Wait for client to connect */
737 trace("Server calling overlapped ConnectNamedPipe...\n");
738 success = ConnectNamedPipe(hnp, &oConnect);
739 err = GetLastError();
740 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
741 "overlapped ConnectNamedPipe got %u err %u\n", success, err );
742 if (!success && err == ERROR_IO_PENDING) {
743 trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
744 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
745 if (!success)
747 ok( GetLastError() == WAIT_TIMEOUT,
748 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
749 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
751 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
752 if (success)
754 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
755 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
758 trace("overlapped ConnectNamedPipe operation complete.\n");
760 /* Echo bytes once */
761 memset(buf, 0, sizeof(buf));
763 trace("Server reading...\n");
764 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
765 trace("Server ReadFile returned...\n");
766 err = GetLastError();
767 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
768 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
769 &oResult, 10000);
770 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
771 if (success)
773 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
774 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
776 trace("Server done reading.\n");
778 trace("Server writing...\n");
779 success = WriteFile(hnp, buf, readden, &written, &oWrite);
780 trace("Server WriteFile returned...\n");
781 err = GetLastError();
782 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
783 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
784 &oResult, 10000);
785 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
786 if (success)
788 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
789 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
790 ok(written == readden, "write file len\n");
792 trace("Server done writing.\n");
794 /* finish this connection, wait for next one */
795 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
796 success = DisconnectNamedPipe(hnp);
797 ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
800 ret = CloseHandle(hnp);
801 ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
802 ret = CloseHandle(hcompletion);
803 ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
805 return 0;
808 static int completion_called;
809 static DWORD completion_errorcode;
810 static DWORD completion_num_bytes;
811 static LPOVERLAPPED completion_lpoverlapped;
813 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
815 completion_called++;
816 completion_errorcode = errorcode;
817 completion_num_bytes = num_bytes;
818 completion_lpoverlapped = lpoverlapped;
819 SetEvent(lpoverlapped->hEvent);
822 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
823 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
825 int i;
826 HANDLE hEvent;
828 trace("serverThreadMain5\n");
829 /* Set up a simple echo server */
830 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
831 PIPE_TYPE_BYTE | PIPE_WAIT,
832 /* nMaxInstances */ 1,
833 /* nOutBufSize */ 1024,
834 /* nInBufSize */ 1024,
835 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
836 /* lpSecurityAttrib */ NULL);
837 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
839 hEvent = CreateEventW(NULL, /* security attribute */
840 TRUE, /* manual reset event */
841 FALSE, /* initial state */
842 NULL); /* name */
843 ok(hEvent != NULL, "CreateEvent\n");
845 for (i = 0; i < NB_SERVER_LOOPS; i++) {
846 char buf[512];
847 DWORD readden;
848 BOOL success;
849 OVERLAPPED oOverlap;
850 DWORD err;
852 memset(&oOverlap, 0, sizeof(oOverlap));
853 oOverlap.hEvent = hEvent;
855 /* Wait for client to connect */
856 trace("Server calling ConnectNamedPipe...\n");
857 success = ConnectNamedPipe(hnp, NULL);
858 err = GetLastError();
859 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
860 trace("ConnectNamedPipe operation complete.\n");
862 /* Echo bytes once */
863 memset(buf, 0, sizeof(buf));
865 trace("Server reading...\n");
866 completion_called = 0;
867 ResetEvent(hEvent);
868 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
869 trace("Server ReadFileEx returned...\n");
870 ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
871 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
872 trace("ReadFileEx returned.\n");
873 if (success) {
874 DWORD ret;
875 do {
876 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
877 } while (ret == WAIT_IO_COMPLETION);
878 ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
880 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
881 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
882 ok(completion_num_bytes != 0, "read 0 bytes\n");
883 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
884 readden = completion_num_bytes;
885 trace("Server done reading.\n");
887 trace("Server writing...\n");
888 completion_called = 0;
889 ResetEvent(hEvent);
890 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
891 trace("Server WriteFileEx returned...\n");
892 ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
893 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
894 trace("overlapped WriteFile returned.\n");
895 if (success) {
896 DWORD ret;
897 do {
898 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
899 } while (ret == WAIT_IO_COMPLETION);
900 ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
902 trace("Server done writing.\n");
903 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
904 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
905 ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
906 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
908 /* finish this connection, wait for next one */
909 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
910 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
912 return 0;
915 static void exercizeServer(const char *pipename, HANDLE serverThread)
917 int i;
919 trace("exercizeServer starting\n");
920 for (i = 0; i < NB_SERVER_LOOPS; i++) {
921 HANDLE hFile=INVALID_HANDLE_VALUE;
922 static const char obuf[] = "Bit Bucket";
923 char ibuf[32];
924 DWORD written;
925 DWORD readden;
926 int loop;
928 for (loop = 0; loop < 3; loop++) {
929 DWORD err;
930 trace("Client connecting...\n");
931 /* Connect to the server */
932 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
933 NULL, OPEN_EXISTING, 0, 0);
934 if (hFile != INVALID_HANDLE_VALUE)
935 break;
936 err = GetLastError();
937 if (loop == 0)
938 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
939 else
940 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
941 trace("connect failed, retrying\n");
942 Sleep(200);
944 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
946 /* Make sure it can echo */
947 memset(ibuf, 0, sizeof(ibuf));
948 trace("Client writing...\n");
949 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
950 ok(written == sizeof(obuf), "write file len\n");
951 trace("Client reading...\n");
952 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
953 ok(readden == sizeof(obuf), "read file len\n");
954 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
956 trace("Client closing...\n");
957 ok(CloseHandle(hFile), "CloseHandle\n");
960 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
961 CloseHandle(hnp);
962 trace("exercizeServer returning\n");
965 static void test_NamedPipe_2(void)
967 HANDLE serverThread;
968 DWORD serverThreadId;
969 HANDLE alarmThread;
970 DWORD alarmThreadId;
972 trace("test_NamedPipe_2 starting\n");
973 /* Set up a twenty second timeout */
974 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
975 SetLastError(0xdeadbeef);
976 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
977 ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
979 /* The servers we're about to exercise do try to clean up carefully,
980 * but to reduce the chance of a test failure due to a pipe handle
981 * leak in the test code, we'll use a different pipe name for each server.
984 /* Try server #1 */
985 SetLastError(0xdeadbeef);
986 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
987 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
988 exercizeServer(PIPENAME "serverThreadMain1", serverThread);
990 /* Try server #2 */
991 SetLastError(0xdeadbeef);
992 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
993 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
994 exercizeServer(PIPENAME "serverThreadMain2", serverThread);
996 /* Try server #3 */
997 SetLastError(0xdeadbeef);
998 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
999 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1000 exercizeServer(PIPENAME "serverThreadMain3", serverThread);
1002 /* Try server #4 */
1003 SetLastError(0xdeadbeef);
1004 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1005 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1006 exercizeServer(PIPENAME "serverThreadMain4", serverThread);
1008 /* Try server #5 */
1009 SetLastError(0xdeadbeef);
1010 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1011 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1012 exercizeServer(PIPENAME "serverThreadMain5", serverThread);
1014 ok(SetEvent( alarm_event ), "SetEvent\n");
1015 CloseHandle( alarm_event );
1016 trace("test_NamedPipe_2 returning\n");
1019 static int test_DisconnectNamedPipe(void)
1021 HANDLE hnp;
1022 HANDLE hFile;
1023 static const char obuf[] = "Bit Bucket";
1024 char ibuf[32];
1025 DWORD written;
1026 DWORD readden;
1027 DWORD ret;
1029 SetLastError(0xdeadbeef);
1030 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1031 /* nMaxInstances */ 1,
1032 /* nOutBufSize */ 1024,
1033 /* nInBufSize */ 1024,
1034 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1035 /* lpSecurityAttrib */ NULL);
1036 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1037 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1039 win_skip("Named pipes are not implemented\n");
1040 return 1;
1043 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1044 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1045 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1046 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1048 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1049 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1051 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1052 if (hFile != INVALID_HANDLE_VALUE) {
1054 /* see what happens if server calls DisconnectNamedPipe
1055 * when there are bytes in the pipe
1058 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1059 ok(written == sizeof(obuf), "write file len\n");
1060 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1061 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1062 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1063 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1064 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1065 "ReadFile from disconnected pipe with bytes waiting\n");
1066 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1067 "DisconnectNamedPipe worked twice\n");
1068 ret = WaitForSingleObject(hFile, 0);
1069 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1070 ok(CloseHandle(hFile), "CloseHandle\n");
1073 ok(CloseHandle(hnp), "CloseHandle\n");
1075 return 0;
1077 static void test_CreatePipe(void)
1079 SECURITY_ATTRIBUTES pipe_attr;
1080 HANDLE piperead, pipewrite;
1081 DWORD written;
1082 DWORD read;
1083 DWORD i, size;
1084 BYTE *buffer;
1085 char readbuf[32];
1087 user_apc_ran = FALSE;
1088 if (pQueueUserAPC)
1089 ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1091 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1092 pipe_attr.bInheritHandle = TRUE;
1093 pipe_attr.lpSecurityDescriptor = NULL;
1094 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1095 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1096 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1097 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1098 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1099 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1100 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1102 /* Now write another chunk*/
1103 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1104 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1105 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1106 /* and close the write end, read should still succeed*/
1107 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1108 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe withe with pending data failed\n");
1109 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1110 /* But now we need to get informed that the pipe is closed */
1111 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1112 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1114 /* Try bigger chunks */
1115 size = 32768;
1116 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1117 for (i = 0; i < size; i++) buffer[i] = i;
1118 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1119 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1120 ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1121 /* and close the write end, read should still succeed*/
1122 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1123 memset( buffer, 0, size );
1124 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe withe with pending data failed\n");
1125 ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
1126 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1127 /* But now we need to get informed that the pipe is closed */
1128 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1129 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1130 HeapFree(GetProcessHeap(), 0, buffer);
1132 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1133 SleepEx(0, TRUE); /* get rid of apc */
1136 struct named_pipe_client_params
1138 DWORD security_flags;
1139 HANDLE token;
1140 BOOL revert;
1143 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1145 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1147 struct named_pipe_client_params *params = p;
1148 HANDLE pipe;
1149 BOOL ret;
1150 const char message[] = "Test";
1151 DWORD bytes_read, bytes_written;
1152 char dummy;
1153 TOKEN_PRIVILEGES *Privileges = NULL;
1155 if (params->token)
1157 if (params->revert)
1159 /* modify the token so we can tell if the pipe impersonation
1160 * token reverts to the process token */
1161 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1162 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1164 ret = SetThreadToken(NULL, params->token);
1165 ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1167 else
1169 DWORD Size = 0;
1170 HANDLE process_token;
1172 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1173 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1175 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1176 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1177 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1178 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1179 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1181 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1182 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1184 CloseHandle(process_token);
1187 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1188 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1190 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1191 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1193 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1194 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1196 if (params->token)
1198 if (params->revert)
1200 ret = RevertToSelf();
1201 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1203 else
1205 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1206 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1209 else
1211 HANDLE process_token;
1213 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1214 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1216 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1217 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1219 HeapFree(GetProcessHeap(), 0, Privileges);
1221 CloseHandle(process_token);
1224 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1225 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1227 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1228 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1230 CloseHandle(pipe);
1232 return 0;
1235 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1237 HANDLE ProcessToken;
1238 HANDLE Token = NULL;
1239 BOOL ret;
1241 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1242 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1244 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1245 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1247 CloseHandle(ProcessToken);
1249 return Token;
1252 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1254 HANDLE hPipeServer;
1255 BOOL ret;
1256 DWORD dwTid;
1257 HANDLE hThread;
1258 char buffer[256];
1259 DWORD dwBytesRead;
1260 DWORD error;
1261 struct named_pipe_client_params params;
1262 char dummy = 0;
1263 DWORD dwBytesWritten;
1264 HANDLE hToken = NULL;
1265 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1266 DWORD size;
1268 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1269 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1271 params.security_flags = security_flags;
1272 params.token = hClientToken;
1273 params.revert = revert;
1274 hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1275 ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1277 SetLastError(0xdeadbeef);
1278 ret = ImpersonateNamedPipeClient(hPipeServer);
1279 error = GetLastError();
1280 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1281 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1283 ret = ConnectNamedPipe(hPipeServer, NULL);
1284 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1286 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1287 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1289 ret = ImpersonateNamedPipeClient(hPipeServer);
1290 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1292 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1293 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1295 (*test_func)(0, hToken);
1297 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1298 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1299 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1300 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1302 CloseHandle(hToken);
1304 RevertToSelf();
1306 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1307 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1309 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1310 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1312 ret = ImpersonateNamedPipeClient(hPipeServer);
1313 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1315 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1316 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1318 (*test_func)(1, hToken);
1320 CloseHandle(hToken);
1322 RevertToSelf();
1324 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1325 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1327 WaitForSingleObject(hThread, INFINITE);
1329 ret = ImpersonateNamedPipeClient(hPipeServer);
1330 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1332 RevertToSelf();
1334 CloseHandle(hThread);
1335 CloseHandle(hPipeServer);
1338 static BOOL are_all_privileges_disabled(HANDLE hToken)
1340 BOOL ret;
1341 TOKEN_PRIVILEGES *Privileges = NULL;
1342 DWORD Size = 0;
1343 BOOL all_privs_disabled = TRUE;
1344 DWORD i;
1346 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1347 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1349 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1350 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1351 if (!ret)
1353 HeapFree(GetProcessHeap(), 0, Privileges);
1354 return FALSE;
1357 else
1358 return FALSE;
1360 for (i = 0; i < Privileges->PrivilegeCount; i++)
1362 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
1364 all_privs_disabled = FALSE;
1365 break;
1369 HeapFree(GetProcessHeap(), 0, Privileges);
1371 return all_privs_disabled;
1374 static DWORD get_privilege_count(HANDLE hToken)
1376 TOKEN_STATISTICS Statistics;
1377 DWORD Size = sizeof(Statistics);
1378 BOOL ret;
1380 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
1381 ok(ret, "GetTokenInformation(TokenStatistics)\n");
1382 if (!ret) return -1;
1384 return Statistics.PrivilegeCount;
1387 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
1389 DWORD priv_count;
1391 switch (call_index)
1393 case 0:
1394 priv_count = get_privilege_count(hToken);
1395 todo_wine
1396 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1397 break;
1398 case 1:
1399 priv_count = get_privilege_count(hToken);
1400 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1401 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1402 break;
1403 default:
1404 ok(0, "shouldn't happen\n");
1408 static void test_no_sqos(int call_index, HANDLE hToken)
1410 switch (call_index)
1412 case 0:
1413 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1414 break;
1415 case 1:
1416 todo_wine
1417 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1418 break;
1419 default:
1420 ok(0, "shouldn't happen\n");
1424 static void test_static_context(int call_index, HANDLE hToken)
1426 switch (call_index)
1428 case 0:
1429 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1430 break;
1431 case 1:
1432 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1433 break;
1434 default:
1435 ok(0, "shouldn't happen\n");
1439 static void test_dynamic_context(int call_index, HANDLE hToken)
1441 switch (call_index)
1443 case 0:
1444 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1445 break;
1446 case 1:
1447 todo_wine
1448 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1449 break;
1450 default:
1451 ok(0, "shouldn't happen\n");
1455 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
1457 switch (call_index)
1459 case 0:
1460 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1461 break;
1462 case 1:
1463 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
1464 break;
1465 default:
1466 ok(0, "shouldn't happen\n");
1470 static void test_no_sqos_revert(int call_index, HANDLE hToken)
1472 DWORD priv_count;
1473 switch (call_index)
1475 case 0:
1476 priv_count = get_privilege_count(hToken);
1477 todo_wine
1478 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1479 break;
1480 case 1:
1481 priv_count = get_privilege_count(hToken);
1482 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1483 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1484 break;
1485 default:
1486 ok(0, "shouldn't happen\n");
1490 static void test_static_context_revert(int call_index, HANDLE hToken)
1492 switch (call_index)
1494 case 0:
1495 todo_wine
1496 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1497 break;
1498 case 1:
1499 todo_wine
1500 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1501 break;
1502 default:
1503 ok(0, "shouldn't happen\n");
1507 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
1509 switch (call_index)
1511 case 0:
1512 todo_wine
1513 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1514 break;
1515 case 1:
1516 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
1517 break;
1518 default:
1519 ok(0, "shouldn't happen\n");
1523 static void test_impersonation(void)
1525 HANDLE hClientToken;
1526 HANDLE hProcessToken;
1527 BOOL ret;
1529 if( !pDuplicateTokenEx ) {
1530 skip("DuplicateTokenEx not found\n");
1531 return;
1534 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
1535 if (!ret)
1537 skip("couldn't open process token, skipping impersonation tests\n");
1538 return;
1541 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
1543 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
1544 CloseHandle(hProcessToken);
1545 return;
1547 CloseHandle(hProcessToken);
1549 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
1550 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1551 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
1552 CloseHandle(hClientToken);
1553 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1554 test_ImpersonateNamedPipeClient(hClientToken,
1555 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
1556 test_static_context);
1557 CloseHandle(hClientToken);
1558 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1559 test_ImpersonateNamedPipeClient(hClientToken,
1560 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1561 FALSE, test_dynamic_context);
1562 CloseHandle(hClientToken);
1563 test_ImpersonateNamedPipeClient(NULL,
1564 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1565 FALSE, test_dynamic_context_no_token);
1567 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1568 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
1569 CloseHandle(hClientToken);
1570 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1571 test_ImpersonateNamedPipeClient(hClientToken,
1572 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
1573 test_static_context_revert);
1574 CloseHandle(hClientToken);
1575 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1576 test_ImpersonateNamedPipeClient(hClientToken,
1577 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1578 TRUE, test_dynamic_context_revert);
1579 CloseHandle(hClientToken);
1582 struct overlapped_server_args
1584 HANDLE pipe_created;
1587 static DWORD CALLBACK overlapped_server(LPVOID arg)
1589 OVERLAPPED ol;
1590 HANDLE pipe;
1591 int ret, err;
1592 struct overlapped_server_args *a = arg;
1593 DWORD num;
1594 char buf[100];
1596 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
1597 ok(pipe != NULL, "pipe NULL\n");
1599 ol.hEvent = CreateEventA(0, 1, 0, 0);
1600 ok(ol.hEvent != NULL, "event NULL\n");
1601 ret = ConnectNamedPipe(pipe, &ol);
1602 err = GetLastError();
1603 ok(ret == 0, "ret %d\n", ret);
1604 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
1605 SetEvent(a->pipe_created);
1607 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
1608 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
1610 ret = GetOverlappedResult(pipe, &ol, &num, 1);
1611 ok(ret == 1, "ret %d\n", ret);
1613 /* This should block */
1614 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
1615 ok(ret == 1, "ret %d\n", ret);
1617 DisconnectNamedPipe(pipe);
1618 CloseHandle(ol.hEvent);
1619 CloseHandle(pipe);
1620 return 1;
1623 static void test_overlapped(void)
1625 DWORD tid, num;
1626 HANDLE thread, pipe;
1627 BOOL ret;
1628 struct overlapped_server_args args;
1630 args.pipe_created = CreateEventA(0, 1, 0, 0);
1631 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
1633 WaitForSingleObject(args.pipe_created, INFINITE);
1634 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1635 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
1637 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
1638 Sleep(1);
1640 ret = WriteFile(pipe, "x", 1, &num, NULL);
1641 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1643 WaitForSingleObject(thread, INFINITE);
1644 CloseHandle(pipe);
1645 CloseHandle(args.pipe_created);
1646 CloseHandle(thread);
1649 static void test_NamedPipeHandleState(void)
1651 HANDLE server, client;
1652 BOOL ret;
1653 DWORD state, instances, maxCollectionCount, collectDataTimeout;
1654 char userName[MAX_PATH];
1656 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1657 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1658 /* nMaxInstances */ 1,
1659 /* nOutBufSize */ 1024,
1660 /* nInBufSize */ 1024,
1661 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1662 /* lpSecurityAttrib */ NULL);
1663 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1664 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
1665 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1666 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
1668 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1669 if (ret)
1671 ok(state == 0, "unexpected state %08x\n", state);
1672 ok(instances == 1, "expected 1 instances, got %d\n", instances);
1674 /* Some parameters have no meaning, and therefore can't be retrieved,
1675 * on a local pipe.
1677 SetLastError(0xdeadbeef);
1678 ret = GetNamedPipeHandleStateA(server, &state, &instances,
1679 &maxCollectionCount, &collectDataTimeout, userName,
1680 sizeof(userName) / sizeof(userName[0]));
1681 todo_wine
1682 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1683 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1684 /* A byte-mode pipe server can't be changed to message mode. */
1685 state = PIPE_READMODE_MESSAGE;
1686 SetLastError(0xdeadbeef);
1687 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1688 todo_wine
1689 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1690 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1692 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1693 OPEN_EXISTING, 0, NULL);
1694 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1696 state = PIPE_READMODE_BYTE;
1697 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1698 todo_wine
1699 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1700 /* A byte-mode pipe client can't be changed to message mode, either. */
1701 state = PIPE_READMODE_MESSAGE;
1702 SetLastError(0xdeadbeef);
1703 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1704 todo_wine
1705 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1706 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1708 CloseHandle(client);
1709 CloseHandle(server);
1711 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1712 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
1713 /* nMaxInstances */ 1,
1714 /* nOutBufSize */ 1024,
1715 /* nInBufSize */ 1024,
1716 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1717 /* lpSecurityAttrib */ NULL);
1718 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1719 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
1720 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1721 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
1723 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1724 if (ret)
1726 ok(state == 0, "unexpected state %08x\n", state);
1727 ok(instances == 1, "expected 1 instances, got %d\n", instances);
1729 /* In contrast to byte-mode pipes, a message-mode pipe server can be
1730 * changed to byte mode.
1732 state = PIPE_READMODE_BYTE;
1733 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1734 todo_wine
1735 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1737 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1738 OPEN_EXISTING, 0, NULL);
1739 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1741 state = PIPE_READMODE_MESSAGE;
1742 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1743 todo_wine
1744 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1745 /* A message-mode pipe client can also be changed to byte mode.
1747 state = PIPE_READMODE_BYTE;
1748 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1749 todo_wine
1750 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1752 CloseHandle(client);
1753 CloseHandle(server);
1756 static void test_readfileex_pending(void)
1758 HANDLE server, client, event;
1759 BOOL ret;
1760 DWORD err, wait, num_bytes;
1761 OVERLAPPED overlapped;
1762 char read_buf[1024];
1763 char write_buf[1024];
1764 const char test_string[] = "test";
1765 int i;
1767 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
1768 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1769 /* nMaxInstances */ 1,
1770 /* nOutBufSize */ 1024,
1771 /* nInBufSize */ 1024,
1772 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1773 /* lpSecurityAttrib */ NULL);
1774 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1776 event = CreateEventA(NULL, TRUE, FALSE, NULL);
1777 ok(event != NULL, "CreateEventA failed\n");
1779 memset(&overlapped, 0, sizeof(overlapped));
1780 overlapped.hEvent = event;
1782 ret = ConnectNamedPipe(server, &overlapped);
1783 err = GetLastError();
1784 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
1785 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
1787 wait = WaitForSingleObject(event, 0);
1788 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
1790 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1791 OPEN_EXISTING, 0, NULL);
1792 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1794 wait = WaitForSingleObject(event, 0);
1795 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1797 /* Start a read that can't complete immediately. */
1798 completion_called = 0;
1799 ResetEvent(event);
1800 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
1801 ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
1802 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
1804 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
1805 ok(ret == TRUE, "WriteFile failed\n");
1806 ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
1808 ok(completion_called == 0, "completion routine called during WriteFile\n");
1810 wait = WaitForSingleObjectEx(event, 0, TRUE);
1811 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
1813 ok(completion_called == 1, "completion not called after writing pipe\n");
1814 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1815 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
1816 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1817 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
1819 /* Make writes until the pipe is full and the write fails */
1820 memset(write_buf, 0xaa, sizeof(write_buf));
1821 for (i=0; i<256; i++)
1823 completion_called = 0;
1824 ResetEvent(event);
1825 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
1826 err = GetLastError();
1828 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
1830 wait = WaitForSingleObjectEx(event, 0, TRUE);
1832 if (wait == WAIT_TIMEOUT)
1833 /* write couldn't complete immediately, presumably the pipe is full */
1834 break;
1836 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1838 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
1839 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1840 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1843 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
1844 ok(completion_called == 0, "completion routine called but wait timed out\n");
1845 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1846 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1848 /* free up some space in the pipe */
1849 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
1850 ok(ret == TRUE, "ReadFile failed\n");
1852 ok(completion_called == 0, "completion routine called during ReadFile\n");
1854 wait = WaitForSingleObjectEx(event, 0, TRUE);
1855 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1857 ok(completion_called == 1, "completion routine not called\n");
1858 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1859 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1861 num_bytes = 0xdeadbeef;
1862 SetLastError(0xdeadbeef);
1863 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
1864 ok(!ret, "ReadFile should fail\n");
1865 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
1866 ok(num_bytes == 0, "expected 0, got %u\n", num_bytes);
1868 S(U(overlapped)).Offset = 0;
1869 S(U(overlapped)).OffsetHigh = 0;
1870 overlapped.Internal = -1;
1871 overlapped.InternalHigh = -1;
1872 overlapped.hEvent = event;
1873 num_bytes = 0xdeadbeef;
1874 SetLastError(0xdeadbeef);
1875 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
1876 todo_wine
1877 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
1878 ok(num_bytes == 0, "bytes %u\n", num_bytes);
1879 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
1880 todo_wine
1881 ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
1883 wait = WaitForSingleObject(event, 100);
1884 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
1886 num_bytes = 0xdeadbeef;
1887 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
1888 ok(ret, "WriteFile failed\n");
1889 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1891 wait = WaitForSingleObject(event, 100);
1892 todo_wine
1893 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1895 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1896 todo_wine
1897 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
1898 ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
1900 /* read the pending byte and clear the pipe */
1901 num_bytes = 0xdeadbeef;
1902 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
1903 ok(ret, "ReadFile failed\n");
1904 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1906 CloseHandle(client);
1907 CloseHandle(server);
1908 CloseHandle(event);
1911 START_TEST(pipe)
1913 HMODULE hmod;
1915 hmod = GetModuleHandleA("advapi32.dll");
1916 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
1917 hmod = GetModuleHandleA("kernel32.dll");
1918 pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
1920 if (test_DisconnectNamedPipe())
1921 return;
1922 test_CreateNamedPipe_instances_must_match();
1923 test_NamedPipe_2();
1924 test_CreateNamedPipe(PIPE_TYPE_BYTE);
1925 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
1926 test_CreatePipe();
1927 test_impersonation();
1928 test_overlapped();
1929 test_NamedPipeHandleState();
1930 test_readfileex_pending();