1 /* Unit test suite for Ntdll NamedPipe API functions 2 * 3 * Copyright 2011 Bernhard Loos 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include <stdio.h> 21 #include <stdarg.h> 22 23 #include "ntstatus.h" 24 #define WIN32_NO_STATUS 25 #include "windef.h" 26 #include "winbase.h" 27 #include "winuser.h" 28 #include "winreg.h" 29 #include "winnls.h" 30 #include "wine/test.h" 31 #include "winternl.h" 32 #include "winioctl.h" 33 34 #ifndef __WINE_WINTERNL_H 35 36 typedef struct { 37 ULONG ReadMode; 38 ULONG CompletionMode; 39 } FILE_PIPE_INFORMATION; 40 41 typedef struct { 42 ULONG NamedPipeType; 43 ULONG NamedPipeConfiguration; 44 ULONG MaximumInstances; 45 ULONG CurrentInstances; 46 ULONG InboundQuota; 47 ULONG ReadDataAvailable; 48 ULONG OutboundQuota; 49 ULONG WriteQuotaAvailable; 50 ULONG NamedPipeState; 51 ULONG NamedPipeEnd; 52 } FILE_PIPE_LOCAL_INFORMATION; 53 54 #ifndef FILE_SYNCHRONOUS_IO_ALERT 55 #define FILE_SYNCHRONOUS_IO_ALERT 0x10 56 #endif 57 58 #ifndef FILE_SYNCHRONOUS_IO_NONALERT 59 #define FILE_SYNCHRONOUS_IO_NONALERT 0x20 60 #endif 61 62 #ifndef FSCTL_PIPE_LISTEN 63 #define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) 64 #endif 65 #endif 66 67 static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size); 68 static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access, 69 POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK iosb, 70 ULONG sharing, ULONG dispo, ULONG options, 71 ULONG pipe_type, ULONG read_mode, 72 ULONG completion_mode, ULONG max_inst, 73 ULONG inbound_quota, ULONG outbound_quota, 74 PLARGE_INTEGER timeout); 75 static NTSTATUS (WINAPI *pNtQueryInformationFile) (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass); 76 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE handle, PIO_STATUS_BLOCK io, void *buffer, ULONG length, FS_INFORMATION_CLASS info_class); 77 static NTSTATUS (WINAPI *pNtSetInformationFile) (HANDLE handle, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class); 78 static NTSTATUS (WINAPI *pNtCancelIoFile) (HANDLE hFile, PIO_STATUS_BLOCK io_status); 79 static NTSTATUS (WINAPI *pNtCancelIoFileEx) (HANDLE hFile, IO_STATUS_BLOCK *iosb, IO_STATUS_BLOCK *io_status); 80 static void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source); 81 82 static HANDLE (WINAPI *pOpenThread)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId); 83 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData); 84 85 86 static BOOL init_func_ptrs(void) 87 { 88 HMODULE module = GetModuleHandleA("ntdll.dll"); 89 90 #define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \ 91 trace("GetProcAddress(%s) failed\n", #name); \ 92 return FALSE; \ 93 } 94 95 loadfunc(NtFsControlFile) 96 loadfunc(NtCreateNamedPipeFile) 97 loadfunc(NtQueryInformationFile) 98 loadfunc(NtQueryVolumeInformationFile) 99 loadfunc(NtSetInformationFile) 100 loadfunc(NtCancelIoFile) 101 loadfunc(RtlInitUnicodeString) 102 103 /* not fatal */ 104 pNtCancelIoFileEx = (void *)GetProcAddress(module, "NtCancelIoFileEx"); 105 module = GetModuleHandleA("kernel32.dll"); 106 pOpenThread = (void *)GetProcAddress(module, "OpenThread"); 107 pQueueUserAPC = (void *)GetProcAddress(module, "QueueUserAPC"); 108 return TRUE; 109 } 110 111 static inline BOOL is_signaled( HANDLE obj ) 112 { 113 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0; 114 } 115 116 static const WCHAR testpipe[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\', 117 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 }; 118 static const WCHAR testpipe_nt[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\', 119 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 }; 120 121 static NTSTATUS create_pipe(PHANDLE handle, ULONG sharing, ULONG options) 122 { 123 IO_STATUS_BLOCK iosb; 124 OBJECT_ATTRIBUTES attr; 125 UNICODE_STRING name; 126 LARGE_INTEGER timeout; 127 NTSTATUS res; 128 129 pRtlInitUnicodeString(&name, testpipe_nt); 130 131 attr.Length = sizeof(attr); 132 attr.RootDirectory = 0; 133 attr.ObjectName = &name; 134 attr.Attributes = 0x40; /*case insensitive */ 135 attr.SecurityDescriptor = NULL; 136 attr.SecurityQualityOfService = NULL; 137 138 timeout.QuadPart = -100000000; 139 140 res = pNtCreateNamedPipeFile(handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, sharing, 2 /*FILE_CREATE*/, 141 options, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout); 142 return res; 143 } 144 145 static BOOL ioapc_called; 146 static void CALLBACK ioapc(void *arg, PIO_STATUS_BLOCK io, ULONG reserved) 147 { 148 ioapc_called = TRUE; 149 } 150 151 static NTSTATUS listen_pipe(HANDLE hPipe, HANDLE hEvent, PIO_STATUS_BLOCK iosb, BOOL use_apc) 152 { 153 int dummy; 154 155 ioapc_called = FALSE; 156 157 return pNtFsControlFile(hPipe, hEvent, use_apc ? &ioapc: NULL, use_apc ? &dummy: NULL, iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0); 158 } 159 160 static void test_create_invalid(void) 161 { 162 IO_STATUS_BLOCK iosb; 163 OBJECT_ATTRIBUTES attr; 164 UNICODE_STRING name; 165 LARGE_INTEGER timeout; 166 NTSTATUS res; 167 HANDLE handle, handle2; 168 FILE_PIPE_LOCAL_INFORMATION info; 169 170 pRtlInitUnicodeString(&name, testpipe_nt); 171 172 attr.Length = sizeof(attr); 173 attr.RootDirectory = 0; 174 attr.ObjectName = &name; 175 attr.Attributes = 0x40; /*case insensitive */ 176 attr.SecurityDescriptor = NULL; 177 attr.SecurityQualityOfService = NULL; 178 179 timeout.QuadPart = -100000000; 180 181 /* create a pipe with FILE_OVERWRITE */ 182 res = pNtCreateNamedPipeFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ, 4 /*FILE_OVERWRITE*/, 183 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout); 184 todo_wine ok(res == STATUS_INVALID_PARAMETER, "NtCreateNamedPipeFile returned %x\n", res); 185 if (!res) 186 CloseHandle(handle); 187 188 /* create a pipe with FILE_OVERWRITE_IF */ 189 res = pNtCreateNamedPipeFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ, 5 /*FILE_OVERWRITE_IF*/, 190 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout); 191 todo_wine ok(res == STATUS_INVALID_PARAMETER, "NtCreateNamedPipeFile returned %x\n", res); 192 if (!res) 193 CloseHandle(handle); 194 195 /* create a pipe with sharing = 0 */ 196 res = pNtCreateNamedPipeFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, 0, 2 /*FILE_CREATE*/, 197 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout); 198 ok(res == STATUS_INVALID_PARAMETER, "NtCreateNamedPipeFile returned %x\n", res); 199 if (!res) 200 CloseHandle(handle); 201 202 /* create a pipe without r/w access */ 203 res = pNtCreateNamedPipeFile(&handle, SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /*FILE_CREATE*/, 204 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout); 205 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 206 207 res = pNtQueryInformationFile(handle, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24); 208 ok(res == STATUS_ACCESS_DENIED, "NtQueryInformationFile returned %x\n", res); 209 210 /* test FILE_CREATE creation disposition */ 211 res = pNtCreateNamedPipeFile(&handle2, SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /*FILE_CREATE*/, 212 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout); 213 todo_wine ok(res == STATUS_ACCESS_DENIED, "NtCreateNamedPipeFile returned %x\n", res); 214 if (!res) 215 CloseHandle(handle2); 216 217 CloseHandle(handle); 218 } 219 220 static void test_create(void) 221 { 222 HANDLE hserver; 223 NTSTATUS res; 224 int j, k; 225 FILE_PIPE_LOCAL_INFORMATION info; 226 IO_STATUS_BLOCK iosb; 227 HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 228 229 static const DWORD access[] = { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE}; 230 static const DWORD sharing[] = { FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE }; 231 static const DWORD pipe_config[]= { 1, 0, 2 }; 232 233 for (j = 0; j < sizeof(sharing) / sizeof(DWORD); j++) { 234 for (k = 0; k < sizeof(access) / sizeof(DWORD); k++) { 235 HANDLE hclient; 236 BOOL should_succeed = TRUE; 237 238 res = create_pipe(&hserver, sharing[j], 0); 239 if (res) { 240 ok(0, "NtCreateNamedPipeFile returned %x, sharing: %x\n", res, sharing[j]); 241 continue; 242 } 243 244 res = listen_pipe(hserver, hEvent, &iosb, FALSE); 245 ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res); 246 247 res = pNtQueryInformationFile(hserver, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24); 248 ok(!res, "NtQueryInformationFile for server returned %x, sharing: %x\n", res, sharing[j]); 249 ok(info.NamedPipeConfiguration == pipe_config[j], "wrong duplex status for pipe: %d, expected %d\n", 250 info.NamedPipeConfiguration, pipe_config[j]); 251 252 hclient = CreateFileW(testpipe, access[k], 0, 0, OPEN_EXISTING, 0, 0); 253 if (hclient != INVALID_HANDLE_VALUE) { 254 res = pNtQueryInformationFile(hclient, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24); 255 ok(!res, "NtQueryInformationFile for client returned %x, access: %x, sharing: %x\n", 256 res, access[k], sharing[j]); 257 ok(info.NamedPipeConfiguration == pipe_config[j], "wrong duplex status for pipe: %d, expected %d\n", 258 info.NamedPipeConfiguration, pipe_config[j]); 259 260 res = listen_pipe(hclient, hEvent, &iosb, FALSE); 261 ok(res == STATUS_ILLEGAL_FUNCTION, "expected STATUS_ILLEGAL_FUNCTION, got %x\n", res); 262 CloseHandle(hclient); 263 } 264 265 if (access[k] & GENERIC_WRITE) 266 should_succeed &= !!(sharing[j] & FILE_SHARE_WRITE); 267 if (access[k] & GENERIC_READ) 268 should_succeed &= !!(sharing[j] & FILE_SHARE_READ); 269 270 if (should_succeed) 271 ok(hclient != INVALID_HANDLE_VALUE, "CreateFile failed for sharing %x, access: %x, GetLastError: %d\n", 272 sharing[j], access[k], GetLastError()); 273 else 274 ok(hclient == INVALID_HANDLE_VALUE, "CreateFile succeeded for sharing %x, access: %x\n", sharing[j], access[k]); 275 276 CloseHandle(hserver); 277 } 278 } 279 CloseHandle(hEvent); 280 } 281 282 static void test_overlapped(void) 283 { 284 IO_STATUS_BLOCK iosb; 285 HANDLE hEvent; 286 HANDLE hPipe; 287 HANDLE hClient; 288 NTSTATUS res; 289 290 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 291 ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError()); 292 293 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */); 294 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 295 296 memset(&iosb, 0x55, sizeof(iosb)); 297 res = listen_pipe(hPipe, hEvent, &iosb, TRUE); 298 ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res); 299 ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status); 300 301 hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 302 ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError: %x\n", GetLastError()); 303 304 ok(U(iosb).Status == 0, "Wrong iostatus %x\n", U(iosb).Status); 305 ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n"); 306 307 ok(!ioapc_called, "IOAPC ran too early\n"); 308 309 SleepEx(0, TRUE); /* alertable wait state */ 310 311 ok(ioapc_called, "IOAPC didn't run\n"); 312 313 CloseHandle(hPipe); 314 CloseHandle(hClient); 315 316 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */); 317 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 318 319 hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 320 ok(hClient != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_PIPE_BUSY) /* > Win 8 */, 321 "can't open pipe, GetLastError: %x\n", GetLastError()); 322 323 if (hClient != INVALID_HANDLE_VALUE) 324 { 325 SetEvent(hEvent); 326 memset(&iosb, 0x55, sizeof(iosb)); 327 res = listen_pipe(hPipe, hEvent, &iosb, TRUE); 328 ok(res == STATUS_PIPE_CONNECTED, "NtFsControlFile returned %x\n", res); 329 ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status); 330 ok(!is_signaled(hEvent), "hEvent not signaled\n"); 331 332 CloseHandle(hClient); 333 } 334 335 CloseHandle(hPipe); 336 CloseHandle(hEvent); 337 } 338 339 static void test_completion(void) 340 { 341 static const char buf[] = "testdata"; 342 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info; 343 HANDLE port, pipe, client; 344 IO_STATUS_BLOCK iosb; 345 OVERLAPPED ov, *pov; 346 IO_STATUS_BLOCK io; 347 NTSTATUS status; 348 DWORD num_bytes; 349 ULONG_PTR key; 350 DWORD dwret; 351 BOOL ret; 352 353 memset(&ov, 0, sizeof(ov)); 354 ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); 355 ok(ov.hEvent != INVALID_HANDLE_VALUE, "CreateEvent failed, error %u\n", GetLastError()); 356 357 status = create_pipe(&pipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */); 358 ok(!status, "NtCreateNamedPipeFile returned %x\n", status); 359 status = listen_pipe(pipe, ov.hEvent, &iosb, FALSE); 360 ok(status == STATUS_PENDING, "NtFsControlFile returned %x\n", status); 361 362 client = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, 363 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); 364 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed, error %u\n", GetLastError()); 365 dwret = WaitForSingleObject(ov.hEvent, 0); 366 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret); 367 368 port = CreateIoCompletionPort(client, NULL, 0xdeadbeef, 0); 369 ok(port != NULL, "CreateIoCompletionPort failed, error %u\n", GetLastError()); 370 371 ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov); 372 ok(ret, "WriteFile failed, error %u\n", GetLastError()); 373 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes); 374 375 key = 0; 376 pov = NULL; 377 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000); 378 ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError()); 379 ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key); 380 ok(pov == &ov, "expected %p, got %p\n", &ov, pov); 381 382 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS; 383 status = pNtSetInformationFile(client, &io, &info, sizeof(info), FileIoCompletionNotificationInformation); 384 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status); 385 386 info.Flags = 0; 387 status = pNtQueryInformationFile(client, &io, &info, sizeof(info), FileIoCompletionNotificationInformation); 388 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status); 389 ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags); 390 391 ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov); 392 ok(ret, "WriteFile failed, error %u\n", GetLastError()); 393 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes); 394 395 pov = (void *)0xdeadbeef; 396 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000); 397 ok(!ret, "GetQueuedCompletionStatus succeeded\n"); 398 ok(pov == NULL, "expected NULL, got %p\n", pov); 399 400 CloseHandle(ov.hEvent); 401 CloseHandle(client); 402 CloseHandle(pipe); 403 CloseHandle(port); 404 } 405 406 static BOOL userapc_called; 407 static void CALLBACK userapc(ULONG_PTR dwParam) 408 { 409 userapc_called = TRUE; 410 } 411 412 static BOOL open_succeeded; 413 static DWORD WINAPI thread(PVOID main_thread) 414 { 415 HANDLE h; 416 417 Sleep(400); 418 419 if (main_thread) { 420 DWORD ret; 421 userapc_called = FALSE; 422 ret = pQueueUserAPC(&userapc, main_thread, 0); 423 ok(ret, "can't queue user apc, GetLastError: %x\n", GetLastError()); 424 CloseHandle(main_thread); 425 } 426 427 Sleep(400); 428 429 h = CreateFileW(testpipe, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); 430 431 if (h != INVALID_HANDLE_VALUE) { 432 open_succeeded = TRUE; 433 Sleep(100); 434 CloseHandle(h); 435 } else 436 open_succeeded = FALSE; 437 438 return 0; 439 } 440 441 static void test_alertable(void) 442 { 443 IO_STATUS_BLOCK iosb; 444 HANDLE hEvent; 445 HANDLE hPipe; 446 NTSTATUS res; 447 HANDLE hThread; 448 DWORD ret; 449 450 memset(&iosb, 0x55, sizeof(iosb)); 451 452 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 453 ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError()); 454 455 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); 456 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 457 458 /* queue an user apc before calling listen */ 459 userapc_called = FALSE; 460 ret = pQueueUserAPC(&userapc, GetCurrentThread(), 0); 461 ok(ret, "can't queue user apc, GetLastError: %x\n", GetLastError()); 462 463 res = listen_pipe(hPipe, hEvent, &iosb, TRUE); 464 todo_wine ok(res == STATUS_CANCELLED, "NtFsControlFile returned %x\n", res); 465 466 todo_wine ok(userapc_called, "user apc didn't run\n"); 467 ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status); 468 todo_wine ok(WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_TIMEOUT, "hEvent signaled\n"); 469 ok(!ioapc_called, "IOAPC ran\n"); 470 471 /* queue an user apc from a different thread */ 472 hThread = CreateThread(NULL, 0, &thread, pOpenThread(MAXIMUM_ALLOWED, FALSE, GetCurrentThreadId()), 0, 0); 473 ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError()); 474 475 /* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state 476 instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */ 477 res = listen_pipe(hPipe, hEvent, &iosb, TRUE); 478 todo_wine ok(res == STATUS_CANCELLED, "NtFsControlFile returned %x\n", res); 479 480 ok(userapc_called, "user apc didn't run\n"); 481 ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status); 482 ok(WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_TIMEOUT, "hEvent signaled\n"); 483 ok(!ioapc_called, "IOAPC ran\n"); 484 485 WaitForSingleObject(hThread, INFINITE); 486 487 SleepEx(0, TRUE); /* get rid of the userapc, if NtFsControlFile failed */ 488 489 ok(open_succeeded, "couldn't open client side pipe\n"); 490 491 CloseHandle(hThread); 492 DisconnectNamedPipe(hPipe); 493 494 /* finally try without an apc */ 495 hThread = CreateThread(NULL, 0, &thread, 0, 0, 0); 496 ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError()); 497 498 res = listen_pipe(hPipe, hEvent, &iosb, TRUE); 499 todo_wine ok(!res, "NtFsControlFile returned %x\n", res); 500 501 ok(open_succeeded, "couldn't open client side pipe\n"); 502 ok(!U(iosb).Status, "Wrong iostatus %x\n", U(iosb).Status); 503 todo_wine ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n"); 504 505 WaitForSingleObject(hThread, INFINITE); 506 CloseHandle(hThread); 507 CloseHandle(hEvent); 508 CloseHandle(hPipe); 509 } 510 511 static void test_nonalertable(void) 512 { 513 IO_STATUS_BLOCK iosb; 514 HANDLE hEvent; 515 HANDLE hPipe; 516 NTSTATUS res; 517 HANDLE hThread; 518 DWORD ret; 519 520 memset(&iosb, 0x55, sizeof(iosb)); 521 522 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 523 ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError()); 524 525 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); 526 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 527 528 hThread = CreateThread(NULL, 0, &thread, 0, 0, 0); 529 ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError()); 530 531 userapc_called = FALSE; 532 ret = pQueueUserAPC(&userapc, GetCurrentThread(), 0); 533 ok(ret, "can't queue user apc, GetLastError: %x\n", GetLastError()); 534 535 res = listen_pipe(hPipe, hEvent, &iosb, TRUE); 536 todo_wine ok(!res, "NtFsControlFile returned %x\n", res); 537 538 ok(open_succeeded, "couldn't open client side pipe\n"); 539 todo_wine ok(!U(iosb).Status, "Wrong iostatus %x\n", U(iosb).Status); 540 todo_wine ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n"); 541 542 ok(!ioapc_called, "IOAPC ran too early\n"); 543 ok(!userapc_called, "user apc ran too early\n"); 544 545 SleepEx(0, TRUE); /* alertable wait state */ 546 547 ok(ioapc_called, "IOAPC didn't run\n"); 548 ok(userapc_called, "user apc didn't run\n"); 549 550 WaitForSingleObject(hThread, INFINITE); 551 CloseHandle(hThread); 552 CloseHandle(hEvent); 553 CloseHandle(hPipe); 554 } 555 556 static void test_cancelio(void) 557 { 558 IO_STATUS_BLOCK iosb; 559 IO_STATUS_BLOCK cancel_sb; 560 HANDLE hEvent; 561 HANDLE hPipe; 562 NTSTATUS res; 563 564 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 565 ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError()); 566 567 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */); 568 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 569 570 memset(&iosb, 0x55, sizeof(iosb)); 571 572 res = listen_pipe(hPipe, hEvent, &iosb, TRUE); 573 ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res); 574 575 res = pNtCancelIoFile(hPipe, &cancel_sb); 576 ok(!res, "NtCancelIoFile returned %x\n", res); 577 578 ok(U(iosb).Status == STATUS_CANCELLED, "Wrong iostatus %x\n", U(iosb).Status); 579 ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n"); 580 581 ok(!ioapc_called, "IOAPC ran too early\n"); 582 583 SleepEx(0, TRUE); /* alertable wait state */ 584 585 ok(ioapc_called, "IOAPC didn't run\n"); 586 587 CloseHandle(hPipe); 588 589 if (pNtCancelIoFileEx) 590 { 591 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */); 592 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 593 594 memset(&iosb, 0x55, sizeof(iosb)); 595 res = listen_pipe(hPipe, hEvent, &iosb, FALSE); 596 ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res); 597 598 res = pNtCancelIoFileEx(hPipe, &iosb, &cancel_sb); 599 ok(!res, "NtCancelIoFileEx returned %x\n", res); 600 601 ok(U(iosb).Status == STATUS_CANCELLED, "Wrong iostatus %x\n", U(iosb).Status); 602 ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n"); 603 604 CloseHandle(hPipe); 605 } 606 else 607 win_skip("NtCancelIoFileEx not available\n"); 608 609 CloseHandle(hEvent); 610 } 611 612 static void _check_pipe_handle_state(int line, HANDLE handle, ULONG read, ULONG completion) 613 { 614 IO_STATUS_BLOCK iosb; 615 FILE_PIPE_INFORMATION fpi; 616 NTSTATUS res; 617 if (handle != INVALID_HANDLE_VALUE) 618 { 619 memset(&fpi, 0x55, sizeof(fpi)); 620 res = pNtQueryInformationFile(handle, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 621 ok_(__FILE__, line)(!res, "NtQueryInformationFile returned %x\n", res); 622 ok_(__FILE__, line)(fpi.ReadMode == read, "Unexpected ReadMode, expected %x, got %x\n", 623 read, fpi.ReadMode); 624 ok_(__FILE__, line)(fpi.CompletionMode == completion, "Unexpected CompletionMode, expected %x, got %x\n", 625 completion, fpi.CompletionMode); 626 } 627 } 628 #define check_pipe_handle_state(handle, r, c) _check_pipe_handle_state(__LINE__, handle, r, c) 629 630 static void test_filepipeinfo(void) 631 { 632 IO_STATUS_BLOCK iosb; 633 OBJECT_ATTRIBUTES attr; 634 UNICODE_STRING name; 635 LARGE_INTEGER timeout; 636 HANDLE hServer, hClient; 637 FILE_PIPE_INFORMATION fpi; 638 NTSTATUS res; 639 640 pRtlInitUnicodeString(&name, testpipe_nt); 641 642 attr.Length = sizeof(attr); 643 attr.RootDirectory = 0; 644 attr.ObjectName = &name; 645 attr.Attributes = 0x40; /* case insensitive */ 646 attr.SecurityDescriptor = NULL; 647 attr.SecurityQualityOfService = NULL; 648 649 timeout.QuadPart = -100000000; 650 651 /* test with INVALID_HANDLE_VALUE */ 652 res = pNtQueryInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 653 ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtQueryInformationFile returned %x\n", res); 654 655 fpi.ReadMode = 0; 656 fpi.CompletionMode = 0; 657 res = pNtSetInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 658 ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtSetInformationFile returned %x\n", res); 659 660 /* server end with read-only attributes */ 661 res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, 662 FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE */, 663 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout); 664 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 665 666 check_pipe_handle_state(hServer, 0, 1); 667 668 hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 669 ok(hClient != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_PIPE_BUSY) /* > Win 8 */, 670 "can't open pipe, GetLastError: %x\n", GetLastError()); 671 672 check_pipe_handle_state(hServer, 0, 1); 673 check_pipe_handle_state(hClient, 0, 0); 674 675 fpi.ReadMode = 0; 676 fpi.CompletionMode = 0; 677 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 678 ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res); 679 680 check_pipe_handle_state(hServer, 0, 1); 681 check_pipe_handle_state(hClient, 0, 0); 682 683 fpi.ReadMode = 1; /* invalid on a byte stream pipe */ 684 fpi.CompletionMode = 1; 685 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 686 ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res); 687 688 check_pipe_handle_state(hServer, 0, 1); 689 check_pipe_handle_state(hClient, 0, 0); 690 691 if (hClient != INVALID_HANDLE_VALUE) 692 { 693 fpi.ReadMode = 1; /* invalid on a byte stream pipe */ 694 fpi.CompletionMode = 1; 695 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 696 ok(res == STATUS_INVALID_PARAMETER, "NtSetInformationFile returned %x\n", res); 697 } 698 699 check_pipe_handle_state(hServer, 0, 1); 700 check_pipe_handle_state(hClient, 0, 0); 701 702 if (hClient != INVALID_HANDLE_VALUE) 703 { 704 fpi.ReadMode = 0; 705 fpi.CompletionMode = 1; 706 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 707 ok(!res, "NtSetInformationFile returned %x\n", res); 708 } 709 710 check_pipe_handle_state(hServer, 0, 1); 711 check_pipe_handle_state(hClient, 0, 1); 712 713 if (hClient != INVALID_HANDLE_VALUE) 714 { 715 fpi.ReadMode = 0; 716 fpi.CompletionMode = 2; /* not in range 0-1 */ 717 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 718 ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res); 719 720 fpi.ReadMode = 2; /* not in range 0-1 */ 721 fpi.CompletionMode = 0; 722 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 723 ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res); 724 } 725 726 CloseHandle(hClient); 727 728 check_pipe_handle_state(hServer, 0, 1); 729 730 fpi.ReadMode = 0; 731 fpi.CompletionMode = 0; 732 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 733 ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res); 734 735 CloseHandle(hServer); 736 737 /* message mode server with read/write attributes */ 738 res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, 739 FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE */, 740 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout); 741 ok(!res, "NtCreateNamedPipeFile returned %x\n", res); 742 743 check_pipe_handle_state(hServer, 1, 0); 744 745 hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); 746 ok(hClient != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_PIPE_BUSY) /* > Win 8 */, 747 "can't open pipe, GetLastError: %x\n", GetLastError()); 748 749 check_pipe_handle_state(hServer, 1, 0); 750 check_pipe_handle_state(hClient, 0, 0); 751 752 if (hClient != INVALID_HANDLE_VALUE) 753 { 754 fpi.ReadMode = 1; 755 fpi.CompletionMode = 1; 756 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 757 ok(!res, "NtSetInformationFile returned %x\n", res); 758 } 759 760 check_pipe_handle_state(hServer, 1, 0); 761 check_pipe_handle_state(hClient, 1, 1); 762 763 fpi.ReadMode = 0; 764 fpi.CompletionMode = 1; 765 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 766 ok(!res, "NtSetInformationFile returned %x\n", res); 767 768 check_pipe_handle_state(hServer, 0, 1); 769 check_pipe_handle_state(hClient, 1, 1); 770 771 if (hClient != INVALID_HANDLE_VALUE) 772 { 773 fpi.ReadMode = 0; 774 fpi.CompletionMode = 2; /* not in range 0-1 */ 775 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 776 ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res); 777 778 fpi.ReadMode = 2; /* not in range 0-1 */ 779 fpi.CompletionMode = 0; 780 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 781 ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res); 782 } 783 784 CloseHandle(hClient); 785 786 check_pipe_handle_state(hServer, 0, 1); 787 788 fpi.ReadMode = 1; 789 fpi.CompletionMode = 0; 790 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); 791 ok(!res, "NtSetInformationFile returned %x\n", res); 792 793 check_pipe_handle_state(hServer, 1, 0); 794 795 CloseHandle(hServer); 796 } 797 798 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved ) 799 { 800 int *count = arg; 801 (*count)++; 802 ok( !reserved, "reserved is not 0: %x\n", reserved ); 803 } 804 805 static void test_peek(HANDLE pipe) 806 { 807 FILE_PIPE_PEEK_BUFFER buf; 808 IO_STATUS_BLOCK iosb; 809 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL ); 810 NTSTATUS status; 811 812 memset(&iosb, 0x55, sizeof(iosb)); 813 status = NtFsControlFile(pipe, NULL, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0, &buf, sizeof(buf)); 814 ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status); 815 ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status); 816 ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable); 817 818 ResetEvent(event); 819 memset(&iosb, 0x55, sizeof(iosb)); 820 status = NtFsControlFile(pipe, event, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0, &buf, sizeof(buf)); 821 ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status); 822 ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable); 823 ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status); 824 ok(is_signaled(event), "event is not signaled\n"); 825 826 CloseHandle(event); 827 } 828 829 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_pipe.c" 830 831 static BOOL create_pipe_pair( HANDLE *read, HANDLE *write, ULONG flags, ULONG type, ULONG size ) 832 { 833 const BOOL server_reader = flags & PIPE_ACCESS_INBOUND; 834 HANDLE client, server; 835 836 server = CreateNamedPipeA(PIPENAME, flags, PIPE_WAIT | type, 837 1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL); 838 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n"); 839 840 client = CreateFileA(PIPENAME, server_reader ? GENERIC_WRITE : GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, 841 NULL, OPEN_EXISTING, flags & FILE_FLAG_OVERLAPPED, 0); 842 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError()); 843 844 if(server_reader) 845 { 846 *read = server; 847 *write = client; 848 } 849 else 850 { 851 if(type & PIPE_READMODE_MESSAGE) 852 { 853 DWORD read_mode = PIPE_READMODE_MESSAGE; 854 ok(SetNamedPipeHandleState(client, &read_mode, NULL, NULL), "Change mode\n"); 855 } 856 857 *read = client; 858 *write = server; 859 } 860 return TRUE; 861 } 862 863 static void read_pipe_test(ULONG pipe_flags, ULONG pipe_type) 864 { 865 IO_STATUS_BLOCK iosb, iosb2; 866 HANDLE handle, read, write; 867 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL ); 868 int apc_count = 0; 869 char buffer[128]; 870 DWORD written; 871 BOOL ret; 872 NTSTATUS status; 873 874 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return; 875 876 /* try read with no data */ 877 U(iosb).Status = 0xdeadbabe; 878 iosb.Information = 0xdeadbeef; 879 ok( is_signaled( read ), "read handle is not signaled\n" ); 880 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); 881 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 882 ok( !is_signaled( read ), "read handle is signaled\n" ); 883 ok( !is_signaled( event ), "event is signaled\n" ); 884 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 885 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 886 ok( !apc_count, "apc was called\n" ); 887 ret = WriteFile( write, buffer, 1, &written, NULL ); 888 ok(ret && written == 1, "WriteFile error %d\n", GetLastError()); 889 /* iosb updated here by async i/o */ 890 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status ); 891 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information ); 892 ok( !is_signaled( read ), "read handle is signaled\n" ); 893 ok( is_signaled( event ), "event is not signaled\n" ); 894 ok( !apc_count, "apc was called\n" ); 895 apc_count = 0; 896 SleepEx( 1, FALSE ); /* non-alertable sleep */ 897 ok( !apc_count, "apc was called\n" ); 898 SleepEx( 1, TRUE ); /* alertable sleep */ 899 ok( apc_count == 1, "apc not called\n" ); 900 901 /* with no event, the pipe handle itself gets signaled */ 902 apc_count = 0; 903 U(iosb).Status = 0xdeadbabe; 904 iosb.Information = 0xdeadbeef; 905 ok( !is_signaled( read ), "read handle is signaled\n" ); 906 status = NtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); 907 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 908 ok( !is_signaled( read ), "read handle is signaled\n" ); 909 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 910 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 911 ok( !apc_count, "apc was called\n" ); 912 ret = WriteFile( write, buffer, 1, &written, NULL ); 913 ok(ret && written == 1, "WriteFile error %d\n", GetLastError()); 914 /* iosb updated here by async i/o */ 915 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status ); 916 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information ); 917 ok( is_signaled( read ), "read handle is not signaled\n" ); 918 ok( !apc_count, "apc was called\n" ); 919 apc_count = 0; 920 SleepEx( 1, FALSE ); /* non-alertable sleep */ 921 ok( !apc_count, "apc was called\n" ); 922 SleepEx( 1, TRUE ); /* alertable sleep */ 923 ok( apc_count == 1, "apc not called\n" ); 924 925 /* now read with data ready */ 926 apc_count = 0; 927 U(iosb).Status = 0xdeadbabe; 928 iosb.Information = 0xdeadbeef; 929 ResetEvent( event ); 930 ret = WriteFile( write, buffer, 1, &written, NULL ); 931 ok(ret && written == 1, "WriteFile error %d\n", GetLastError()); 932 933 test_peek(read); 934 935 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); 936 ok( status == STATUS_SUCCESS, "wrong status %x\n", status ); 937 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status ); 938 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information ); 939 ok( is_signaled( event ), "event is not signaled\n" ); 940 ok( !apc_count, "apc was called\n" ); 941 SleepEx( 1, FALSE ); /* non-alertable sleep */ 942 ok( !apc_count, "apc was called\n" ); 943 SleepEx( 1, TRUE ); /* alertable sleep */ 944 ok( apc_count == 1, "apc not called\n" ); 945 946 /* now partial read with data ready */ 947 apc_count = 0; 948 U(iosb).Status = 0xdeadbabe; 949 iosb.Information = 0xdeadbeef; 950 ResetEvent( event ); 951 ret = WriteFile( write, buffer, 2, &written, NULL ); 952 ok(ret && written == 2, "WriteFile error %d\n", GetLastError()); 953 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); 954 if (pipe_type & PIPE_READMODE_MESSAGE) 955 { 956 ok( status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", status ); 957 ok( U(iosb).Status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", U(iosb).Status ); 958 } 959 else 960 { 961 ok( status == STATUS_SUCCESS, "wrong status %x\n", status ); 962 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status ); 963 } 964 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information ); 965 ok( is_signaled( event ), "event is not signaled\n" ); 966 ok( !apc_count, "apc was called\n" ); 967 SleepEx( 1, FALSE ); /* non-alertable sleep */ 968 ok( !apc_count, "apc was called\n" ); 969 SleepEx( 1, TRUE ); /* alertable sleep */ 970 ok( apc_count == 1, "apc not called\n" ); 971 apc_count = 0; 972 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); 973 ok( status == STATUS_SUCCESS, "wrong status %x\n", status ); 974 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status ); 975 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information ); 976 ok( is_signaled( event ), "event is not signaled\n" ); 977 ok( !apc_count, "apc was called\n" ); 978 SleepEx( 1, FALSE ); /* non-alertable sleep */ 979 ok( !apc_count, "apc was called\n" ); 980 SleepEx( 1, TRUE ); /* alertable sleep */ 981 ok( apc_count == 1, "apc not called\n" ); 982 983 /* try read with no data */ 984 apc_count = 0; 985 U(iosb).Status = 0xdeadbabe; 986 iosb.Information = 0xdeadbeef; 987 ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */ 988 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL ); 989 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 990 ok( !is_signaled( event ), "event is signaled\n" ); 991 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 992 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 993 ok( !apc_count, "apc was called\n" ); 994 ret = WriteFile( write, buffer, 1, &written, NULL ); 995 ok(ret && written == 1, "WriteFile error %d\n", GetLastError()); 996 /* partial read is good enough */ 997 Sleep(1); /* FIXME: needed for wine to run the i/o apc */ 998 ok( is_signaled( event ), "event is not signaled\n" ); 999 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status ); 1000 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information ); 1001 ok( !apc_count, "apc was called\n" ); 1002 SleepEx( 1, TRUE ); /* alertable sleep */ 1003 ok( apc_count == 1, "apc was not called\n" ); 1004 1005 /* read from disconnected pipe */ 1006 apc_count = 0; 1007 U(iosb).Status = 0xdeadbabe; 1008 iosb.Information = 0xdeadbeef; 1009 CloseHandle( write ); 1010 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); 1011 ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status ); 1012 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1013 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1014 ok( !is_signaled( event ), "event is signaled\n" ); 1015 ok( !apc_count, "apc was called\n" ); 1016 SleepEx( 1, TRUE ); /* alertable sleep */ 1017 ok( !apc_count, "apc was called\n" ); 1018 CloseHandle( read ); 1019 1020 /* read from disconnected pipe, with invalid event handle */ 1021 apc_count = 0; 1022 U(iosb).Status = 0xdeadbabe; 1023 iosb.Information = 0xdeadbeef; 1024 status = NtReadFile( read, (HANDLE)0xdeadbeef, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); 1025 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status ); 1026 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1027 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1028 ok( !apc_count, "apc was called\n" ); 1029 SleepEx( 1, TRUE ); /* alertable sleep */ 1030 ok( !apc_count, "apc was called\n" ); 1031 CloseHandle( read ); 1032 1033 /* read from closed handle */ 1034 apc_count = 0; 1035 U(iosb).Status = 0xdeadbabe; 1036 iosb.Information = 0xdeadbeef; 1037 SetEvent( event ); 1038 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); 1039 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status ); 1040 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1041 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1042 ok( is_signaled( event ), "event is not signaled\n" ); /* not reset on invalid handle */ 1043 ok( !apc_count, "apc was called\n" ); 1044 SleepEx( 1, TRUE ); /* alertable sleep */ 1045 ok( !apc_count, "apc was called\n" ); 1046 1047 /* disconnect while async read is in progress */ 1048 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return; 1049 apc_count = 0; 1050 U(iosb).Status = 0xdeadbabe; 1051 iosb.Information = 0xdeadbeef; 1052 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL ); 1053 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 1054 ok( !is_signaled( event ), "event is signaled\n" ); 1055 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1056 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1057 ok( !apc_count, "apc was called\n" ); 1058 CloseHandle( write ); 1059 Sleep(1); /* FIXME: needed for wine to run the i/o apc */ 1060 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status ); 1061 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information ); 1062 ok( is_signaled( event ), "event is not signaled\n" ); 1063 ok( !apc_count, "apc was called\n" ); 1064 SleepEx( 1, TRUE ); /* alertable sleep */ 1065 ok( apc_count == 1, "apc was not called\n" ); 1066 CloseHandle( read ); 1067 1068 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return; 1069 ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS); 1070 ok(ret, "Failed to duplicate handle: %d\n", GetLastError()); 1071 1072 apc_count = 0; 1073 U(iosb).Status = 0xdeadbabe; 1074 iosb.Information = 0xdeadbeef; 1075 status = NtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL ); 1076 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 1077 ok( !is_signaled( event ), "event is signaled\n" ); 1078 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1079 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1080 ok( !apc_count, "apc was called\n" ); 1081 /* Cancel by other handle */ 1082 status = pNtCancelIoFile( read, &iosb2 ); 1083 ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status); 1084 Sleep(1); /* FIXME: needed for wine to run the i/o apc */ 1085 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status ); 1086 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information ); 1087 ok( is_signaled( event ), "event is not signaled\n" ); 1088 ok( !apc_count, "apc was called\n" ); 1089 SleepEx( 1, TRUE ); /* alertable sleep */ 1090 ok( apc_count == 1, "apc was not called\n" ); 1091 1092 apc_count = 0; 1093 U(iosb).Status = 0xdeadbabe; 1094 iosb.Information = 0xdeadbeef; 1095 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL ); 1096 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 1097 ok( !is_signaled( event ), "event is signaled\n" ); 1098 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1099 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1100 ok( !apc_count, "apc was called\n" ); 1101 /* Close queued handle */ 1102 CloseHandle( read ); 1103 SleepEx( 1, TRUE ); /* alertable sleep */ 1104 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1105 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1106 status = pNtCancelIoFile( read, &iosb2 ); 1107 ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n"); 1108 status = pNtCancelIoFile( handle, &iosb2 ); 1109 ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status); 1110 Sleep(1); /* FIXME: needed for wine to run the i/o apc */ 1111 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status ); 1112 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information ); 1113 ok( is_signaled( event ), "event is not signaled\n" ); 1114 ok( !apc_count, "apc was called\n" ); 1115 SleepEx( 1, TRUE ); /* alertable sleep */ 1116 ok( apc_count == 1, "apc was not called\n" ); 1117 CloseHandle( handle ); 1118 CloseHandle( write ); 1119 1120 if (pNtCancelIoFileEx) 1121 { 1122 /* Basic Cancel Ex */ 1123 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return; 1124 1125 apc_count = 0; 1126 U(iosb).Status = 0xdeadbabe; 1127 iosb.Information = 0xdeadbeef; 1128 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL ); 1129 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 1130 ok( !is_signaled( event ), "event is signaled\n" ); 1131 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1132 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1133 ok( !apc_count, "apc was called\n" ); 1134 status = pNtCancelIoFileEx( read, &iosb, &iosb2 ); 1135 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n"); 1136 Sleep(1); /* FIXME: needed for wine to run the i/o apc */ 1137 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status ); 1138 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information ); 1139 ok( is_signaled( event ), "event is not signaled\n" ); 1140 ok( !apc_count, "apc was called\n" ); 1141 SleepEx( 1, TRUE ); /* alertable sleep */ 1142 ok( apc_count == 1, "apc was not called\n" ); 1143 1144 /* Duplicate iosb */ 1145 apc_count = 0; 1146 U(iosb).Status = 0xdeadbabe; 1147 iosb.Information = 0xdeadbeef; 1148 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL ); 1149 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 1150 ok( !is_signaled( event ), "event is signaled\n" ); 1151 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1152 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1153 ok( !apc_count, "apc was called\n" ); 1154 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL ); 1155 ok( status == STATUS_PENDING, "wrong status %x\n", status ); 1156 ok( !is_signaled( event ), "event is signaled\n" ); 1157 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status ); 1158 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information ); 1159 ok( !apc_count, "apc was called\n" ); 1160 status = pNtCancelIoFileEx( read, &iosb, &iosb2 ); 1161 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n"); 1162 Sleep(1); /* FIXME: needed for wine to run the i/o apc */ 1163 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status ); 1164 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information ); 1165 ok( is_signaled( event ), "event is not signaled\n" ); 1166 ok( !apc_count, "apc was called\n" ); 1167 SleepEx( 1, TRUE ); /* alertable sleep */ 1168 ok( apc_count == 2, "apc was not called\n" ); 1169 1170 CloseHandle( read ); 1171 CloseHandle( write ); 1172 } 1173 else 1174 win_skip("NtCancelIoFileEx not available\n"); 1175 1176 CloseHandle(event); 1177 } 1178 1179 static void test_volume_info(void) 1180 { 1181 FILE_FS_DEVICE_INFORMATION *device_info; 1182 IO_STATUS_BLOCK iosb; 1183 HANDLE read, write; 1184 char buffer[128]; 1185 NTSTATUS status; 1186 1187 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND, 1188 PIPE_TYPE_MESSAGE, 4096 )) return; 1189 1190 memset( buffer, 0xaa, sizeof(buffer) ); 1191 status = pNtQueryVolumeInformationFile( read, &iosb, buffer, sizeof(buffer), FileFsDeviceInformation ); 1192 ok( status == STATUS_SUCCESS, "NtQueryVolumeInformationFile failed: %x\n", status ); 1193 ok( iosb.Information == sizeof(*device_info), "Information = %lu\n", iosb.Information ); 1194 device_info = (FILE_FS_DEVICE_INFORMATION*)buffer; 1195 ok( device_info->DeviceType == FILE_DEVICE_NAMED_PIPE, "DeviceType = %u\n", device_info->DeviceType ); 1196 ok( !(device_info->Characteristics & ~FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL), 1197 "Characteristics = %x\n", device_info->Characteristics ); 1198 1199 memset( buffer, 0xaa, sizeof(buffer) ); 1200 status = pNtQueryVolumeInformationFile( write, &iosb, buffer, sizeof(buffer), FileFsDeviceInformation ); 1201 ok( status == STATUS_SUCCESS, "NtQueryVolumeInformationFile failed: %x\n", status ); 1202 ok( iosb.Information == sizeof(*device_info), "Information = %lu\n", iosb.Information ); 1203 device_info = (FILE_FS_DEVICE_INFORMATION*)buffer; 1204 ok( device_info->DeviceType == FILE_DEVICE_NAMED_PIPE, "DeviceType = %u\n", device_info->DeviceType ); 1205 ok( !(device_info->Characteristics & ~FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL), 1206 "Characteristics = %x\n", device_info->Characteristics ); 1207 1208 CloseHandle( read ); 1209 CloseHandle( write ); 1210 } 1211 1212 #define test_file_name_fail(a,b) _test_file_name_fail(__LINE__,a,b) 1213 static void _test_file_name_fail(unsigned line, HANDLE pipe, NTSTATUS expected_status) 1214 { 1215 char buffer[512]; 1216 IO_STATUS_BLOCK iosb; 1217 NTSTATUS status; 1218 1219 status = NtQueryInformationFile( pipe, &iosb, buffer, sizeof(buffer), FileNameInformation ); 1220 ok_(__FILE__,line)( status == expected_status, "NtQueryInformationFile failed: %x, expected %x\n", 1221 status, expected_status ); 1222 } 1223 1224 #define test_file_name(a) _test_file_name(__LINE__,a) 1225 static void _test_file_name(unsigned line, HANDLE pipe) 1226 { 1227 char buffer[512]; 1228 FILE_NAME_INFORMATION *name_info = (FILE_NAME_INFORMATION*)buffer; 1229 IO_STATUS_BLOCK iosb; 1230 NTSTATUS status; 1231 1232 static const WCHAR nameW[] = 1233 {'\\','n','t','d','l','l','_','t','e','s','t','s','_','p','i','p','e','.','c'}; 1234 1235 memset( buffer, 0xaa, sizeof(buffer) ); 1236 memset( &iosb, 0xaa, sizeof(iosb) ); 1237 status = NtQueryInformationFile( pipe, &iosb, buffer, sizeof(buffer), FileNameInformation ); 1238 ok_(__FILE__,line)( status == STATUS_SUCCESS, "NtQueryInformationFile failed: %x\n", status ); 1239 ok_(__FILE__,line)( iosb.Status == STATUS_SUCCESS, "Status = %x\n", iosb.Status ); 1240 ok_(__FILE__,line)( iosb.Information == sizeof(name_info->FileNameLength) + sizeof(nameW), 1241 "Information = %lu\n", iosb.Information ); 1242 ok( name_info->FileNameLength == sizeof(nameW), "FileNameLength = %u\n", name_info->FileNameLength ); 1243 ok( !memcmp(name_info->FileName, nameW, sizeof(nameW)), "FileName = %s\n", wine_dbgstr_w(name_info->FileName) ); 1244 1245 /* too small buffer */ 1246 memset( buffer, 0xaa, sizeof(buffer) ); 1247 memset( &iosb, 0xaa, sizeof(iosb) ); 1248 status = NtQueryInformationFile( pipe, &iosb, buffer, 20, FileNameInformation ); 1249 ok( status == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile failed: %x\n", status ); 1250 ok( iosb.Status == STATUS_BUFFER_OVERFLOW, "Status = %x\n", iosb.Status ); 1251 ok( iosb.Information == 20, "Information = %lu\n", iosb.Information ); 1252 ok( name_info->FileNameLength == sizeof(nameW), "FileNameLength = %u\n", name_info->FileNameLength ); 1253 ok( !memcmp(name_info->FileName, nameW, 16), "FileName = %s\n", wine_dbgstr_w(name_info->FileName) ); 1254 1255 /* too small buffer */ 1256 memset( buffer, 0xaa, sizeof(buffer) ); 1257 memset( &iosb, 0xaa, sizeof(iosb) ); 1258 status = NtQueryInformationFile( pipe, &iosb, buffer, 4, FileNameInformation ); 1259 ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile failed: %x\n", status ); 1260 } 1261 1262 static void test_file_info(void) 1263 { 1264 HANDLE server, client; 1265 1266 if (!create_pipe_pair( &server, &client, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND, 1267 PIPE_TYPE_MESSAGE, 4096 )) return; 1268 1269 test_file_name( client ); 1270 test_file_name( server ); 1271 1272 DisconnectNamedPipe( server ); 1273 test_file_name_fail( client, STATUS_PIPE_DISCONNECTED ); 1274 1275 CloseHandle( server ); 1276 CloseHandle( client ); 1277 } 1278 1279 static PSECURITY_DESCRIPTOR get_security_descriptor(HANDLE handle, BOOL todo) 1280 { 1281 SECURITY_DESCRIPTOR *sec_desc; 1282 ULONG length = 0; 1283 NTSTATUS status; 1284 1285 status = NtQuerySecurityObject(handle, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, 1286 NULL, 0, &length); 1287 todo_wine_if(todo && status == STATUS_PIPE_DISCONNECTED) 1288 ok(status == STATUS_BUFFER_TOO_SMALL, 1289 "Failed to query object security descriptor length: %08x\n", status); 1290 if(status != STATUS_BUFFER_TOO_SMALL) return NULL; 1291 ok(length != 0, "length = 0\n"); 1292 1293 sec_desc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, length); 1294 status = NtQuerySecurityObject(handle, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, 1295 sec_desc, length, &length); 1296 ok(status == STATUS_SUCCESS, "Failed to query object security descriptor: %08x\n", status); 1297 1298 return sec_desc; 1299 } 1300 1301 static TOKEN_OWNER *get_current_owner(void) 1302 { 1303 TOKEN_OWNER *owner; 1304 ULONG length = 0; 1305 HANDLE token; 1306 BOOL ret; 1307 1308 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token); 1309 ok(ret, "Failed to get process token: %u\n", GetLastError()); 1310 1311 ret = GetTokenInformation(token, TokenOwner, NULL, 0, &length); 1312 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 1313 "GetTokenInformation failed: %u\n", GetLastError()); 1314 ok(length != 0, "Failed to get token owner information length: %u\n", GetLastError()); 1315 1316 owner = HeapAlloc(GetProcessHeap(), 0, length); 1317 ret = GetTokenInformation(token, TokenOwner, owner, length, &length); 1318 ok(ret, "Failed to get token owner information: %u)\n", GetLastError()); 1319 1320 CloseHandle(token); 1321 return owner; 1322 } 1323 1324 static TOKEN_PRIMARY_GROUP *get_current_group(void) 1325 { 1326 TOKEN_PRIMARY_GROUP *group; 1327 ULONG length = 0; 1328 HANDLE token; 1329 BOOL ret; 1330 1331 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token); 1332 ok(ret, "Failed to get process token: %u\n", GetLastError()); 1333 1334 ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &length); 1335 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, 1336 "GetTokenInformation failed: %u\n", GetLastError()); 1337 ok(length != 0, "Failed to get primary group token information length: %u\n", GetLastError()); 1338 1339 group = HeapAlloc(GetProcessHeap(), 0, length); 1340 ret = GetTokenInformation(token, TokenPrimaryGroup, group, length, &length); 1341 ok(ret, "Failed to get primary group token information: %u\n", GetLastError()); 1342 1343 CloseHandle(token); 1344 return group; 1345 } 1346 1347 static SID *well_known_sid(WELL_KNOWN_SID_TYPE sid_type) 1348 { 1349 DWORD size = SECURITY_MAX_SID_SIZE; 1350 SID *sid; 1351 BOOL ret; 1352 1353 sid = HeapAlloc(GetProcessHeap(), 0, size); 1354 ret = CreateWellKnownSid(sid_type, NULL, sid, &size); 1355 ok(ret, "CreateWellKnownSid failed: %u\n", GetLastError()); 1356 return sid; 1357 } 1358 1359 #define test_group(a,b,c) _test_group(__LINE__,a,b,c) 1360 static void _test_group(unsigned line, HANDLE handle, SID *expected_sid, BOOL todo) 1361 { 1362 SECURITY_DESCRIPTOR *sec_desc; 1363 BOOLEAN defaulted; 1364 PSID group_sid; 1365 NTSTATUS status; 1366 1367 sec_desc = get_security_descriptor(handle, todo); 1368 if (!sec_desc) return; 1369 1370 status = RtlGetGroupSecurityDescriptor(sec_desc, &group_sid, &defaulted); 1371 ok_(__FILE__,line)(status == STATUS_SUCCESS, 1372 "Failed to query group from security descriptor: %08x\n", status); 1373 todo_wine_if(todo) 1374 ok_(__FILE__,line)(EqualSid(group_sid, expected_sid), "SIDs are not equal\n"); 1375 1376 HeapFree(GetProcessHeap(), 0, sec_desc); 1377 } 1378 1379 static void test_security_info(void) 1380 { 1381 char sec_desc[SECURITY_DESCRIPTOR_MIN_LENGTH]; 1382 TOKEN_PRIMARY_GROUP *process_group; 1383 SECURITY_ATTRIBUTES sec_attr; 1384 TOKEN_OWNER *process_owner; 1385 HANDLE server, client, server2; 1386 SID *world_sid, *local_sid; 1387 ULONG length; 1388 NTSTATUS status; 1389 BOOL ret; 1390 1391 trace("security tests...\n"); 1392 1393 process_owner = get_current_owner(); 1394 process_group = get_current_group(); 1395 world_sid = well_known_sid(WinWorldSid); 1396 local_sid = well_known_sid(WinLocalSid); 1397 1398 ret = InitializeSecurityDescriptor(sec_desc, SECURITY_DESCRIPTOR_REVISION); 1399 ok(ret, "InitializeSecurityDescriptor failed\n"); 1400 1401 ret = SetSecurityDescriptorOwner(sec_desc, process_owner->Owner, FALSE); 1402 ok(ret, "SetSecurityDescriptorOwner failed\n"); 1403 1404 ret = SetSecurityDescriptorGroup(sec_desc, process_group->PrimaryGroup, FALSE); 1405 ok(ret, "SetSecurityDescriptorGroup failed\n"); 1406 1407 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | WRITE_OWNER, PIPE_TYPE_BYTE, 10, 1408 0x20000, 0x20000, 0, NULL); 1409 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError()); 1410 1411 client = CreateFileA(PIPENAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL); 1412 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); 1413 1414 test_group(server, process_group->PrimaryGroup, TRUE); 1415 test_group(client, process_group->PrimaryGroup, TRUE); 1416 1417 /* set server group, client changes as well */ 1418 ret = SetSecurityDescriptorGroup(sec_desc, world_sid, FALSE); 1419 ok(ret, "SetSecurityDescriptorGroup failed\n"); 1420 status = NtSetSecurityObject(server, GROUP_SECURITY_INFORMATION, sec_desc); 1421 ok(status == STATUS_SUCCESS, "NtSetSecurityObject failed: %08x\n", status); 1422 1423 test_group(server, world_sid, FALSE); 1424 test_group(client, world_sid, FALSE); 1425 1426 /* new instance of pipe server has the same security descriptor */ 1427 server2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 10, 1428 0x20000, 0x20000, 0, NULL); 1429 ok(server2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError()); 1430 test_group(server2, world_sid, FALSE); 1431 1432 /* set client group, server changes as well */ 1433 ret = SetSecurityDescriptorGroup(sec_desc, local_sid, FALSE); 1434 ok(ret, "SetSecurityDescriptorGroup failed\n"); 1435 status = NtSetSecurityObject(server, GROUP_SECURITY_INFORMATION, sec_desc); 1436 ok(status == STATUS_SUCCESS, "NtSetSecurityObject failed: %08x\n", status); 1437 1438 test_group(server, local_sid, FALSE); 1439 test_group(client, local_sid, FALSE); 1440 test_group(server2, local_sid, FALSE); 1441 1442 CloseHandle(server); 1443 /* SD is preserved after closing server object */ 1444 test_group(client, local_sid, TRUE); 1445 CloseHandle(client); 1446 1447 server = server2; 1448 client = CreateFileA(PIPENAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL); 1449 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); 1450 1451 test_group(client, local_sid, FALSE); 1452 1453 ret = DisconnectNamedPipe(server); 1454 ok(ret, "DisconnectNamedPipe failed: %u\n", GetLastError()); 1455 1456 /* disconnected server may be queried for security info, but client does not */ 1457 test_group(server, local_sid, FALSE); 1458 status = NtQuerySecurityObject(client, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, 1459 NULL, 0, &length); 1460 ok(status == STATUS_PIPE_DISCONNECTED, "NtQuerySecurityObject returned %08x\n", status); 1461 status = NtSetSecurityObject(client, GROUP_SECURITY_INFORMATION, sec_desc); 1462 ok(status == STATUS_PIPE_DISCONNECTED, "NtQuerySecurityObject returned %08x\n", status); 1463 1464 /* attempting to create another pipe instance with specified sd fails */ 1465 sec_attr.nLength = sizeof(sec_attr); 1466 sec_attr.lpSecurityDescriptor = sec_desc; 1467 sec_attr.bInheritHandle = FALSE; 1468 ret = SetSecurityDescriptorGroup(sec_desc, local_sid, FALSE); 1469 ok(ret, "SetSecurityDescriptorGroup failed\n"); 1470 server2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | WRITE_OWNER, PIPE_TYPE_BYTE, 10, 1471 0x20000, 0x20000, 0, &sec_attr); 1472 todo_wine 1473 ok(server2 == INVALID_HANDLE_VALUE && GetLastError() == ERROR_ACCESS_DENIED, 1474 "CreateNamedPipe failed: %u\n", GetLastError()); 1475 if (server2 != INVALID_HANDLE_VALUE) CloseHandle(server2); 1476 1477 CloseHandle(server); 1478 CloseHandle(client); 1479 1480 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | WRITE_OWNER, PIPE_TYPE_BYTE, 10, 1481 0x20000, 0x20000, 0, &sec_attr); 1482 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError()); 1483 test_group(server, local_sid, FALSE); 1484 CloseHandle(server); 1485 1486 HeapFree(GetProcessHeap(), 0, process_owner); 1487 HeapFree(GetProcessHeap(), 0, process_group); 1488 HeapFree(GetProcessHeap(), 0, world_sid); 1489 HeapFree(GetProcessHeap(), 0, local_sid); 1490 } 1491 1492 START_TEST(pipe) 1493 { 1494 if (!init_func_ptrs()) 1495 return; 1496 1497 trace("starting invalid create tests\n"); 1498 test_create_invalid(); 1499 1500 trace("starting create tests\n"); 1501 test_create(); 1502 1503 trace("starting overlapped tests\n"); 1504 test_overlapped(); 1505 1506 trace("starting completion tests\n"); 1507 test_completion(); 1508 1509 trace("starting FILE_PIPE_INFORMATION tests\n"); 1510 test_filepipeinfo(); 1511 1512 if (!pOpenThread || !pQueueUserAPC) 1513 return; 1514 1515 trace("starting alertable tests\n"); 1516 test_alertable(); 1517 1518 trace("starting nonalertable tests\n"); 1519 test_nonalertable(); 1520 1521 trace("starting cancelio tests\n"); 1522 test_cancelio(); 1523 1524 trace("starting byte read in byte mode client -> server\n"); 1525 read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE); 1526 trace("starting byte read in message mode client -> server\n"); 1527 read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE); 1528 trace("starting message read in message mode client -> server\n"); 1529 read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE); 1530 trace("starting byte read in byte mode server -> client\n"); 1531 read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE); 1532 trace("starting byte read in message mode server -> client\n"); 1533 read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE); 1534 trace("starting message read in message mode server -> client\n"); 1535 read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE); 1536 1537 test_volume_info(); 1538 test_file_info(); 1539 test_security_info(); 1540 } 1541