kernel32/tests: Add basic tests for partially received pipe messages (ERROR_MORE_DATA).
[wine/multimedia.git] / dlls / kernel32 / tests / pipe.c
blob5e969300c837da1c08ae808be170a9c9713e9d88
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");
349 /* Picky conformance tests */
351 /* Verify that you can't connect to pipe again
352 * until server calls DisconnectNamedPipe+ConnectNamedPipe
353 * or creates a new pipe
354 * case 1: other client not yet closed
356 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
357 ok(hFile2 == INVALID_HANDLE_VALUE,
358 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
359 ok(GetLastError() == ERROR_PIPE_BUSY,
360 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
362 ok(CloseHandle(hFile), "CloseHandle\n");
364 /* case 2: other client already closed */
365 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
366 ok(hFile == INVALID_HANDLE_VALUE,
367 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
368 ok(GetLastError() == ERROR_PIPE_BUSY,
369 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
371 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
373 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
374 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
375 ok(hFile == INVALID_HANDLE_VALUE,
376 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
377 ok(GetLastError() == ERROR_PIPE_BUSY,
378 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
380 /* to be complete, we'd call ConnectNamedPipe here and loop,
381 * but by default that's blocking, so we'd either have
382 * to turn on the uncommon nonblocking mode, or
383 * use another thread.
387 ok(CloseHandle(hnp), "CloseHandle\n");
389 trace("test_CreateNamedPipe returning\n");
392 static void test_CreateNamedPipe_instances_must_match(void)
394 HANDLE hnp, hnp2;
396 /* Check no mismatch */
397 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
398 /* nMaxInstances */ 2,
399 /* nOutBufSize */ 1024,
400 /* nInBufSize */ 1024,
401 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
402 /* lpSecurityAttrib */ NULL);
403 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
405 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
406 /* nMaxInstances */ 2,
407 /* nOutBufSize */ 1024,
408 /* nInBufSize */ 1024,
409 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
410 /* lpSecurityAttrib */ NULL);
411 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
413 ok(CloseHandle(hnp), "CloseHandle\n");
414 ok(CloseHandle(hnp2), "CloseHandle\n");
416 /* Check nMaxInstances */
417 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
418 /* nMaxInstances */ 1,
419 /* nOutBufSize */ 1024,
420 /* nInBufSize */ 1024,
421 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
422 /* lpSecurityAttrib */ NULL);
423 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
425 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
426 /* nMaxInstances */ 1,
427 /* nOutBufSize */ 1024,
428 /* nInBufSize */ 1024,
429 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
430 /* lpSecurityAttrib */ NULL);
431 ok(hnp2 == INVALID_HANDLE_VALUE
432 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
434 ok(CloseHandle(hnp), "CloseHandle\n");
436 /* Check PIPE_ACCESS_* */
437 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
438 /* nMaxInstances */ 2,
439 /* nOutBufSize */ 1024,
440 /* nInBufSize */ 1024,
441 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
442 /* lpSecurityAttrib */ NULL);
443 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
445 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
446 /* nMaxInstances */ 2,
447 /* nOutBufSize */ 1024,
448 /* nInBufSize */ 1024,
449 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
450 /* lpSecurityAttrib */ NULL);
451 ok(hnp2 == INVALID_HANDLE_VALUE
452 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
454 ok(CloseHandle(hnp), "CloseHandle\n");
456 /* check everything else */
457 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
458 /* nMaxInstances */ 4,
459 /* nOutBufSize */ 1024,
460 /* nInBufSize */ 1024,
461 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
462 /* lpSecurityAttrib */ NULL);
463 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
465 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
466 /* nMaxInstances */ 3,
467 /* nOutBufSize */ 102,
468 /* nInBufSize */ 24,
469 /* nDefaultWait */ 1234,
470 /* lpSecurityAttrib */ NULL);
471 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
473 ok(CloseHandle(hnp), "CloseHandle\n");
474 ok(CloseHandle(hnp2), "CloseHandle\n");
477 /** implementation of alarm() */
478 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
480 DWORD_PTR timeout = (DWORD_PTR) arg;
481 trace("alarmThreadMain\n");
482 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
484 ok(FALSE, "alarm\n");
485 ExitProcess(1);
487 return 1;
490 static HANDLE hnp = INVALID_HANDLE_VALUE;
492 /** Trivial byte echo server - disconnects after each session */
493 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
495 int i;
497 trace("serverThreadMain1 start\n");
498 /* Set up a simple echo server */
499 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
500 PIPE_TYPE_BYTE | PIPE_WAIT,
501 /* nMaxInstances */ 1,
502 /* nOutBufSize */ 1024,
503 /* nInBufSize */ 1024,
504 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
505 /* lpSecurityAttrib */ NULL);
507 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
508 for (i = 0; i < NB_SERVER_LOOPS; i++) {
509 char buf[512];
510 DWORD written;
511 DWORD readden;
512 BOOL success;
514 /* Wait for client to connect */
515 trace("Server calling ConnectNamedPipe...\n");
516 ok(ConnectNamedPipe(hnp, NULL)
517 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
518 trace("ConnectNamedPipe returned.\n");
520 /* Echo bytes once */
521 memset(buf, 0, sizeof(buf));
523 trace("Server reading...\n");
524 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
525 trace("Server done reading.\n");
526 ok(success, "ReadFile\n");
527 ok(readden, "short read\n");
529 trace("Server writing...\n");
530 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
531 trace("Server done writing.\n");
532 ok(written == readden, "write file len\n");
534 /* finish this connection, wait for next one */
535 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
536 trace("Server done flushing.\n");
537 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
538 trace("Server done disconnecting.\n");
540 return 0;
543 /** Trivial byte echo server - closes after each connection */
544 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
546 int i;
547 HANDLE hnpNext = 0;
549 trace("serverThreadMain2\n");
550 /* Set up a simple echo server */
551 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
552 PIPE_TYPE_BYTE | PIPE_WAIT,
553 /* nMaxInstances */ 2,
554 /* nOutBufSize */ 1024,
555 /* nInBufSize */ 1024,
556 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
557 /* lpSecurityAttrib */ NULL);
558 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
560 for (i = 0; i < NB_SERVER_LOOPS; i++) {
561 char buf[512];
562 DWORD written;
563 DWORD readden;
564 DWORD ret;
565 BOOL success;
568 user_apc_ran = FALSE;
569 if (i == 0 && pQueueUserAPC) {
570 trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
571 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
572 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
575 /* Wait for client to connect */
576 trace("Server calling ConnectNamedPipe...\n");
577 ok(ConnectNamedPipe(hnp, NULL)
578 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
579 trace("ConnectNamedPipe returned.\n");
581 /* Echo bytes once */
582 memset(buf, 0, sizeof(buf));
584 trace("Server reading...\n");
585 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
586 trace("Server done reading.\n");
587 ok(success, "ReadFile\n");
589 trace("Server writing...\n");
590 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
591 trace("Server done writing.\n");
592 ok(written == readden, "write file len\n");
594 /* finish this connection, wait for next one */
595 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
596 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
598 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
600 if (i == 0 && pQueueUserAPC)
601 SleepEx(0, TRUE); /* get rid of apc */
603 /* Set up next echo server */
604 hnpNext =
605 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
606 PIPE_TYPE_BYTE | PIPE_WAIT,
607 /* nMaxInstances */ 2,
608 /* nOutBufSize */ 1024,
609 /* nInBufSize */ 1024,
610 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
611 /* lpSecurityAttrib */ NULL);
613 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
615 ok(CloseHandle(hnp), "CloseHandle\n");
616 hnp = hnpNext;
618 return 0;
621 /** Trivial byte echo server - uses overlapped named pipe calls */
622 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
624 int i;
625 HANDLE hEvent;
627 trace("serverThreadMain3\n");
628 /* Set up a simple echo server */
629 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
630 PIPE_TYPE_BYTE | PIPE_WAIT,
631 /* nMaxInstances */ 1,
632 /* nOutBufSize */ 1024,
633 /* nInBufSize */ 1024,
634 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
635 /* lpSecurityAttrib */ NULL);
636 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
638 hEvent = CreateEventW(NULL, /* security attribute */
639 TRUE, /* manual reset event */
640 FALSE, /* initial state */
641 NULL); /* name */
642 ok(hEvent != NULL, "CreateEvent\n");
644 for (i = 0; i < NB_SERVER_LOOPS; i++) {
645 char buf[512];
646 DWORD written;
647 DWORD readden;
648 DWORD dummy;
649 BOOL success;
650 OVERLAPPED oOverlap;
651 int letWFSOEwait = (i & 2);
652 int letGORwait = (i & 1);
653 DWORD err;
655 memset(&oOverlap, 0, sizeof(oOverlap));
656 oOverlap.hEvent = hEvent;
658 /* Wait for client to connect */
659 if (i == 0) {
660 trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
661 success = ConnectNamedPipe(hnp, NULL);
662 err = GetLastError();
663 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
664 trace("ConnectNamedPipe operation complete.\n");
665 } else {
666 trace("Server calling overlapped ConnectNamedPipe...\n");
667 success = ConnectNamedPipe(hnp, &oOverlap);
668 err = GetLastError();
669 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
670 trace("overlapped ConnectNamedPipe returned.\n");
671 if (!success && (err == ERROR_IO_PENDING)) {
672 if (letWFSOEwait)
674 DWORD ret;
675 do {
676 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
677 } while (ret == WAIT_IO_COMPLETION);
678 ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
680 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
681 if (!letGORwait && !letWFSOEwait && !success) {
682 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
683 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
686 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
687 trace("overlapped ConnectNamedPipe operation complete.\n");
690 /* Echo bytes once */
691 memset(buf, 0, sizeof(buf));
693 trace("Server reading...\n");
694 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
695 trace("Server ReadFile returned...\n");
696 err = GetLastError();
697 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
698 trace("overlapped ReadFile 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 ReadFile returned %x\n", ret);
708 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
709 if (!letGORwait && !letWFSOEwait && !success) {
710 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
711 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
714 trace("Server done reading.\n");
715 ok(success, "overlapped ReadFile\n");
717 trace("Server writing...\n");
718 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
719 trace("Server WriteFile returned...\n");
720 err = GetLastError();
721 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
722 trace("overlapped WriteFile returned.\n");
723 if (!success && (err == ERROR_IO_PENDING)) {
724 if (letWFSOEwait)
726 DWORD ret;
727 do {
728 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
729 } while (ret == WAIT_IO_COMPLETION);
730 ok(ret == 0, "wait WriteFile returned %x\n", ret);
732 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
733 if (!letGORwait && !letWFSOEwait && !success) {
734 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
735 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
738 trace("Server done writing.\n");
739 ok(success, "overlapped WriteFile\n");
740 ok(written == readden, "write file len\n");
742 /* finish this connection, wait for next one */
743 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
744 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
746 return 0;
749 /** Trivial byte echo server - uses i/o completion ports */
750 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
752 int i;
753 HANDLE hcompletion;
754 BOOL ret;
756 trace("serverThreadMain4\n");
757 /* Set up a simple echo server */
758 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
759 PIPE_TYPE_BYTE | PIPE_WAIT,
760 /* nMaxInstances */ 1,
761 /* nOutBufSize */ 1024,
762 /* nInBufSize */ 1024,
763 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
764 /* lpSecurityAttrib */ NULL);
765 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
767 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
768 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
770 for (i = 0; i < NB_SERVER_LOOPS; i++) {
771 char buf[512];
772 DWORD written;
773 DWORD readden;
774 DWORD dummy;
775 BOOL success;
776 OVERLAPPED oConnect;
777 OVERLAPPED oRead;
778 OVERLAPPED oWrite;
779 OVERLAPPED *oResult;
780 DWORD err;
781 ULONG_PTR compkey;
783 memset(&oConnect, 0, sizeof(oConnect));
784 memset(&oRead, 0, sizeof(oRead));
785 memset(&oWrite, 0, sizeof(oWrite));
787 /* Wait for client to connect */
788 trace("Server calling overlapped ConnectNamedPipe...\n");
789 success = ConnectNamedPipe(hnp, &oConnect);
790 err = GetLastError();
791 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
792 "overlapped ConnectNamedPipe got %u err %u\n", success, err );
793 if (!success && err == ERROR_IO_PENDING) {
794 trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
795 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
796 if (!success)
798 ok( GetLastError() == WAIT_TIMEOUT,
799 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
800 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
802 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
803 if (success)
805 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
806 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
809 trace("overlapped ConnectNamedPipe operation complete.\n");
811 /* Echo bytes once */
812 memset(buf, 0, sizeof(buf));
814 trace("Server reading...\n");
815 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
816 trace("Server ReadFile returned...\n");
817 err = GetLastError();
818 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
819 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
820 &oResult, 10000);
821 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
822 if (success)
824 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
825 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
827 trace("Server done reading.\n");
829 trace("Server writing...\n");
830 success = WriteFile(hnp, buf, readden, &written, &oWrite);
831 trace("Server WriteFile returned...\n");
832 err = GetLastError();
833 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
834 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
835 &oResult, 10000);
836 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
837 if (success)
839 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
840 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
841 ok(written == readden, "write file len\n");
843 trace("Server done writing.\n");
845 /* finish this connection, wait for next one */
846 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
847 success = DisconnectNamedPipe(hnp);
848 ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
851 ret = CloseHandle(hnp);
852 ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
853 ret = CloseHandle(hcompletion);
854 ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
856 return 0;
859 static int completion_called;
860 static DWORD completion_errorcode;
861 static DWORD completion_num_bytes;
862 static LPOVERLAPPED completion_lpoverlapped;
864 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
866 completion_called++;
867 completion_errorcode = errorcode;
868 completion_num_bytes = num_bytes;
869 completion_lpoverlapped = lpoverlapped;
870 SetEvent(lpoverlapped->hEvent);
873 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
874 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
876 int i;
877 HANDLE hEvent;
879 trace("serverThreadMain5\n");
880 /* Set up a simple echo server */
881 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
882 PIPE_TYPE_BYTE | PIPE_WAIT,
883 /* nMaxInstances */ 1,
884 /* nOutBufSize */ 1024,
885 /* nInBufSize */ 1024,
886 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
887 /* lpSecurityAttrib */ NULL);
888 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
890 hEvent = CreateEventW(NULL, /* security attribute */
891 TRUE, /* manual reset event */
892 FALSE, /* initial state */
893 NULL); /* name */
894 ok(hEvent != NULL, "CreateEvent\n");
896 for (i = 0; i < NB_SERVER_LOOPS; i++) {
897 char buf[512];
898 DWORD readden;
899 BOOL success;
900 OVERLAPPED oOverlap;
901 DWORD err;
903 memset(&oOverlap, 0, sizeof(oOverlap));
904 oOverlap.hEvent = hEvent;
906 /* Wait for client to connect */
907 trace("Server calling ConnectNamedPipe...\n");
908 success = ConnectNamedPipe(hnp, NULL);
909 err = GetLastError();
910 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
911 trace("ConnectNamedPipe operation complete.\n");
913 /* Echo bytes once */
914 memset(buf, 0, sizeof(buf));
916 trace("Server reading...\n");
917 completion_called = 0;
918 ResetEvent(hEvent);
919 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
920 trace("Server ReadFileEx returned...\n");
921 ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
922 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
923 trace("ReadFileEx returned.\n");
924 if (success) {
925 DWORD ret;
926 do {
927 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
928 } while (ret == WAIT_IO_COMPLETION);
929 ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
931 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
932 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
933 ok(completion_num_bytes != 0, "read 0 bytes\n");
934 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
935 readden = completion_num_bytes;
936 trace("Server done reading.\n");
938 trace("Server writing...\n");
939 completion_called = 0;
940 ResetEvent(hEvent);
941 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
942 trace("Server WriteFileEx returned...\n");
943 ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
944 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
945 trace("overlapped WriteFile returned.\n");
946 if (success) {
947 DWORD ret;
948 do {
949 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
950 } while (ret == WAIT_IO_COMPLETION);
951 ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
953 trace("Server done writing.\n");
954 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
955 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
956 ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
957 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
959 /* finish this connection, wait for next one */
960 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
961 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
963 return 0;
966 static void exercizeServer(const char *pipename, HANDLE serverThread)
968 int i;
970 trace("exercizeServer starting\n");
971 for (i = 0; i < NB_SERVER_LOOPS; i++) {
972 HANDLE hFile=INVALID_HANDLE_VALUE;
973 static const char obuf[] = "Bit Bucket";
974 char ibuf[32];
975 DWORD written;
976 DWORD readden;
977 int loop;
979 for (loop = 0; loop < 3; loop++) {
980 DWORD err;
981 trace("Client connecting...\n");
982 /* Connect to the server */
983 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
984 NULL, OPEN_EXISTING, 0, 0);
985 if (hFile != INVALID_HANDLE_VALUE)
986 break;
987 err = GetLastError();
988 if (loop == 0)
989 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
990 else
991 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
992 trace("connect failed, retrying\n");
993 Sleep(200);
995 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
997 /* Make sure it can echo */
998 memset(ibuf, 0, sizeof(ibuf));
999 trace("Client writing...\n");
1000 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1001 ok(written == sizeof(obuf), "write file len\n");
1002 trace("Client reading...\n");
1003 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1004 ok(readden == sizeof(obuf), "read file len\n");
1005 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1007 trace("Client closing...\n");
1008 ok(CloseHandle(hFile), "CloseHandle\n");
1011 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1012 CloseHandle(hnp);
1013 trace("exercizeServer returning\n");
1016 static void test_NamedPipe_2(void)
1018 HANDLE serverThread;
1019 DWORD serverThreadId;
1020 HANDLE alarmThread;
1021 DWORD alarmThreadId;
1023 trace("test_NamedPipe_2 starting\n");
1024 /* Set up a twenty second timeout */
1025 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1026 SetLastError(0xdeadbeef);
1027 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1028 ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
1030 /* The servers we're about to exercise do try to clean up carefully,
1031 * but to reduce the chance of a test failure due to a pipe handle
1032 * leak in the test code, we'll use a different pipe name for each server.
1035 /* Try server #1 */
1036 SetLastError(0xdeadbeef);
1037 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1038 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1039 exercizeServer(PIPENAME "serverThreadMain1", serverThread);
1041 /* Try server #2 */
1042 SetLastError(0xdeadbeef);
1043 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1044 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1045 exercizeServer(PIPENAME "serverThreadMain2", serverThread);
1047 /* Try server #3 */
1048 SetLastError(0xdeadbeef);
1049 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1050 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1051 exercizeServer(PIPENAME "serverThreadMain3", serverThread);
1053 /* Try server #4 */
1054 SetLastError(0xdeadbeef);
1055 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1056 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1057 exercizeServer(PIPENAME "serverThreadMain4", serverThread);
1059 /* Try server #5 */
1060 SetLastError(0xdeadbeef);
1061 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1062 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1063 exercizeServer(PIPENAME "serverThreadMain5", serverThread);
1065 ok(SetEvent( alarm_event ), "SetEvent\n");
1066 CloseHandle( alarm_event );
1067 trace("test_NamedPipe_2 returning\n");
1070 static int test_DisconnectNamedPipe(void)
1072 HANDLE hnp;
1073 HANDLE hFile;
1074 static const char obuf[] = "Bit Bucket";
1075 char ibuf[32];
1076 DWORD written;
1077 DWORD readden;
1078 DWORD ret;
1080 SetLastError(0xdeadbeef);
1081 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1082 /* nMaxInstances */ 1,
1083 /* nOutBufSize */ 1024,
1084 /* nInBufSize */ 1024,
1085 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1086 /* lpSecurityAttrib */ NULL);
1087 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1088 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1090 win_skip("Named pipes are not implemented\n");
1091 return 1;
1094 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1095 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1096 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1097 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1099 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1100 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1102 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1103 if (hFile != INVALID_HANDLE_VALUE) {
1105 /* see what happens if server calls DisconnectNamedPipe
1106 * when there are bytes in the pipe
1109 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1110 ok(written == sizeof(obuf), "write file len\n");
1111 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1112 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1113 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1114 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1115 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1116 "ReadFile from disconnected pipe with bytes waiting\n");
1117 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1118 "DisconnectNamedPipe worked twice\n");
1119 ret = WaitForSingleObject(hFile, 0);
1120 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1121 ok(CloseHandle(hFile), "CloseHandle\n");
1124 ok(CloseHandle(hnp), "CloseHandle\n");
1126 return 0;
1128 static void test_CreatePipe(void)
1130 SECURITY_ATTRIBUTES pipe_attr;
1131 HANDLE piperead, pipewrite;
1132 DWORD written;
1133 DWORD read;
1134 DWORD i, size;
1135 BYTE *buffer;
1136 char readbuf[32];
1138 user_apc_ran = FALSE;
1139 if (pQueueUserAPC)
1140 ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1142 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1143 pipe_attr.bInheritHandle = TRUE;
1144 pipe_attr.lpSecurityDescriptor = NULL;
1145 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1146 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1147 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1148 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1149 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1150 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1151 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1153 /* Now write another chunk*/
1154 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1155 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1156 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1157 /* and close the write end, read should still succeed*/
1158 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1159 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe withe with pending data failed\n");
1160 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1161 /* But now we need to get informed that the pipe is closed */
1162 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1163 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1165 /* Try bigger chunks */
1166 size = 32768;
1167 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1168 for (i = 0; i < size; i++) buffer[i] = i;
1169 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1170 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1171 ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1172 /* and close the write end, read should still succeed*/
1173 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1174 memset( buffer, 0, size );
1175 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe withe with pending data failed\n");
1176 ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
1177 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1178 /* But now we need to get informed that the pipe is closed */
1179 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1180 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1181 HeapFree(GetProcessHeap(), 0, buffer);
1183 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1184 SleepEx(0, TRUE); /* get rid of apc */
1187 struct named_pipe_client_params
1189 DWORD security_flags;
1190 HANDLE token;
1191 BOOL revert;
1194 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1196 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1198 struct named_pipe_client_params *params = p;
1199 HANDLE pipe;
1200 BOOL ret;
1201 const char message[] = "Test";
1202 DWORD bytes_read, bytes_written;
1203 char dummy;
1204 TOKEN_PRIVILEGES *Privileges = NULL;
1206 if (params->token)
1208 if (params->revert)
1210 /* modify the token so we can tell if the pipe impersonation
1211 * token reverts to the process token */
1212 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1213 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1215 ret = SetThreadToken(NULL, params->token);
1216 ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1218 else
1220 DWORD Size = 0;
1221 HANDLE process_token;
1223 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1224 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1226 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1227 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1228 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1229 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1230 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1232 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1233 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1235 CloseHandle(process_token);
1238 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1239 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1241 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1242 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1244 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1245 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1247 if (params->token)
1249 if (params->revert)
1251 ret = RevertToSelf();
1252 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1254 else
1256 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1257 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1260 else
1262 HANDLE process_token;
1264 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1265 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1267 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1268 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1270 HeapFree(GetProcessHeap(), 0, Privileges);
1272 CloseHandle(process_token);
1275 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1276 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1278 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1279 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1281 CloseHandle(pipe);
1283 return 0;
1286 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1288 HANDLE ProcessToken;
1289 HANDLE Token = NULL;
1290 BOOL ret;
1292 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1293 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1295 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1296 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1298 CloseHandle(ProcessToken);
1300 return Token;
1303 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1305 HANDLE hPipeServer;
1306 BOOL ret;
1307 DWORD dwTid;
1308 HANDLE hThread;
1309 char buffer[256];
1310 DWORD dwBytesRead;
1311 DWORD error;
1312 struct named_pipe_client_params params;
1313 char dummy = 0;
1314 DWORD dwBytesWritten;
1315 HANDLE hToken = NULL;
1316 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1317 DWORD size;
1319 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1320 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1322 params.security_flags = security_flags;
1323 params.token = hClientToken;
1324 params.revert = revert;
1325 hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1326 ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1328 SetLastError(0xdeadbeef);
1329 ret = ImpersonateNamedPipeClient(hPipeServer);
1330 error = GetLastError();
1331 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1332 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1334 ret = ConnectNamedPipe(hPipeServer, NULL);
1335 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1337 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1338 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1340 ret = ImpersonateNamedPipeClient(hPipeServer);
1341 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1343 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1344 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1346 (*test_func)(0, hToken);
1348 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1349 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1350 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1351 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1353 CloseHandle(hToken);
1355 RevertToSelf();
1357 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1358 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1360 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1361 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1363 ret = ImpersonateNamedPipeClient(hPipeServer);
1364 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1366 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1367 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1369 (*test_func)(1, hToken);
1371 CloseHandle(hToken);
1373 RevertToSelf();
1375 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1376 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1378 WaitForSingleObject(hThread, INFINITE);
1380 ret = ImpersonateNamedPipeClient(hPipeServer);
1381 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1383 RevertToSelf();
1385 CloseHandle(hThread);
1386 CloseHandle(hPipeServer);
1389 static BOOL are_all_privileges_disabled(HANDLE hToken)
1391 BOOL ret;
1392 TOKEN_PRIVILEGES *Privileges = NULL;
1393 DWORD Size = 0;
1394 BOOL all_privs_disabled = TRUE;
1395 DWORD i;
1397 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1398 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1400 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1401 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1402 if (!ret)
1404 HeapFree(GetProcessHeap(), 0, Privileges);
1405 return FALSE;
1408 else
1409 return FALSE;
1411 for (i = 0; i < Privileges->PrivilegeCount; i++)
1413 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
1415 all_privs_disabled = FALSE;
1416 break;
1420 HeapFree(GetProcessHeap(), 0, Privileges);
1422 return all_privs_disabled;
1425 static DWORD get_privilege_count(HANDLE hToken)
1427 TOKEN_STATISTICS Statistics;
1428 DWORD Size = sizeof(Statistics);
1429 BOOL ret;
1431 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
1432 ok(ret, "GetTokenInformation(TokenStatistics)\n");
1433 if (!ret) return -1;
1435 return Statistics.PrivilegeCount;
1438 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
1440 DWORD priv_count;
1442 switch (call_index)
1444 case 0:
1445 priv_count = get_privilege_count(hToken);
1446 todo_wine
1447 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1448 break;
1449 case 1:
1450 priv_count = get_privilege_count(hToken);
1451 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1452 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1453 break;
1454 default:
1455 ok(0, "shouldn't happen\n");
1459 static void test_no_sqos(int call_index, HANDLE hToken)
1461 switch (call_index)
1463 case 0:
1464 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1465 break;
1466 case 1:
1467 todo_wine
1468 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1469 break;
1470 default:
1471 ok(0, "shouldn't happen\n");
1475 static void test_static_context(int call_index, HANDLE hToken)
1477 switch (call_index)
1479 case 0:
1480 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1481 break;
1482 case 1:
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_dynamic_context(int call_index, HANDLE hToken)
1492 switch (call_index)
1494 case 0:
1495 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1496 break;
1497 case 1:
1498 todo_wine
1499 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1500 break;
1501 default:
1502 ok(0, "shouldn't happen\n");
1506 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
1508 switch (call_index)
1510 case 0:
1511 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1512 break;
1513 case 1:
1514 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
1515 break;
1516 default:
1517 ok(0, "shouldn't happen\n");
1521 static void test_no_sqos_revert(int call_index, HANDLE hToken)
1523 DWORD priv_count;
1524 switch (call_index)
1526 case 0:
1527 priv_count = get_privilege_count(hToken);
1528 todo_wine
1529 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1530 break;
1531 case 1:
1532 priv_count = get_privilege_count(hToken);
1533 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1534 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1535 break;
1536 default:
1537 ok(0, "shouldn't happen\n");
1541 static void test_static_context_revert(int call_index, HANDLE hToken)
1543 switch (call_index)
1545 case 0:
1546 todo_wine
1547 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1548 break;
1549 case 1:
1550 todo_wine
1551 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1552 break;
1553 default:
1554 ok(0, "shouldn't happen\n");
1558 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
1560 switch (call_index)
1562 case 0:
1563 todo_wine
1564 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1565 break;
1566 case 1:
1567 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
1568 break;
1569 default:
1570 ok(0, "shouldn't happen\n");
1574 static void test_impersonation(void)
1576 HANDLE hClientToken;
1577 HANDLE hProcessToken;
1578 BOOL ret;
1580 if( !pDuplicateTokenEx ) {
1581 skip("DuplicateTokenEx not found\n");
1582 return;
1585 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
1586 if (!ret)
1588 skip("couldn't open process token, skipping impersonation tests\n");
1589 return;
1592 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
1594 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
1595 CloseHandle(hProcessToken);
1596 return;
1598 CloseHandle(hProcessToken);
1600 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
1601 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1602 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
1603 CloseHandle(hClientToken);
1604 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1605 test_ImpersonateNamedPipeClient(hClientToken,
1606 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
1607 test_static_context);
1608 CloseHandle(hClientToken);
1609 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1610 test_ImpersonateNamedPipeClient(hClientToken,
1611 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1612 FALSE, test_dynamic_context);
1613 CloseHandle(hClientToken);
1614 test_ImpersonateNamedPipeClient(NULL,
1615 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1616 FALSE, test_dynamic_context_no_token);
1618 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1619 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
1620 CloseHandle(hClientToken);
1621 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1622 test_ImpersonateNamedPipeClient(hClientToken,
1623 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
1624 test_static_context_revert);
1625 CloseHandle(hClientToken);
1626 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1627 test_ImpersonateNamedPipeClient(hClientToken,
1628 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1629 TRUE, test_dynamic_context_revert);
1630 CloseHandle(hClientToken);
1633 struct overlapped_server_args
1635 HANDLE pipe_created;
1638 static DWORD CALLBACK overlapped_server(LPVOID arg)
1640 OVERLAPPED ol;
1641 HANDLE pipe;
1642 int ret, err;
1643 struct overlapped_server_args *a = arg;
1644 DWORD num;
1645 char buf[100];
1647 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
1648 ok(pipe != NULL, "pipe NULL\n");
1650 ol.hEvent = CreateEventA(0, 1, 0, 0);
1651 ok(ol.hEvent != NULL, "event NULL\n");
1652 ret = ConnectNamedPipe(pipe, &ol);
1653 err = GetLastError();
1654 ok(ret == 0, "ret %d\n", ret);
1655 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
1656 SetEvent(a->pipe_created);
1658 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
1659 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
1661 ret = GetOverlappedResult(pipe, &ol, &num, 1);
1662 ok(ret == 1, "ret %d\n", ret);
1664 /* This should block */
1665 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
1666 ok(ret == 1, "ret %d\n", ret);
1668 DisconnectNamedPipe(pipe);
1669 CloseHandle(ol.hEvent);
1670 CloseHandle(pipe);
1671 return 1;
1674 static void test_overlapped(void)
1676 DWORD tid, num;
1677 HANDLE thread, pipe;
1678 BOOL ret;
1679 struct overlapped_server_args args;
1681 args.pipe_created = CreateEventA(0, 1, 0, 0);
1682 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
1684 WaitForSingleObject(args.pipe_created, INFINITE);
1685 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1686 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
1688 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
1689 Sleep(1);
1691 ret = WriteFile(pipe, "x", 1, &num, NULL);
1692 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1694 WaitForSingleObject(thread, INFINITE);
1695 CloseHandle(pipe);
1696 CloseHandle(args.pipe_created);
1697 CloseHandle(thread);
1700 static void test_NamedPipeHandleState(void)
1702 HANDLE server, client;
1703 BOOL ret;
1704 DWORD state, instances, maxCollectionCount, collectDataTimeout;
1705 char userName[MAX_PATH];
1707 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1708 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1709 /* nMaxInstances */ 1,
1710 /* nOutBufSize */ 1024,
1711 /* nInBufSize */ 1024,
1712 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1713 /* lpSecurityAttrib */ NULL);
1714 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1715 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
1716 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1717 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
1719 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1720 if (ret)
1722 ok(state == 0, "unexpected state %08x\n", state);
1723 ok(instances == 1, "expected 1 instances, got %d\n", instances);
1725 /* Some parameters have no meaning, and therefore can't be retrieved,
1726 * on a local pipe.
1728 SetLastError(0xdeadbeef);
1729 ret = GetNamedPipeHandleStateA(server, &state, &instances,
1730 &maxCollectionCount, &collectDataTimeout, userName,
1731 sizeof(userName) / sizeof(userName[0]));
1732 todo_wine
1733 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1734 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1735 /* A byte-mode pipe server can't be changed to message mode. */
1736 state = PIPE_READMODE_MESSAGE;
1737 SetLastError(0xdeadbeef);
1738 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1739 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1740 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1742 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1743 OPEN_EXISTING, 0, NULL);
1744 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1746 state = PIPE_READMODE_BYTE;
1747 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1748 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1749 /* A byte-mode pipe client can't be changed to message mode, either. */
1750 state = PIPE_READMODE_MESSAGE;
1751 SetLastError(0xdeadbeef);
1752 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1753 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1754 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1756 CloseHandle(client);
1757 CloseHandle(server);
1759 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1760 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
1761 /* nMaxInstances */ 1,
1762 /* nOutBufSize */ 1024,
1763 /* nInBufSize */ 1024,
1764 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1765 /* lpSecurityAttrib */ NULL);
1766 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1767 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
1768 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1769 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
1771 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1772 if (ret)
1774 ok(state == 0, "unexpected state %08x\n", state);
1775 ok(instances == 1, "expected 1 instances, got %d\n", instances);
1777 /* In contrast to byte-mode pipes, a message-mode pipe server can be
1778 * changed to byte mode.
1780 state = PIPE_READMODE_BYTE;
1781 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1782 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1784 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1785 OPEN_EXISTING, 0, NULL);
1786 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1788 state = PIPE_READMODE_MESSAGE;
1789 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1790 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1791 /* A message-mode pipe client can also be changed to byte mode.
1793 state = PIPE_READMODE_BYTE;
1794 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1795 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1797 CloseHandle(client);
1798 CloseHandle(server);
1801 static void test_readfileex_pending(void)
1803 HANDLE server, client, event;
1804 BOOL ret;
1805 DWORD err, wait, num_bytes;
1806 OVERLAPPED overlapped;
1807 char read_buf[1024];
1808 char write_buf[1024];
1809 const char test_string[] = "test";
1810 int i;
1812 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
1813 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1814 /* nMaxInstances */ 1,
1815 /* nOutBufSize */ 1024,
1816 /* nInBufSize */ 1024,
1817 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1818 /* lpSecurityAttrib */ NULL);
1819 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1821 event = CreateEventA(NULL, TRUE, FALSE, NULL);
1822 ok(event != NULL, "CreateEventA failed\n");
1824 memset(&overlapped, 0, sizeof(overlapped));
1825 overlapped.hEvent = event;
1827 ret = ConnectNamedPipe(server, &overlapped);
1828 err = GetLastError();
1829 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
1830 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
1832 wait = WaitForSingleObject(event, 0);
1833 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
1835 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1836 OPEN_EXISTING, 0, NULL);
1837 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1839 wait = WaitForSingleObject(event, 0);
1840 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1842 /* Start a read that can't complete immediately. */
1843 completion_called = 0;
1844 ResetEvent(event);
1845 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
1846 ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
1847 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
1849 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
1850 ok(ret == TRUE, "WriteFile failed\n");
1851 ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
1853 ok(completion_called == 0, "completion routine called during WriteFile\n");
1855 wait = WaitForSingleObjectEx(event, 0, TRUE);
1856 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
1858 ok(completion_called == 1, "completion not called after writing pipe\n");
1859 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1860 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
1861 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1862 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
1864 /* Make writes until the pipe is full and the write fails */
1865 memset(write_buf, 0xaa, sizeof(write_buf));
1866 for (i=0; i<256; i++)
1868 completion_called = 0;
1869 ResetEvent(event);
1870 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
1871 err = GetLastError();
1873 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
1875 wait = WaitForSingleObjectEx(event, 0, TRUE);
1877 if (wait == WAIT_TIMEOUT)
1878 /* write couldn't complete immediately, presumably the pipe is full */
1879 break;
1881 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1883 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
1884 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1885 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1888 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
1889 ok(completion_called == 0, "completion routine called but wait timed out\n");
1890 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1891 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1893 /* free up some space in the pipe */
1894 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
1895 ok(ret == TRUE, "ReadFile failed\n");
1897 ok(completion_called == 0, "completion routine called during ReadFile\n");
1899 wait = WaitForSingleObjectEx(event, 0, TRUE);
1900 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1901 if (wait == WAIT_TIMEOUT)
1903 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
1904 ok(ret == TRUE, "ReadFile failed\n");
1905 ok(completion_called == 0, "completion routine called during ReadFile\n");
1906 wait = WaitForSingleObjectEx(event, 0, TRUE);
1907 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1910 ok(completion_called == 1, "completion routine not called\n");
1911 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1912 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1914 num_bytes = 0xdeadbeef;
1915 SetLastError(0xdeadbeef);
1916 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
1917 ok(!ret, "ReadFile should fail\n");
1918 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
1919 ok(num_bytes == 0, "expected 0, got %u\n", num_bytes);
1921 S(U(overlapped)).Offset = 0;
1922 S(U(overlapped)).OffsetHigh = 0;
1923 overlapped.Internal = -1;
1924 overlapped.InternalHigh = -1;
1925 overlapped.hEvent = event;
1926 num_bytes = 0xdeadbeef;
1927 SetLastError(0xdeadbeef);
1928 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
1929 todo_wine
1930 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
1931 ok(num_bytes == 0, "bytes %u\n", num_bytes);
1932 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
1933 todo_wine
1934 ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
1936 wait = WaitForSingleObject(event, 100);
1937 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
1939 num_bytes = 0xdeadbeef;
1940 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
1941 ok(ret, "WriteFile failed\n");
1942 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1944 wait = WaitForSingleObject(event, 100);
1945 todo_wine
1946 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1948 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1949 todo_wine
1950 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
1951 ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
1953 /* read the pending byte and clear the pipe */
1954 num_bytes = 0xdeadbeef;
1955 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
1956 ok(ret, "ReadFile failed\n");
1957 ok(num_bytes == 1, "bytes %u\n", num_bytes);
1959 CloseHandle(client);
1960 CloseHandle(server);
1961 CloseHandle(event);
1964 START_TEST(pipe)
1966 HMODULE hmod;
1968 hmod = GetModuleHandleA("advapi32.dll");
1969 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
1970 hmod = GetModuleHandleA("kernel32.dll");
1971 pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
1973 if (test_DisconnectNamedPipe())
1974 return;
1975 test_CreateNamedPipe_instances_must_match();
1976 test_NamedPipe_2();
1977 test_CreateNamedPipe(PIPE_TYPE_BYTE);
1978 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
1979 test_CreatePipe();
1980 test_impersonation();
1981 test_overlapped();
1982 test_NamedPipeHandleState();
1983 test_readfileex_pending();