kernel32/tests: Add tests for partially received pipe messages after calling SetNamed...
[wine/wine-gecko.git] / dlls / kernel32 / tests / pipe.c
blobeeeaa32fc7a5b06e2de1f9db7cd140f3474c21ef
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\n");
131 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
132 ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
133 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
135 memset(ibuf, 0, sizeof(ibuf));
136 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
137 ok(written == sizeof(obuf2), "write file len\n");
138 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
139 ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
140 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
142 /* Now the same again, but with an additional call to PeekNamedPipe */
143 memset(ibuf, 0, sizeof(ibuf));
144 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
145 ok(written == sizeof(obuf), "write file len 1\n");
146 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
147 ok(readden == sizeof(obuf), "peek 1 got %d bytes\n", readden);
148 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
149 ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
150 ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
152 memset(ibuf, 0, sizeof(ibuf));
153 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
154 ok(written == sizeof(obuf2), "write file len 2\n");
155 ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
156 ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
157 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &readden, NULL), "Peek\n");
158 ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
159 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
160 ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
161 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
163 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
164 memset(ibuf, 0, sizeof(ibuf));
165 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
166 ok(written == sizeof(obuf2), "write file len\n");
167 ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
168 ok(readden == 4, "read got %d bytes\n", readden);
169 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
170 ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
171 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
173 memset(ibuf, 0, sizeof(ibuf));
174 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
175 ok(written == sizeof(obuf), "write file len\n");
176 if (pipemode == PIPE_TYPE_BYTE)
178 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
180 else
182 SetLastError(0xdeadbeef);
183 todo_wine
184 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
185 todo_wine
186 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
188 ok(readden == 4, "read got %d bytes\n", readden);
189 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
190 ok(readden == sizeof(obuf) - 4, "read got %d bytes\n", readden);
191 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
193 /* Similar to above, but use a read buffer size small enough to read in three parts */
194 memset(ibuf, 0, sizeof(ibuf));
195 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
196 ok(written == sizeof(obuf2), "write file len\n");
197 if (pipemode == PIPE_TYPE_BYTE)
199 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
200 ok(readden == 4, "read got %d bytes\n", readden);
201 ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
203 else
205 SetLastError(0xdeadbeef);
206 todo_wine
207 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
208 todo_wine
209 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
210 ok(readden == 4, "read got %d bytes\n", readden);
211 SetLastError(0xdeadbeef);
212 todo_wine
213 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
214 todo_wine
215 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
217 ok(readden == 4, "read got %d bytes\n", readden);
218 ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n");
219 ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden);
220 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
222 /* Test reading of multiple writes */
223 memset(ibuf, 0, sizeof(ibuf));
224 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
225 ok(written == sizeof(obuf), "write file len 3a\n");
226 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
227 ok(written == sizeof(obuf2), "write file len 3b\n");
228 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
229 if (pipemode == PIPE_TYPE_BYTE) {
230 todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
232 else
234 ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
236 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
237 pbuf = ibuf;
238 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
239 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
240 pbuf += sizeof(obuf);
241 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
243 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
244 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
245 pbuf = ibuf;
246 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
247 pbuf += sizeof(obuf);
248 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
250 /* Multiple writes in the reverse direction */
251 memset(ibuf, 0, sizeof(ibuf));
252 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
253 ok(written == sizeof(obuf), "write file len 4a\n");
254 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
255 ok(written == sizeof(obuf2), "write file len 4b\n");
256 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
257 if (pipemode == PIPE_TYPE_BYTE) {
258 todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
260 else
262 ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
264 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
265 pbuf = ibuf;
266 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
267 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
268 pbuf += sizeof(obuf);
269 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
271 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
272 if (pipemode == PIPE_TYPE_BYTE) {
273 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
275 else {
276 todo_wine {
277 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
280 pbuf = ibuf;
281 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
282 if (pipemode == PIPE_TYPE_BYTE) {
283 pbuf += sizeof(obuf);
284 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
287 /* Test reading of multiple writes after a mode change
288 (CreateFile always creates a byte mode pipe) */
289 lpmode = PIPE_READMODE_MESSAGE;
290 if (pipemode == PIPE_TYPE_BYTE) {
291 /* trying to change the client end of a byte pipe to message mode should fail */
292 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
294 else {
295 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
297 memset(ibuf, 0, sizeof(ibuf));
298 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
299 ok(written == sizeof(obuf), "write file len 3a\n");
300 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
301 ok(written == sizeof(obuf2), "write file len 3b\n");
302 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
303 ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
304 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
305 pbuf = ibuf;
306 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
307 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
308 todo_wine {
309 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
311 pbuf = ibuf;
312 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
313 if (readden <= sizeof(obuf))
314 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
316 /* Multiple writes in the reverse direction */
317 /* the write of obuf2 from write4 should still be in the buffer */
318 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
319 todo_wine {
320 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
321 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
323 if (avail > 0) {
324 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
325 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
326 pbuf = ibuf;
327 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
329 memset(ibuf, 0, sizeof(ibuf));
330 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
331 ok(written == sizeof(obuf), "write file len 6a\n");
332 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
333 ok(written == sizeof(obuf2), "write file len 6b\n");
334 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
335 ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
336 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
337 pbuf = ibuf;
338 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
339 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
340 todo_wine {
341 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
343 pbuf = ibuf;
344 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
345 if (readden <= sizeof(obuf))
346 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
348 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
349 memset(ibuf, 0, sizeof(ibuf));
350 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
351 ok(written == sizeof(obuf2), "write file len 7\n");
352 SetLastError(0xdeadbeef);
353 todo_wine
354 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
355 todo_wine
356 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
357 ok(readden == 4, "read got %d bytes 7\n", readden);
358 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
359 ok(readden == sizeof(obuf2) - 4, "read got %d bytes 7\n", readden);
360 ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n");
362 memset(ibuf, 0, sizeof(ibuf));
363 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
364 ok(written == sizeof(obuf), "write file len 8\n");
365 SetLastError(0xdeadbeef);
366 todo_wine
367 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
368 todo_wine
369 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
370 ok(readden == 4, "read got %d bytes 8\n", readden);
371 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
372 ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden);
373 ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
377 /* Picky conformance tests */
379 /* Verify that you can't connect to pipe again
380 * until server calls DisconnectNamedPipe+ConnectNamedPipe
381 * or creates a new pipe
382 * case 1: other client not yet closed
384 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
385 ok(hFile2 == INVALID_HANDLE_VALUE,
386 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
387 ok(GetLastError() == ERROR_PIPE_BUSY,
388 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
390 ok(CloseHandle(hFile), "CloseHandle\n");
392 /* case 2: other client already closed */
393 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
394 ok(hFile == INVALID_HANDLE_VALUE,
395 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
396 ok(GetLastError() == ERROR_PIPE_BUSY,
397 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
399 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
401 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
402 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
403 ok(hFile == INVALID_HANDLE_VALUE,
404 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
405 ok(GetLastError() == ERROR_PIPE_BUSY,
406 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
408 /* to be complete, we'd call ConnectNamedPipe here and loop,
409 * but by default that's blocking, so we'd either have
410 * to turn on the uncommon nonblocking mode, or
411 * use another thread.
415 ok(CloseHandle(hnp), "CloseHandle\n");
417 trace("test_CreateNamedPipe returning\n");
420 static void test_CreateNamedPipe_instances_must_match(void)
422 HANDLE hnp, hnp2;
424 /* Check no mismatch */
425 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
426 /* nMaxInstances */ 2,
427 /* nOutBufSize */ 1024,
428 /* nInBufSize */ 1024,
429 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
430 /* lpSecurityAttrib */ NULL);
431 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
433 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
434 /* nMaxInstances */ 2,
435 /* nOutBufSize */ 1024,
436 /* nInBufSize */ 1024,
437 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
438 /* lpSecurityAttrib */ NULL);
439 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
441 ok(CloseHandle(hnp), "CloseHandle\n");
442 ok(CloseHandle(hnp2), "CloseHandle\n");
444 /* Check nMaxInstances */
445 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
446 /* nMaxInstances */ 1,
447 /* nOutBufSize */ 1024,
448 /* nInBufSize */ 1024,
449 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
450 /* lpSecurityAttrib */ NULL);
451 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
453 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
454 /* nMaxInstances */ 1,
455 /* nOutBufSize */ 1024,
456 /* nInBufSize */ 1024,
457 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
458 /* lpSecurityAttrib */ NULL);
459 ok(hnp2 == INVALID_HANDLE_VALUE
460 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
462 ok(CloseHandle(hnp), "CloseHandle\n");
464 /* Check PIPE_ACCESS_* */
465 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
466 /* nMaxInstances */ 2,
467 /* nOutBufSize */ 1024,
468 /* nInBufSize */ 1024,
469 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
470 /* lpSecurityAttrib */ NULL);
471 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
473 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
474 /* nMaxInstances */ 2,
475 /* nOutBufSize */ 1024,
476 /* nInBufSize */ 1024,
477 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
478 /* lpSecurityAttrib */ NULL);
479 ok(hnp2 == INVALID_HANDLE_VALUE
480 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
482 ok(CloseHandle(hnp), "CloseHandle\n");
484 /* check everything else */
485 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
486 /* nMaxInstances */ 4,
487 /* nOutBufSize */ 1024,
488 /* nInBufSize */ 1024,
489 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
490 /* lpSecurityAttrib */ NULL);
491 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
493 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
494 /* nMaxInstances */ 3,
495 /* nOutBufSize */ 102,
496 /* nInBufSize */ 24,
497 /* nDefaultWait */ 1234,
498 /* lpSecurityAttrib */ NULL);
499 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
501 ok(CloseHandle(hnp), "CloseHandle\n");
502 ok(CloseHandle(hnp2), "CloseHandle\n");
505 /** implementation of alarm() */
506 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
508 DWORD_PTR timeout = (DWORD_PTR) arg;
509 trace("alarmThreadMain\n");
510 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
512 ok(FALSE, "alarm\n");
513 ExitProcess(1);
515 return 1;
518 static HANDLE hnp = INVALID_HANDLE_VALUE;
520 /** Trivial byte echo server - disconnects after each session */
521 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
523 int i;
525 trace("serverThreadMain1 start\n");
526 /* Set up a simple echo server */
527 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
528 PIPE_TYPE_BYTE | PIPE_WAIT,
529 /* nMaxInstances */ 1,
530 /* nOutBufSize */ 1024,
531 /* nInBufSize */ 1024,
532 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
533 /* lpSecurityAttrib */ NULL);
535 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
536 for (i = 0; i < NB_SERVER_LOOPS; i++) {
537 char buf[512];
538 DWORD written;
539 DWORD readden;
540 BOOL success;
542 /* Wait for client to connect */
543 trace("Server calling ConnectNamedPipe...\n");
544 ok(ConnectNamedPipe(hnp, NULL)
545 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
546 trace("ConnectNamedPipe returned.\n");
548 /* Echo bytes once */
549 memset(buf, 0, sizeof(buf));
551 trace("Server reading...\n");
552 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
553 trace("Server done reading.\n");
554 ok(success, "ReadFile\n");
555 ok(readden, "short read\n");
557 trace("Server writing...\n");
558 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
559 trace("Server done writing.\n");
560 ok(written == readden, "write file len\n");
562 /* finish this connection, wait for next one */
563 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
564 trace("Server done flushing.\n");
565 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
566 trace("Server done disconnecting.\n");
568 return 0;
571 /** Trivial byte echo server - closes after each connection */
572 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
574 int i;
575 HANDLE hnpNext = 0;
577 trace("serverThreadMain2\n");
578 /* Set up a simple echo server */
579 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
580 PIPE_TYPE_BYTE | PIPE_WAIT,
581 /* nMaxInstances */ 2,
582 /* nOutBufSize */ 1024,
583 /* nInBufSize */ 1024,
584 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
585 /* lpSecurityAttrib */ NULL);
586 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
588 for (i = 0; i < NB_SERVER_LOOPS; i++) {
589 char buf[512];
590 DWORD written;
591 DWORD readden;
592 DWORD ret;
593 BOOL success;
596 user_apc_ran = FALSE;
597 if (i == 0 && pQueueUserAPC) {
598 trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
599 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
600 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
603 /* Wait for client to connect */
604 trace("Server calling ConnectNamedPipe...\n");
605 ok(ConnectNamedPipe(hnp, NULL)
606 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
607 trace("ConnectNamedPipe returned.\n");
609 /* Echo bytes once */
610 memset(buf, 0, sizeof(buf));
612 trace("Server reading...\n");
613 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
614 trace("Server done reading.\n");
615 ok(success, "ReadFile\n");
617 trace("Server writing...\n");
618 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
619 trace("Server done writing.\n");
620 ok(written == readden, "write file len\n");
622 /* finish this connection, wait for next one */
623 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
624 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
626 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
628 if (i == 0 && pQueueUserAPC)
629 SleepEx(0, TRUE); /* get rid of apc */
631 /* Set up next echo server */
632 hnpNext =
633 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
634 PIPE_TYPE_BYTE | PIPE_WAIT,
635 /* nMaxInstances */ 2,
636 /* nOutBufSize */ 1024,
637 /* nInBufSize */ 1024,
638 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
639 /* lpSecurityAttrib */ NULL);
641 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
643 ok(CloseHandle(hnp), "CloseHandle\n");
644 hnp = hnpNext;
646 return 0;
649 /** Trivial byte echo server - uses overlapped named pipe calls */
650 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
652 int i;
653 HANDLE hEvent;
655 trace("serverThreadMain3\n");
656 /* Set up a simple echo server */
657 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
658 PIPE_TYPE_BYTE | PIPE_WAIT,
659 /* nMaxInstances */ 1,
660 /* nOutBufSize */ 1024,
661 /* nInBufSize */ 1024,
662 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
663 /* lpSecurityAttrib */ NULL);
664 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
666 hEvent = CreateEventW(NULL, /* security attribute */
667 TRUE, /* manual reset event */
668 FALSE, /* initial state */
669 NULL); /* name */
670 ok(hEvent != NULL, "CreateEvent\n");
672 for (i = 0; i < NB_SERVER_LOOPS; i++) {
673 char buf[512];
674 DWORD written;
675 DWORD readden;
676 DWORD dummy;
677 BOOL success;
678 OVERLAPPED oOverlap;
679 int letWFSOEwait = (i & 2);
680 int letGORwait = (i & 1);
681 DWORD err;
683 memset(&oOverlap, 0, sizeof(oOverlap));
684 oOverlap.hEvent = hEvent;
686 /* Wait for client to connect */
687 if (i == 0) {
688 trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
689 success = ConnectNamedPipe(hnp, NULL);
690 err = GetLastError();
691 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
692 trace("ConnectNamedPipe operation complete.\n");
693 } else {
694 trace("Server calling overlapped ConnectNamedPipe...\n");
695 success = ConnectNamedPipe(hnp, &oOverlap);
696 err = GetLastError();
697 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
698 trace("overlapped ConnectNamedPipe returned.\n");
699 if (!success && (err == ERROR_IO_PENDING)) {
700 if (letWFSOEwait)
702 DWORD ret;
703 do {
704 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
705 } while (ret == WAIT_IO_COMPLETION);
706 ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
708 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
709 if (!letGORwait && !letWFSOEwait && !success) {
710 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
711 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
714 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
715 trace("overlapped ConnectNamedPipe operation complete.\n");
718 /* Echo bytes once */
719 memset(buf, 0, sizeof(buf));
721 trace("Server reading...\n");
722 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
723 trace("Server ReadFile returned...\n");
724 err = GetLastError();
725 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
726 trace("overlapped ReadFile returned.\n");
727 if (!success && (err == ERROR_IO_PENDING)) {
728 if (letWFSOEwait)
730 DWORD ret;
731 do {
732 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
733 } while (ret == WAIT_IO_COMPLETION);
734 ok(ret == 0, "wait ReadFile returned %x\n", ret);
736 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
737 if (!letGORwait && !letWFSOEwait && !success) {
738 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
739 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
742 trace("Server done reading.\n");
743 ok(success, "overlapped ReadFile\n");
745 trace("Server writing...\n");
746 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
747 trace("Server WriteFile returned...\n");
748 err = GetLastError();
749 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
750 trace("overlapped WriteFile returned.\n");
751 if (!success && (err == ERROR_IO_PENDING)) {
752 if (letWFSOEwait)
754 DWORD ret;
755 do {
756 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
757 } while (ret == WAIT_IO_COMPLETION);
758 ok(ret == 0, "wait WriteFile returned %x\n", ret);
760 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
761 if (!letGORwait && !letWFSOEwait && !success) {
762 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
763 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
766 trace("Server done writing.\n");
767 ok(success, "overlapped WriteFile\n");
768 ok(written == readden, "write file len\n");
770 /* finish this connection, wait for next one */
771 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
772 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
774 return 0;
777 /** Trivial byte echo server - uses i/o completion ports */
778 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
780 int i;
781 HANDLE hcompletion;
782 BOOL ret;
784 trace("serverThreadMain4\n");
785 /* Set up a simple echo server */
786 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
787 PIPE_TYPE_BYTE | PIPE_WAIT,
788 /* nMaxInstances */ 1,
789 /* nOutBufSize */ 1024,
790 /* nInBufSize */ 1024,
791 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
792 /* lpSecurityAttrib */ NULL);
793 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
795 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
796 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
798 for (i = 0; i < NB_SERVER_LOOPS; i++) {
799 char buf[512];
800 DWORD written;
801 DWORD readden;
802 DWORD dummy;
803 BOOL success;
804 OVERLAPPED oConnect;
805 OVERLAPPED oRead;
806 OVERLAPPED oWrite;
807 OVERLAPPED *oResult;
808 DWORD err;
809 ULONG_PTR compkey;
811 memset(&oConnect, 0, sizeof(oConnect));
812 memset(&oRead, 0, sizeof(oRead));
813 memset(&oWrite, 0, sizeof(oWrite));
815 /* Wait for client to connect */
816 trace("Server calling overlapped ConnectNamedPipe...\n");
817 success = ConnectNamedPipe(hnp, &oConnect);
818 err = GetLastError();
819 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
820 "overlapped ConnectNamedPipe got %u err %u\n", success, err );
821 if (!success && err == ERROR_IO_PENDING) {
822 trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
823 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
824 if (!success)
826 ok( GetLastError() == WAIT_TIMEOUT,
827 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
828 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
830 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
831 if (success)
833 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
834 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
837 trace("overlapped ConnectNamedPipe operation complete.\n");
839 /* Echo bytes once */
840 memset(buf, 0, sizeof(buf));
842 trace("Server reading...\n");
843 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
844 trace("Server ReadFile returned...\n");
845 err = GetLastError();
846 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
847 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
848 &oResult, 10000);
849 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
850 if (success)
852 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
853 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
855 trace("Server done reading.\n");
857 trace("Server writing...\n");
858 success = WriteFile(hnp, buf, readden, &written, &oWrite);
859 trace("Server WriteFile returned...\n");
860 err = GetLastError();
861 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
862 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
863 &oResult, 10000);
864 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
865 if (success)
867 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
868 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
869 ok(written == readden, "write file len\n");
871 trace("Server done writing.\n");
873 /* finish this connection, wait for next one */
874 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
875 success = DisconnectNamedPipe(hnp);
876 ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
879 ret = CloseHandle(hnp);
880 ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
881 ret = CloseHandle(hcompletion);
882 ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
884 return 0;
887 static int completion_called;
888 static DWORD completion_errorcode;
889 static DWORD completion_num_bytes;
890 static LPOVERLAPPED completion_lpoverlapped;
892 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
894 completion_called++;
895 completion_errorcode = errorcode;
896 completion_num_bytes = num_bytes;
897 completion_lpoverlapped = lpoverlapped;
898 SetEvent(lpoverlapped->hEvent);
901 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
902 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
904 int i;
905 HANDLE hEvent;
907 trace("serverThreadMain5\n");
908 /* Set up a simple echo server */
909 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
910 PIPE_TYPE_BYTE | PIPE_WAIT,
911 /* nMaxInstances */ 1,
912 /* nOutBufSize */ 1024,
913 /* nInBufSize */ 1024,
914 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
915 /* lpSecurityAttrib */ NULL);
916 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
918 hEvent = CreateEventW(NULL, /* security attribute */
919 TRUE, /* manual reset event */
920 FALSE, /* initial state */
921 NULL); /* name */
922 ok(hEvent != NULL, "CreateEvent\n");
924 for (i = 0; i < NB_SERVER_LOOPS; i++) {
925 char buf[512];
926 DWORD readden;
927 BOOL success;
928 OVERLAPPED oOverlap;
929 DWORD err;
931 memset(&oOverlap, 0, sizeof(oOverlap));
932 oOverlap.hEvent = hEvent;
934 /* Wait for client to connect */
935 trace("Server calling ConnectNamedPipe...\n");
936 success = ConnectNamedPipe(hnp, NULL);
937 err = GetLastError();
938 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
939 trace("ConnectNamedPipe operation complete.\n");
941 /* Echo bytes once */
942 memset(buf, 0, sizeof(buf));
944 trace("Server reading...\n");
945 completion_called = 0;
946 ResetEvent(hEvent);
947 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
948 trace("Server ReadFileEx returned...\n");
949 ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
950 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
951 trace("ReadFileEx returned.\n");
952 if (success) {
953 DWORD ret;
954 do {
955 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
956 } while (ret == WAIT_IO_COMPLETION);
957 ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
959 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
960 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
961 ok(completion_num_bytes != 0, "read 0 bytes\n");
962 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
963 readden = completion_num_bytes;
964 trace("Server done reading.\n");
966 trace("Server writing...\n");
967 completion_called = 0;
968 ResetEvent(hEvent);
969 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
970 trace("Server WriteFileEx returned...\n");
971 ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
972 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
973 trace("overlapped WriteFile returned.\n");
974 if (success) {
975 DWORD ret;
976 do {
977 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
978 } while (ret == WAIT_IO_COMPLETION);
979 ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
981 trace("Server done writing.\n");
982 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
983 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
984 ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
985 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
987 /* finish this connection, wait for next one */
988 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
989 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
991 return 0;
994 static void exercizeServer(const char *pipename, HANDLE serverThread)
996 int i;
998 trace("exercizeServer starting\n");
999 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1000 HANDLE hFile=INVALID_HANDLE_VALUE;
1001 static const char obuf[] = "Bit Bucket";
1002 char ibuf[32];
1003 DWORD written;
1004 DWORD readden;
1005 int loop;
1007 for (loop = 0; loop < 3; loop++) {
1008 DWORD err;
1009 trace("Client connecting...\n");
1010 /* Connect to the server */
1011 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
1012 NULL, OPEN_EXISTING, 0, 0);
1013 if (hFile != INVALID_HANDLE_VALUE)
1014 break;
1015 err = GetLastError();
1016 if (loop == 0)
1017 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
1018 else
1019 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
1020 trace("connect failed, retrying\n");
1021 Sleep(200);
1023 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
1025 /* Make sure it can echo */
1026 memset(ibuf, 0, sizeof(ibuf));
1027 trace("Client writing...\n");
1028 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1029 ok(written == sizeof(obuf), "write file len\n");
1030 trace("Client reading...\n");
1031 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1032 ok(readden == sizeof(obuf), "read file len\n");
1033 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1035 trace("Client closing...\n");
1036 ok(CloseHandle(hFile), "CloseHandle\n");
1039 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1040 CloseHandle(hnp);
1041 trace("exercizeServer returning\n");
1044 static void test_NamedPipe_2(void)
1046 HANDLE serverThread;
1047 DWORD serverThreadId;
1048 HANDLE alarmThread;
1049 DWORD alarmThreadId;
1051 trace("test_NamedPipe_2 starting\n");
1052 /* Set up a twenty second timeout */
1053 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1054 SetLastError(0xdeadbeef);
1055 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1056 ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
1058 /* The servers we're about to exercise do try to clean up carefully,
1059 * but to reduce the chance of a test failure due to a pipe handle
1060 * leak in the test code, we'll use a different pipe name for each server.
1063 /* Try server #1 */
1064 SetLastError(0xdeadbeef);
1065 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1066 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1067 exercizeServer(PIPENAME "serverThreadMain1", serverThread);
1069 /* Try server #2 */
1070 SetLastError(0xdeadbeef);
1071 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1072 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1073 exercizeServer(PIPENAME "serverThreadMain2", serverThread);
1075 /* Try server #3 */
1076 SetLastError(0xdeadbeef);
1077 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1078 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1079 exercizeServer(PIPENAME "serverThreadMain3", serverThread);
1081 /* Try server #4 */
1082 SetLastError(0xdeadbeef);
1083 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1084 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1085 exercizeServer(PIPENAME "serverThreadMain4", serverThread);
1087 /* Try server #5 */
1088 SetLastError(0xdeadbeef);
1089 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1090 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1091 exercizeServer(PIPENAME "serverThreadMain5", serverThread);
1093 ok(SetEvent( alarm_event ), "SetEvent\n");
1094 CloseHandle( alarm_event );
1095 trace("test_NamedPipe_2 returning\n");
1098 static int test_DisconnectNamedPipe(void)
1100 HANDLE hnp;
1101 HANDLE hFile;
1102 static const char obuf[] = "Bit Bucket";
1103 char ibuf[32];
1104 DWORD written;
1105 DWORD readden;
1106 DWORD ret;
1108 SetLastError(0xdeadbeef);
1109 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1110 /* nMaxInstances */ 1,
1111 /* nOutBufSize */ 1024,
1112 /* nInBufSize */ 1024,
1113 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1114 /* lpSecurityAttrib */ NULL);
1115 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1116 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1118 win_skip("Named pipes are not implemented\n");
1119 return 1;
1122 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1123 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1124 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1125 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1127 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1128 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1130 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1131 if (hFile != INVALID_HANDLE_VALUE) {
1133 /* see what happens if server calls DisconnectNamedPipe
1134 * when there are bytes in the pipe
1137 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1138 ok(written == sizeof(obuf), "write file len\n");
1139 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1140 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1141 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1142 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1143 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1144 "ReadFile from disconnected pipe with bytes waiting\n");
1145 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1146 "DisconnectNamedPipe worked twice\n");
1147 ret = WaitForSingleObject(hFile, 0);
1148 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1149 ok(CloseHandle(hFile), "CloseHandle\n");
1152 ok(CloseHandle(hnp), "CloseHandle\n");
1154 return 0;
1156 static void test_CreatePipe(void)
1158 SECURITY_ATTRIBUTES pipe_attr;
1159 HANDLE piperead, pipewrite;
1160 DWORD written;
1161 DWORD read;
1162 DWORD i, size;
1163 BYTE *buffer;
1164 char readbuf[32];
1166 user_apc_ran = FALSE;
1167 if (pQueueUserAPC)
1168 ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1170 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1171 pipe_attr.bInheritHandle = TRUE;
1172 pipe_attr.lpSecurityDescriptor = NULL;
1173 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1174 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1175 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1176 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1177 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1178 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1179 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1181 /* Now write another chunk*/
1182 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1183 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1184 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1185 /* and close the write end, read should still succeed*/
1186 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1187 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe withe with pending data failed\n");
1188 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1189 /* But now we need to get informed that the pipe is closed */
1190 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1191 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1193 /* Try bigger chunks */
1194 size = 32768;
1195 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1196 for (i = 0; i < size; i++) buffer[i] = i;
1197 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1198 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1199 ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1200 /* and close the write end, read should still succeed*/
1201 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1202 memset( buffer, 0, size );
1203 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe withe with pending data failed\n");
1204 ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
1205 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1206 /* But now we need to get informed that the pipe is closed */
1207 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1208 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1209 HeapFree(GetProcessHeap(), 0, buffer);
1211 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1212 SleepEx(0, TRUE); /* get rid of apc */
1215 struct named_pipe_client_params
1217 DWORD security_flags;
1218 HANDLE token;
1219 BOOL revert;
1222 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1224 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1226 struct named_pipe_client_params *params = p;
1227 HANDLE pipe;
1228 BOOL ret;
1229 const char message[] = "Test";
1230 DWORD bytes_read, bytes_written;
1231 char dummy;
1232 TOKEN_PRIVILEGES *Privileges = NULL;
1234 if (params->token)
1236 if (params->revert)
1238 /* modify the token so we can tell if the pipe impersonation
1239 * token reverts to the process token */
1240 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1241 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1243 ret = SetThreadToken(NULL, params->token);
1244 ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1246 else
1248 DWORD Size = 0;
1249 HANDLE process_token;
1251 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1252 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1254 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1255 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1256 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1257 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1258 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1260 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1261 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1263 CloseHandle(process_token);
1266 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1267 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1269 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1270 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1272 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1273 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1275 if (params->token)
1277 if (params->revert)
1279 ret = RevertToSelf();
1280 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1282 else
1284 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1285 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1288 else
1290 HANDLE process_token;
1292 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1293 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1295 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1296 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1298 HeapFree(GetProcessHeap(), 0, Privileges);
1300 CloseHandle(process_token);
1303 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1304 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1306 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1307 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1309 CloseHandle(pipe);
1311 return 0;
1314 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1316 HANDLE ProcessToken;
1317 HANDLE Token = NULL;
1318 BOOL ret;
1320 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1321 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1323 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1324 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1326 CloseHandle(ProcessToken);
1328 return Token;
1331 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1333 HANDLE hPipeServer;
1334 BOOL ret;
1335 DWORD dwTid;
1336 HANDLE hThread;
1337 char buffer[256];
1338 DWORD dwBytesRead;
1339 DWORD error;
1340 struct named_pipe_client_params params;
1341 char dummy = 0;
1342 DWORD dwBytesWritten;
1343 HANDLE hToken = NULL;
1344 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1345 DWORD size;
1347 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1348 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1350 params.security_flags = security_flags;
1351 params.token = hClientToken;
1352 params.revert = revert;
1353 hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1354 ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1356 SetLastError(0xdeadbeef);
1357 ret = ImpersonateNamedPipeClient(hPipeServer);
1358 error = GetLastError();
1359 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1360 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1362 ret = ConnectNamedPipe(hPipeServer, NULL);
1363 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1365 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1366 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1368 ret = ImpersonateNamedPipeClient(hPipeServer);
1369 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1371 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1372 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1374 (*test_func)(0, hToken);
1376 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1377 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1378 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1379 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1381 CloseHandle(hToken);
1383 RevertToSelf();
1385 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1386 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1388 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1389 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1391 ret = ImpersonateNamedPipeClient(hPipeServer);
1392 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1394 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1395 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1397 (*test_func)(1, hToken);
1399 CloseHandle(hToken);
1401 RevertToSelf();
1403 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1404 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1406 WaitForSingleObject(hThread, INFINITE);
1408 ret = ImpersonateNamedPipeClient(hPipeServer);
1409 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1411 RevertToSelf();
1413 CloseHandle(hThread);
1414 CloseHandle(hPipeServer);
1417 static BOOL are_all_privileges_disabled(HANDLE hToken)
1419 BOOL ret;
1420 TOKEN_PRIVILEGES *Privileges = NULL;
1421 DWORD Size = 0;
1422 BOOL all_privs_disabled = TRUE;
1423 DWORD i;
1425 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1426 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1428 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1429 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1430 if (!ret)
1432 HeapFree(GetProcessHeap(), 0, Privileges);
1433 return FALSE;
1436 else
1437 return FALSE;
1439 for (i = 0; i < Privileges->PrivilegeCount; i++)
1441 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
1443 all_privs_disabled = FALSE;
1444 break;
1448 HeapFree(GetProcessHeap(), 0, Privileges);
1450 return all_privs_disabled;
1453 static DWORD get_privilege_count(HANDLE hToken)
1455 TOKEN_STATISTICS Statistics;
1456 DWORD Size = sizeof(Statistics);
1457 BOOL ret;
1459 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
1460 ok(ret, "GetTokenInformation(TokenStatistics)\n");
1461 if (!ret) return -1;
1463 return Statistics.PrivilegeCount;
1466 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
1468 DWORD priv_count;
1470 switch (call_index)
1472 case 0:
1473 priv_count = get_privilege_count(hToken);
1474 todo_wine
1475 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1476 break;
1477 case 1:
1478 priv_count = get_privilege_count(hToken);
1479 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1480 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1481 break;
1482 default:
1483 ok(0, "shouldn't happen\n");
1487 static void test_no_sqos(int call_index, HANDLE hToken)
1489 switch (call_index)
1491 case 0:
1492 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1493 break;
1494 case 1:
1495 todo_wine
1496 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1497 break;
1498 default:
1499 ok(0, "shouldn't happen\n");
1503 static void test_static_context(int call_index, HANDLE hToken)
1505 switch (call_index)
1507 case 0:
1508 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1509 break;
1510 case 1:
1511 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1512 break;
1513 default:
1514 ok(0, "shouldn't happen\n");
1518 static void test_dynamic_context(int call_index, HANDLE hToken)
1520 switch (call_index)
1522 case 0:
1523 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1524 break;
1525 case 1:
1526 todo_wine
1527 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1528 break;
1529 default:
1530 ok(0, "shouldn't happen\n");
1534 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
1536 switch (call_index)
1538 case 0:
1539 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1540 break;
1541 case 1:
1542 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
1543 break;
1544 default:
1545 ok(0, "shouldn't happen\n");
1549 static void test_no_sqos_revert(int call_index, HANDLE hToken)
1551 DWORD priv_count;
1552 switch (call_index)
1554 case 0:
1555 priv_count = get_privilege_count(hToken);
1556 todo_wine
1557 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1558 break;
1559 case 1:
1560 priv_count = get_privilege_count(hToken);
1561 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1562 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1563 break;
1564 default:
1565 ok(0, "shouldn't happen\n");
1569 static void test_static_context_revert(int call_index, HANDLE hToken)
1571 switch (call_index)
1573 case 0:
1574 todo_wine
1575 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1576 break;
1577 case 1:
1578 todo_wine
1579 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1580 break;
1581 default:
1582 ok(0, "shouldn't happen\n");
1586 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
1588 switch (call_index)
1590 case 0:
1591 todo_wine
1592 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1593 break;
1594 case 1:
1595 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
1596 break;
1597 default:
1598 ok(0, "shouldn't happen\n");
1602 static void test_impersonation(void)
1604 HANDLE hClientToken;
1605 HANDLE hProcessToken;
1606 BOOL ret;
1608 if( !pDuplicateTokenEx ) {
1609 skip("DuplicateTokenEx not found\n");
1610 return;
1613 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
1614 if (!ret)
1616 skip("couldn't open process token, skipping impersonation tests\n");
1617 return;
1620 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
1622 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
1623 CloseHandle(hProcessToken);
1624 return;
1626 CloseHandle(hProcessToken);
1628 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
1629 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1630 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
1631 CloseHandle(hClientToken);
1632 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1633 test_ImpersonateNamedPipeClient(hClientToken,
1634 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
1635 test_static_context);
1636 CloseHandle(hClientToken);
1637 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1638 test_ImpersonateNamedPipeClient(hClientToken,
1639 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1640 FALSE, test_dynamic_context);
1641 CloseHandle(hClientToken);
1642 test_ImpersonateNamedPipeClient(NULL,
1643 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1644 FALSE, test_dynamic_context_no_token);
1646 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1647 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
1648 CloseHandle(hClientToken);
1649 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1650 test_ImpersonateNamedPipeClient(hClientToken,
1651 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
1652 test_static_context_revert);
1653 CloseHandle(hClientToken);
1654 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1655 test_ImpersonateNamedPipeClient(hClientToken,
1656 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1657 TRUE, test_dynamic_context_revert);
1658 CloseHandle(hClientToken);
1661 struct overlapped_server_args
1663 HANDLE pipe_created;
1666 static DWORD CALLBACK overlapped_server(LPVOID arg)
1668 OVERLAPPED ol;
1669 HANDLE pipe;
1670 int ret, err;
1671 struct overlapped_server_args *a = arg;
1672 DWORD num;
1673 char buf[100];
1675 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
1676 ok(pipe != NULL, "pipe NULL\n");
1678 ol.hEvent = CreateEventA(0, 1, 0, 0);
1679 ok(ol.hEvent != NULL, "event NULL\n");
1680 ret = ConnectNamedPipe(pipe, &ol);
1681 err = GetLastError();
1682 ok(ret == 0, "ret %d\n", ret);
1683 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
1684 SetEvent(a->pipe_created);
1686 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
1687 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
1689 ret = GetOverlappedResult(pipe, &ol, &num, 1);
1690 ok(ret == 1, "ret %d\n", ret);
1692 /* This should block */
1693 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
1694 ok(ret == 1, "ret %d\n", ret);
1696 DisconnectNamedPipe(pipe);
1697 CloseHandle(ol.hEvent);
1698 CloseHandle(pipe);
1699 return 1;
1702 static void test_overlapped(void)
1704 DWORD tid, num;
1705 HANDLE thread, pipe;
1706 BOOL ret;
1707 struct overlapped_server_args args;
1709 args.pipe_created = CreateEventA(0, 1, 0, 0);
1710 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
1712 WaitForSingleObject(args.pipe_created, INFINITE);
1713 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1714 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
1716 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
1717 Sleep(1);
1719 ret = WriteFile(pipe, "x", 1, &num, NULL);
1720 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1722 WaitForSingleObject(thread, INFINITE);
1723 CloseHandle(pipe);
1724 CloseHandle(args.pipe_created);
1725 CloseHandle(thread);
1728 static void test_NamedPipeHandleState(void)
1730 HANDLE server, client;
1731 BOOL ret;
1732 DWORD state, instances, maxCollectionCount, collectDataTimeout;
1733 char userName[MAX_PATH];
1735 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1736 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1737 /* nMaxInstances */ 1,
1738 /* nOutBufSize */ 1024,
1739 /* nInBufSize */ 1024,
1740 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1741 /* lpSecurityAttrib */ NULL);
1742 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1743 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
1744 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1745 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
1747 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1748 if (ret)
1750 ok(state == 0, "unexpected state %08x\n", state);
1751 ok(instances == 1, "expected 1 instances, got %d\n", instances);
1753 /* Some parameters have no meaning, and therefore can't be retrieved,
1754 * on a local pipe.
1756 SetLastError(0xdeadbeef);
1757 ret = GetNamedPipeHandleStateA(server, &state, &instances,
1758 &maxCollectionCount, &collectDataTimeout, userName,
1759 sizeof(userName) / sizeof(userName[0]));
1760 todo_wine
1761 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1762 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1763 /* A byte-mode pipe server can't be changed to message mode. */
1764 state = PIPE_READMODE_MESSAGE;
1765 SetLastError(0xdeadbeef);
1766 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1767 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1768 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1770 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1771 OPEN_EXISTING, 0, NULL);
1772 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1774 state = PIPE_READMODE_BYTE;
1775 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1776 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1777 /* A byte-mode pipe client can't be changed to message mode, either. */
1778 state = PIPE_READMODE_MESSAGE;
1779 SetLastError(0xdeadbeef);
1780 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1781 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1782 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1784 CloseHandle(client);
1785 CloseHandle(server);
1787 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1788 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
1789 /* nMaxInstances */ 1,
1790 /* nOutBufSize */ 1024,
1791 /* nInBufSize */ 1024,
1792 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1793 /* lpSecurityAttrib */ NULL);
1794 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1795 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
1796 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1797 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
1799 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1800 if (ret)
1802 ok(state == 0, "unexpected state %08x\n", state);
1803 ok(instances == 1, "expected 1 instances, got %d\n", instances);
1805 /* In contrast to byte-mode pipes, a message-mode pipe server can be
1806 * changed to byte mode.
1808 state = PIPE_READMODE_BYTE;
1809 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1810 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1812 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1813 OPEN_EXISTING, 0, NULL);
1814 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1816 state = PIPE_READMODE_MESSAGE;
1817 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1818 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1819 /* A message-mode pipe client can also be changed to byte mode.
1821 state = PIPE_READMODE_BYTE;
1822 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1823 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1825 CloseHandle(client);
1826 CloseHandle(server);
1829 static void test_readfileex_pending(void)
1831 HANDLE server, client, event;
1832 BOOL ret;
1833 DWORD err, wait, num_bytes;
1834 OVERLAPPED overlapped;
1835 char read_buf[1024];
1836 char write_buf[1024];
1837 const char test_string[] = "test";
1838 int i;
1840 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
1841 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1842 /* nMaxInstances */ 1,
1843 /* nOutBufSize */ 1024,
1844 /* nInBufSize */ 1024,
1845 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1846 /* lpSecurityAttrib */ NULL);
1847 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1849 event = CreateEventA(NULL, TRUE, FALSE, NULL);
1850 ok(event != NULL, "CreateEventA failed\n");
1852 memset(&overlapped, 0, sizeof(overlapped));
1853 overlapped.hEvent = event;
1855 ret = ConnectNamedPipe(server, &overlapped);
1856 err = GetLastError();
1857 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
1858 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
1860 wait = WaitForSingleObject(event, 0);
1861 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
1863 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1864 OPEN_EXISTING, 0, NULL);
1865 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1867 wait = WaitForSingleObject(event, 0);
1868 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1870 /* Start a read that can't complete immediately. */
1871 completion_called = 0;
1872 ResetEvent(event);
1873 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
1874 ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
1875 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
1877 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
1878 ok(ret == TRUE, "WriteFile failed\n");
1879 ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
1881 ok(completion_called == 0, "completion routine called during WriteFile\n");
1883 wait = WaitForSingleObjectEx(event, 0, TRUE);
1884 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
1886 ok(completion_called == 1, "completion not called after writing pipe\n");
1887 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1888 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
1889 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1890 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
1892 /* Make writes until the pipe is full and the write fails */
1893 memset(write_buf, 0xaa, sizeof(write_buf));
1894 for (i=0; i<256; i++)
1896 completion_called = 0;
1897 ResetEvent(event);
1898 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
1899 err = GetLastError();
1901 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
1903 wait = WaitForSingleObjectEx(event, 0, TRUE);
1905 if (wait == WAIT_TIMEOUT)
1906 /* write couldn't complete immediately, presumably the pipe is full */
1907 break;
1909 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1911 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
1912 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1913 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1916 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
1917 ok(completion_called == 0, "completion routine called but wait timed out\n");
1918 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1919 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1921 /* free up some space in the pipe */
1922 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
1923 ok(ret == TRUE, "ReadFile failed\n");
1925 ok(completion_called == 0, "completion routine called during ReadFile\n");
1927 wait = WaitForSingleObjectEx(event, 0, TRUE);
1928 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1929 if (wait == WAIT_TIMEOUT)
1931 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
1932 ok(ret == TRUE, "ReadFile failed\n");
1933 ok(completion_called == 0, "completion routine called during ReadFile\n");
1934 wait = WaitForSingleObjectEx(event, 0, TRUE);
1935 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1938 ok(completion_called == 1, "completion routine not called\n");
1939 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1940 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1942 num_bytes = 0xdeadbeef;
1943 SetLastError(0xdeadbeef);
1944 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
1945 ok(!ret, "ReadFile should fail\n");
1946 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
1947 ok(num_bytes == 0, "expected 0, got %u\n", num_bytes);
1949 S(U(overlapped)).Offset = 0;
1950 S(U(overlapped)).OffsetHigh = 0;
1951 overlapped.Internal = -1;
1952 overlapped.InternalHigh = -1;
1953 overlapped.hEvent = event;
1954 num_bytes = 0xdeadbeef;
1955 SetLastError(0xdeadbeef);
1956 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
1957 todo_wine
1958 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
1959 ok(num_bytes == 0, "bytes %u\n", num_bytes);
1960 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
1961 todo_wine
1962 ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
1964 wait = WaitForSingleObject(event, 100);
1965 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
1967 num_bytes = 0xdeadbeef;
1968 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
1969 ok(ret, "WriteFile failed\n");
1970 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1972 wait = WaitForSingleObject(event, 100);
1973 todo_wine
1974 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1976 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1977 todo_wine
1978 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
1979 ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
1981 /* read the pending byte and clear the pipe */
1982 num_bytes = 0xdeadbeef;
1983 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
1984 ok(ret, "ReadFile failed\n");
1985 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1987 CloseHandle(client);
1988 CloseHandle(server);
1989 CloseHandle(event);
1992 START_TEST(pipe)
1994 HMODULE hmod;
1996 hmod = GetModuleHandleA("advapi32.dll");
1997 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
1998 hmod = GetModuleHandleA("kernel32.dll");
1999 pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
2001 if (test_DisconnectNamedPipe())
2002 return;
2003 test_CreateNamedPipe_instances_must_match();
2004 test_NamedPipe_2();
2005 test_CreateNamedPipe(PIPE_TYPE_BYTE);
2006 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
2007 test_CreatePipe();
2008 test_impersonation();
2009 test_overlapped();
2010 test_NamedPipeHandleState();
2011 test_readfileex_pending();