2003-02-19 23:06:36 +01:00
/*
* Unit tests for named pipe functions in Wine
*
* Copyright ( c ) 2002 Dan Kegel
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
2006-05-18 14:49:52 +02:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
2003-02-19 23:06:36 +01:00
*/
2003-09-06 01:08:26 +02:00
# include <stdarg.h>
2003-02-19 23:06:36 +01:00
# include <stdio.h>
2003-09-06 01:08:26 +02:00
2013-09-18 08:54:32 +02:00
# include "ntstatus.h"
# define WIN32_NO_STATUS
2013-10-21 10:02:23 +02:00
# include "windef.h"
# include "winbase.h"
# include "winternl.h"
2017-05-22 13:40:58 +02:00
# include "winioctl.h"
2005-05-25 11:54:51 +02:00
# include "wine/test.h"
2004-05-24 21:06:52 +02:00
# define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
2003-02-19 23:06:36 +01:00
2004-05-04 02:43:46 +02:00
# define NB_SERVER_LOOPS 8
static HANDLE alarm_event ;
2007-03-16 22:37:46 +01:00
static BOOL ( WINAPI * pDuplicateTokenEx ) ( HANDLE , DWORD , LPSECURITY_ATTRIBUTES ,
SECURITY_IMPERSONATION_LEVEL , TOKEN_TYPE , PHANDLE ) ;
2017-03-23 15:42:47 +01:00
static BOOL ( WINAPI * pCancelIoEx ) ( HANDLE handle , LPOVERLAPPED lpOverlapped ) ;
2018-04-11 14:32:56 +02:00
static BOOL ( WINAPI * pGetNamedPipeClientProcessId ) ( HANDLE , ULONG * ) ;
static BOOL ( WINAPI * pGetNamedPipeServerProcessId ) ( HANDLE , ULONG * ) ;
2018-04-11 14:32:57 +02:00
static BOOL ( WINAPI * pGetNamedPipeClientSessionId ) ( HANDLE , ULONG * ) ;
static BOOL ( WINAPI * pGetNamedPipeServerSessionId ) ( HANDLE , ULONG * ) ;
2019-11-29 01:19:21 +01:00
static BOOL ( WINAPI * pGetOverlappedResultEx ) ( HANDLE , OVERLAPPED * , DWORD * , DWORD , BOOL ) ;
2007-03-16 22:37:46 +01:00
2011-08-22 11:02:51 +02:00
static BOOL user_apc_ran ;
static void CALLBACK user_apc ( ULONG_PTR param )
{
user_apc_ran = TRUE ;
}
2004-05-04 02:43:46 +02:00
2014-09-04 17:24:12 +02:00
enum rpcThreadOp
{
RPC_READFILE
} ;
struct rpcThreadArgs
{
ULONG_PTR returnValue ;
DWORD lastError ;
enum rpcThreadOp op ;
ULONG_PTR args [ 5 ] ;
} ;
static DWORD CALLBACK rpcThreadMain ( LPVOID arg )
{
struct rpcThreadArgs * rpcargs = ( struct rpcThreadArgs * ) arg ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " rpcThreadMain starting \n " ) ;
2014-09-04 17:24:12 +02:00
SetLastError ( rpcargs - > lastError ) ;
switch ( rpcargs - > op )
{
case RPC_READFILE :
rpcargs - > returnValue = ( ULONG_PTR ) ReadFile ( ( HANDLE ) rpcargs - > args [ 0 ] , /* hFile */
( LPVOID ) rpcargs - > args [ 1 ] , /* buffer */
( DWORD ) rpcargs - > args [ 2 ] , /* bytesToRead */
( LPDWORD ) rpcargs - > args [ 3 ] , /* bytesRead */
( LPOVERLAPPED ) rpcargs - > args [ 4 ] ) ; /* overlapped */
break ;
default :
SetLastError ( ERROR_CALL_NOT_IMPLEMENTED ) ;
rpcargs - > returnValue = 0 ;
break ;
}
rpcargs - > lastError = GetLastError ( ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " rpcThreadMain returning \n " ) ;
2014-09-04 17:24:12 +02:00
return 0 ;
}
/* Runs ReadFile(...) from a different thread */
static BOOL RpcReadFile ( HANDLE hFile , LPVOID buffer , DWORD bytesToRead , LPDWORD bytesRead , LPOVERLAPPED overlapped )
{
struct rpcThreadArgs rpcargs ;
HANDLE thread ;
2015-01-20 23:56:41 +01:00
DWORD threadId , ret ;
2014-09-04 17:24:12 +02:00
rpcargs . returnValue = 0 ;
rpcargs . lastError = GetLastError ( ) ;
rpcargs . op = RPC_READFILE ;
rpcargs . args [ 0 ] = ( ULONG_PTR ) hFile ;
rpcargs . args [ 1 ] = ( ULONG_PTR ) buffer ;
rpcargs . args [ 2 ] = ( ULONG_PTR ) bytesToRead ;
rpcargs . args [ 3 ] = ( ULONG_PTR ) bytesRead ;
rpcargs . args [ 4 ] = ( ULONG_PTR ) overlapped ;
thread = CreateThread ( NULL , 0 , rpcThreadMain , ( void * ) & rpcargs , 0 , & threadId ) ;
ok ( thread ! = NULL , " CreateThread failed. %d \n " , GetLastError ( ) ) ;
2015-01-20 23:56:41 +01:00
ret = WaitForSingleObject ( thread , INFINITE ) ;
ok ( ret = = WAIT_OBJECT_0 , " WaitForSingleObject failed with %d. \n " , GetLastError ( ) ) ;
2014-09-04 17:24:12 +02:00
CloseHandle ( thread ) ;
SetLastError ( rpcargs . lastError ) ;
return ( BOOL ) rpcargs . returnValue ;
}
2017-03-23 15:42:47 +01:00
# define test_not_signaled(h) _test_not_signaled(__LINE__,h)
static void _test_not_signaled ( unsigned line , HANDLE handle )
{
DWORD res = WaitForSingleObject ( handle , 0 ) ;
ok_ ( __FILE__ , line ) ( res = = WAIT_TIMEOUT , " WaitForSingleObject returned %u (%u) \n " , res , GetLastError ( ) ) ;
}
2016-12-02 13:37:59 +01:00
# define test_signaled(h) _test_signaled(__LINE__,h)
static void _test_signaled ( unsigned line , HANDLE handle )
{
DWORD res = WaitForSingleObject ( handle , 0 ) ;
ok_ ( __FILE__ , line ) ( res = = WAIT_OBJECT_0 , " WaitForSingleObject returned %u \n " , res ) ;
}
2017-03-30 14:02:49 +02:00
# define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
static void _test_pipe_info ( unsigned line , HANDLE pipe , DWORD ex_flags , DWORD ex_out_buf_size , DWORD ex_in_buf_size , DWORD ex_max_instances )
{
DWORD flags = 0xdeadbeef , out_buf_size = 0xdeadbeef , in_buf_size = 0xdeadbeef , max_instances = 0xdeadbeef ;
BOOL res ;
res = GetNamedPipeInfo ( pipe , & flags , & out_buf_size , & in_buf_size , & max_instances ) ;
ok_ ( __FILE__ , line ) ( res , " GetNamedPipeInfo failed: %x \n " , res ) ;
ok_ ( __FILE__ , line ) ( flags = = ex_flags , " flags = %x, expected %x \n " , flags , ex_flags ) ;
ok_ ( __FILE__ , line ) ( out_buf_size = = ex_out_buf_size , " out_buf_size = %x, expected %u \n " , out_buf_size , ex_out_buf_size ) ;
ok_ ( __FILE__ , line ) ( in_buf_size = = ex_in_buf_size , " in_buf_size = %x, expected %u \n " , in_buf_size , ex_in_buf_size ) ;
ok_ ( __FILE__ , line ) ( max_instances = = ex_max_instances , " max_instances = %x, expected %u \n " , max_instances , ex_max_instances ) ;
}
2018-08-20 19:29:16 +02:00
# define test_file_access(a,b) _test_file_access(__LINE__,a,b)
static void _test_file_access ( unsigned line , HANDLE handle , DWORD expected_access )
{
FILE_ACCESS_INFORMATION info ;
IO_STATUS_BLOCK io ;
NTSTATUS status ;
memset ( & info , 0x11 , sizeof ( info ) ) ;
status = NtQueryInformationFile ( handle , & io , & info , sizeof ( info ) , FileAccessInformation ) ;
ok_ ( __FILE__ , line ) ( status = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08x \n " , status ) ;
ok_ ( __FILE__ , line ) ( info . AccessFlags = = expected_access , " got access %08x expected %08x \n " ,
info . AccessFlags , expected_access ) ;
}
2004-12-13 22:19:01 +01:00
static void test_CreateNamedPipe ( int pipemode )
2003-02-19 23:06:36 +01:00
{
HANDLE hnp ;
HANDLE hFile ;
2004-05-04 06:13:05 +02:00
static const char obuf [ ] = " Bit Bucket " ;
static const char obuf2 [ ] = " More bits " ;
2004-04-27 01:30:51 +02:00
char ibuf [ 32 ] , * pbuf ;
2003-02-19 23:06:36 +01:00
DWORD written ;
2003-05-16 00:52:41 +02:00
DWORD readden ;
2004-04-27 01:30:51 +02:00
DWORD avail ;
2017-05-21 15:53:52 +02:00
DWORD left ;
2004-04-27 01:30:51 +02:00
DWORD lpmode ;
2011-01-11 20:30:00 +01:00
BOOL ret ;
2003-02-19 23:06:36 +01:00
2004-04-27 01:30:51 +02:00
if ( pipemode = = PIPE_TYPE_BYTE )
trace ( " test_CreateNamedPipe starting in byte mode \n " ) ;
else
trace ( " test_CreateNamedPipe starting in message mode \n " ) ;
2014-05-31 02:44:36 +02:00
2014-09-28 23:53:46 +02:00
/* Wait for nonexistent pipe */
2014-05-31 02:44:36 +02:00
ret = WaitNamedPipeA ( PIPENAME , 2000 ) ;
2014-09-28 23:53:46 +02:00
ok ( ret = = 0 , " WaitNamedPipe returned %d for nonexistent pipe \n " , ret ) ;
2014-05-31 02:44:36 +02:00
ok ( GetLastError ( ) = = ERROR_FILE_NOT_FOUND , " wrong error %u \n " , GetLastError ( ) ) ;
2003-02-19 23:06:36 +01:00
/* Bad parameter checks */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( " not a named pipe " , PIPE_ACCESS_DUPLEX , pipemode | PIPE_WAIT ,
2003-02-19 23:06:36 +01:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( hnp = = INVALID_HANDLE_VALUE & & GetLastError ( ) = = ERROR_INVALID_NAME ,
2004-02-06 06:24:34 +01:00
" CreateNamedPipe should fail if name doesn't start with \\ \\ . \\ pipe \n " ) ;
2003-02-19 23:06:36 +01:00
2011-10-12 14:50:40 +02:00
if ( pipemode = = PIPE_TYPE_BYTE )
{
/* Bad parameter checks */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE ,
2011-10-12 14:50:40 +02:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( hnp = = INVALID_HANDLE_VALUE & & GetLastError ( ) = = ERROR_INVALID_PARAMETER ,
" CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE \n " ) ;
}
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( NULL ,
2004-04-27 01:30:51 +02:00
PIPE_ACCESS_DUPLEX , pipemode | PIPE_WAIT ,
2003-02-19 23:06:36 +01:00
1 , 1024 , 1024 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( hnp = = INVALID_HANDLE_VALUE & & GetLastError ( ) = = ERROR_PATH_NOT_FOUND ,
2004-02-06 06:24:34 +01:00
" CreateNamedPipe should fail if name is NULL \n " ) ;
2003-02-19 23:06:36 +01:00
2003-05-16 00:52:41 +02:00
hFile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hFile = = INVALID_HANDLE_VALUE
& & GetLastError ( ) = = ERROR_FILE_NOT_FOUND ,
2004-02-06 06:24:34 +01:00
" connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND \n " ) ;
2003-02-25 04:56:43 +01:00
2003-02-19 23:06:36 +01:00
/* Functional checks */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , pipemode | PIPE_WAIT ,
2003-05-16 00:52:41 +02:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2016-12-02 13:37:59 +01:00
test_signaled ( hnp ) ;
2003-05-16 00:52:41 +02:00
2018-08-20 19:29:16 +02:00
test_file_access ( hnp , SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
| FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES
| FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA ) ;
2017-10-04 15:17:35 +02:00
ret = PeekNamedPipe ( hnp , NULL , 0 , NULL , & readden , NULL ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_BAD_PIPE , " PeekNamedPipe returned %x (%u) \n " ,
ret , GetLastError ( ) ) ;
2011-01-11 20:30:00 +01:00
ret = WaitNamedPipeA ( PIPENAME , 2000 ) ;
ok ( ret , " WaitNamedPipe failed (%d) \n " , GetLastError ( ) ) ;
2005-12-05 13:09:35 +01:00
2003-05-16 00:52:41 +02:00
hFile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
2007-01-04 10:54:10 +01:00
ok ( hFile ! = INVALID_HANDLE_VALUE , " CreateFile failed (%d) \n " , GetLastError ( ) ) ;
2003-05-16 00:52:41 +02:00
2017-05-11 13:49:01 +02:00
ok ( ! WaitNamedPipeA ( PIPENAME , 100 ) , " WaitNamedPipe succeeded \n " ) ;
2011-01-11 20:30:00 +01:00
2007-04-17 22:07:07 +02:00
ok ( GetLastError ( ) = = ERROR_SEM_TIMEOUT , " wrong error %u \n " , GetLastError ( ) ) ;
2017-10-10 18:40:43 +02:00
/* Test ConnectNamedPipe() in both directions */
ok ( ! ConnectNamedPipe ( hnp , NULL ) , " ConnectNamedPipe(server) succeeded \n " ) ;
ok ( GetLastError ( ) = = ERROR_PIPE_CONNECTED , " expected ERROR_PIPE_CONNECTED, got %u \n " , GetLastError ( ) ) ;
ok ( ! ConnectNamedPipe ( hFile , NULL ) , " ConnectNamedPipe(client) succeeded \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_FUNCTION , " expected ERROR_INVALID_FUNCTION, got %u \n " , GetLastError ( ) ) ;
2003-05-16 00:52:41 +02:00
/* don't try to do i/o if one side couldn't be opened, as it hangs */
if ( hFile ! = INVALID_HANDLE_VALUE ) {
HANDLE hFile2 ;
/* Make sure we can read and write a few bytes in both directions */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
2004-02-06 06:24:34 +01:00
ok ( WriteFile ( hnp , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile \n " ) ;
2014-09-04 17:06:12 +02:00
ok ( written = = sizeof ( obuf ) , " write file len \n " ) ;
ok ( ReadFile ( hFile , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
ok ( readden = = sizeof ( obuf ) , " read got %d bytes \n " , readden ) ;
ok ( memcmp ( obuf , ibuf , written ) = = 0 , " content check \n " ) ;
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hFile , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len \n " ) ;
ok ( ReadFile ( hnp , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
ok ( readden = = sizeof ( obuf2 ) , " read got %d bytes \n " , readden ) ;
ok ( memcmp ( obuf2 , ibuf , written ) = = 0 , " content check \n " ) ;
/* Now the same again, but with an additional call to PeekNamedPipe */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hnp , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile \n " ) ;
2004-04-27 01:30:51 +02:00
ok ( written = = sizeof ( obuf ) , " write file len 1 \n " ) ;
2017-05-21 15:53:52 +02:00
ok ( PeekNamedPipe ( hFile , NULL , 0 , NULL , & avail , & left ) , " Peek \n " ) ;
ok ( avail = = sizeof ( obuf ) , " peek 1 got %d bytes \n " , avail ) ;
if ( pipemode = = PIPE_TYPE_BYTE )
ok ( left = = 0 , " peek 1 got %d bytes left \n " , left ) ;
else
ok ( left = = sizeof ( obuf ) , " peek 1 got %d bytes left \n " , left ) ;
2004-04-27 01:30:51 +02:00
ok ( ReadFile ( hFile , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
2006-10-10 01:06:48 +02:00
ok ( readden = = sizeof ( obuf ) , " read 1 got %d bytes \n " , readden ) ;
2004-04-27 01:30:51 +02:00
ok ( memcmp ( obuf , ibuf , written ) = = 0 , " content 1 check \n " ) ;
2003-05-16 00:52:41 +02:00
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
2004-04-27 01:30:51 +02:00
ok ( WriteFile ( hFile , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len 2 \n " ) ;
2017-05-21 15:53:52 +02:00
ok ( PeekNamedPipe ( hnp , NULL , 0 , NULL , & avail , & left ) , " Peek \n " ) ;
ok ( avail = = sizeof ( obuf2 ) , " peek 2 got %d bytes \n " , avail ) ;
if ( pipemode = = PIPE_TYPE_BYTE )
ok ( left = = 0 , " peek 2 got %d bytes left \n " , left ) ;
else
ok ( left = = sizeof ( obuf2 ) , " peek 2 got %d bytes left \n " , left ) ;
ok ( PeekNamedPipe ( hnp , ( LPVOID ) 1 , 0 , NULL , & avail , & left ) , " Peek \n " ) ;
ok ( avail = = sizeof ( obuf2 ) , " peek 2 got %d bytes \n " , avail ) ;
if ( pipemode = = PIPE_TYPE_BYTE )
ok ( left = = 0 , " peek 2 got %d bytes left \n " , left ) ;
else
ok ( left = = sizeof ( obuf2 ) , " peek 2 got %d bytes left \n " , left ) ;
2004-04-27 01:30:51 +02:00
ok ( ReadFile ( hnp , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
2006-10-10 01:06:48 +02:00
ok ( readden = = sizeof ( obuf2 ) , " read 2 got %d bytes \n " , readden ) ;
2004-04-27 01:30:51 +02:00
ok ( memcmp ( obuf2 , ibuf , written ) = = 0 , " content 2 check \n " ) ;
2014-09-04 17:14:19 +02:00
/* Test how ReadFile behaves when the buffer is not big enough for the whole message */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hnp , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len \n " ) ;
2017-05-21 15:53:52 +02:00
ok ( PeekNamedPipe ( hFile , ibuf , 4 , & readden , & avail , & left ) , " Peek \n " ) ;
ok ( readden = = 4 , " peek got %d bytes \n " , readden ) ;
ok ( avail = = sizeof ( obuf2 ) , " peek got %d bytes available \n " , avail ) ;
if ( pipemode = = PIPE_TYPE_BYTE )
ok ( left = = - 4 , " peek got %d bytes left \n " , left ) ;
else
ok ( left = = sizeof ( obuf2 ) - 4 , " peek got %d bytes left \n " , left ) ;
2014-09-04 17:14:19 +02:00
ok ( ReadFile ( hFile , ibuf , 4 , & readden , NULL ) , " ReadFile \n " ) ;
ok ( readden = = 4 , " read got %d bytes \n " , readden ) ;
ok ( ReadFile ( hFile , ibuf + 4 , sizeof ( ibuf ) - 4 , & readden , NULL ) , " ReadFile \n " ) ;
ok ( readden = = sizeof ( obuf2 ) - 4 , " read got %d bytes \n " , readden ) ;
ok ( memcmp ( obuf2 , ibuf , written ) = = 0 , " content check \n " ) ;
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hFile , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len \n " ) ;
2017-05-21 15:53:52 +02:00
ok ( PeekNamedPipe ( hnp , ibuf , 4 , & readden , & avail , & left ) , " Peek \n " ) ;
ok ( readden = = 4 , " peek got %d bytes \n " , readden ) ;
ok ( avail = = sizeof ( obuf ) , " peek got %d bytes available \n " , avail ) ;
2014-09-04 17:14:19 +02:00
if ( pipemode = = PIPE_TYPE_BYTE )
{
2017-05-21 15:53:52 +02:00
ok ( left = = - 4 , " peek got %d bytes left \n " , left ) ;
2014-09-04 17:14:19 +02:00
ok ( ReadFile ( hnp , ibuf , 4 , & readden , NULL ) , " ReadFile \n " ) ;
}
else
{
2017-05-21 15:53:52 +02:00
ok ( left = = sizeof ( obuf ) - 4 , " peek got %d bytes left \n " , left ) ;
2014-09-04 17:14:19 +02:00
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hnp , ibuf , 4 , & readden , NULL ) , " ReadFile \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error \n " ) ;
}
ok ( readden = = 4 , " read got %d bytes \n " , readden ) ;
ok ( ReadFile ( hnp , ibuf + 4 , sizeof ( ibuf ) - 4 , & readden , NULL ) , " ReadFile \n " ) ;
ok ( readden = = sizeof ( obuf ) - 4 , " read got %d bytes \n " , readden ) ;
ok ( memcmp ( obuf , ibuf , written ) = = 0 , " content check \n " ) ;
/* Similar to above, but use a read buffer size small enough to read in three parts */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hFile , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len \n " ) ;
if ( pipemode = = PIPE_TYPE_BYTE )
{
ok ( ReadFile ( hnp , ibuf , 4 , & readden , NULL ) , " ReadFile \n " ) ;
ok ( readden = = 4 , " read got %d bytes \n " , readden ) ;
ok ( ReadFile ( hnp , ibuf + 4 , 4 , & readden , NULL ) , " ReadFile \n " ) ;
}
else
{
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hnp , ibuf , 4 , & readden , NULL ) , " ReadFile \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error \n " ) ;
ok ( readden = = 4 , " read got %d bytes \n " , readden ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hnp , ibuf + 4 , 4 , & readden , NULL ) , " ReadFile \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error \n " ) ;
}
ok ( readden = = 4 , " read got %d bytes \n " , readden ) ;
ok ( ReadFile ( hnp , ibuf + 8 , sizeof ( ibuf ) - 8 , & readden , NULL ) , " ReadFile \n " ) ;
ok ( readden = = sizeof ( obuf2 ) - 8 , " read got %d bytes \n " , readden ) ;
ok ( memcmp ( obuf2 , ibuf , written ) = = 0 , " content check \n " ) ;
2004-04-27 01:30:51 +02:00
/* Test reading of multiple writes */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hnp , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile3a \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len 3a \n " ) ;
ok ( WriteFile ( hnp , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile3b \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len 3b \n " ) ;
2017-05-21 15:53:52 +02:00
ok ( PeekNamedPipe ( hFile , ibuf , 4 , & readden , & avail , & left ) , " Peek3 \n " ) ;
ok ( readden = = 4 , " peek3 got %d bytes \n " , readden ) ;
if ( pipemode = = PIPE_TYPE_BYTE )
ok ( left = = - 4 , " peek3 got %d bytes left \n " , left ) ;
else
ok ( left = = sizeof ( obuf ) - 4 , " peek3 got %d bytes left \n " , left ) ;
ok ( avail = = sizeof ( obuf ) + sizeof ( obuf2 ) , " peek3 got %d bytes available \n " , avail ) ;
ok ( PeekNamedPipe ( hFile , ibuf , sizeof ( ibuf ) , & readden , & avail , & left ) , " Peek3 \n " ) ;
2004-04-27 01:30:51 +02:00
if ( pipemode = = PIPE_TYPE_BYTE ) {
2017-10-05 14:30:56 +02:00
ok ( readden = = sizeof ( obuf ) + sizeof ( obuf2 ) , " peek3 got %d bytes \n " , readden ) ;
2017-05-21 15:53:52 +02:00
ok ( left = = ( DWORD ) - ( sizeof ( obuf ) + sizeof ( obuf2 ) ) , " peek3 got %d bytes left \n " , left ) ;
2004-04-27 01:30:51 +02:00
}
else
2006-11-09 15:40:36 +01:00
{
2017-03-23 15:42:25 +01:00
ok ( readden = = sizeof ( obuf ) , " peek3 got %d bytes \n " , readden ) ;
2017-05-21 15:53:52 +02:00
ok ( left = = 0 , " peek3 got %d bytes left \n " , left ) ;
2006-11-09 15:40:36 +01:00
}
2014-07-30 18:00:19 +02:00
ok ( avail = = sizeof ( obuf ) + sizeof ( obuf2 ) , " peek3 got %d bytes available \n " , avail ) ;
2004-04-27 01:30:51 +02:00
pbuf = ibuf ;
ok ( memcmp ( obuf , pbuf , sizeof ( obuf ) ) = = 0 , " pipe content 3a check \n " ) ;
2006-11-09 15:40:36 +01:00
if ( pipemode = = PIPE_TYPE_BYTE & & readden > = sizeof ( obuf ) + sizeof ( obuf2 ) ) {
pbuf + = sizeof ( obuf ) ;
ok ( memcmp ( obuf2 , pbuf , sizeof ( obuf2 ) ) = = 0 , " pipe content 3b check \n " ) ;
2004-04-27 01:30:51 +02:00
}
ok ( ReadFile ( hFile , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
2006-10-10 01:06:48 +02:00
ok ( readden = = sizeof ( obuf ) + sizeof ( obuf2 ) , " read 3 got %d bytes \n " , readden ) ;
2004-04-27 01:30:51 +02:00
pbuf = ibuf ;
ok ( memcmp ( obuf , pbuf , sizeof ( obuf ) ) = = 0 , " content 3a check \n " ) ;
pbuf + = sizeof ( obuf ) ;
ok ( memcmp ( obuf2 , pbuf , sizeof ( obuf2 ) ) = = 0 , " content 3b check \n " ) ;
/* Multiple writes in the reverse direction */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hFile , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile4a \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len 4a \n " ) ;
ok ( WriteFile ( hFile , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile4b \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len 4b \n " ) ;
2017-05-21 15:53:52 +02:00
ok ( PeekNamedPipe ( hnp , ibuf , 4 , & readden , & avail , & left ) , " Peek3 \n " ) ;
ok ( readden = = 4 , " peek3 got %d bytes \n " , readden ) ;
if ( pipemode = = PIPE_TYPE_BYTE )
ok ( left = = - 4 , " peek3 got %d bytes left \n " , left ) ;
else
ok ( left = = sizeof ( obuf ) - 4 , " peek3 got %d bytes left \n " , left ) ;
ok ( avail = = sizeof ( obuf ) + sizeof ( obuf2 ) , " peek3 got %d bytes available \n " , avail ) ;
ok ( PeekNamedPipe ( hnp , ibuf , sizeof ( ibuf ) , & readden , & avail , & left ) , " Peek4 \n " ) ;
2004-04-27 01:30:51 +02:00
if ( pipemode = = PIPE_TYPE_BYTE ) {
2017-10-05 14:30:56 +02:00
ok ( readden = = sizeof ( obuf ) + sizeof ( obuf2 ) , " peek4 got %d bytes \n " , readden ) ;
2017-05-21 15:53:52 +02:00
ok ( left = = ( DWORD ) - ( sizeof ( obuf ) + sizeof ( obuf2 ) ) , " peek4 got %d bytes left \n " , left ) ;
2004-04-27 01:30:51 +02:00
}
else
2006-11-09 15:40:36 +01:00
{
2017-03-23 15:42:25 +01:00
ok ( readden = = sizeof ( obuf ) , " peek4 got %d bytes \n " , readden ) ;
2017-05-21 15:53:52 +02:00
ok ( left = = 0 , " peek4 got %d bytes left \n " , left ) ;
2006-11-09 15:40:36 +01:00
}
2014-07-30 18:00:19 +02:00
ok ( avail = = sizeof ( obuf ) + sizeof ( obuf2 ) , " peek4 got %d bytes available \n " , avail ) ;
2004-04-27 01:30:51 +02:00
pbuf = ibuf ;
ok ( memcmp ( obuf , pbuf , sizeof ( obuf ) ) = = 0 , " pipe content 4a check \n " ) ;
2006-11-09 15:40:36 +01:00
if ( pipemode = = PIPE_TYPE_BYTE & & readden > = sizeof ( obuf ) + sizeof ( obuf2 ) ) {
pbuf + = sizeof ( obuf ) ;
ok ( memcmp ( obuf2 , pbuf , sizeof ( obuf2 ) ) = = 0 , " pipe content 4b check \n " ) ;
2004-04-27 01:30:51 +02:00
}
ok ( ReadFile ( hnp , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
if ( pipemode = = PIPE_TYPE_BYTE ) {
2006-10-10 01:06:48 +02:00
ok ( readden = = sizeof ( obuf ) + sizeof ( obuf2 ) , " read 4 got %d bytes \n " , readden ) ;
2004-04-27 01:30:51 +02:00
}
else {
2017-03-26 12:52:39 +02:00
ok ( readden = = sizeof ( obuf ) , " read 4 got %d bytes \n " , readden ) ;
2004-04-27 01:30:51 +02:00
}
pbuf = ibuf ;
ok ( memcmp ( obuf , pbuf , sizeof ( obuf ) ) = = 0 , " content 4a check \n " ) ;
if ( pipemode = = PIPE_TYPE_BYTE ) {
pbuf + = sizeof ( obuf ) ;
ok ( memcmp ( obuf2 , pbuf , sizeof ( obuf2 ) ) = = 0 , " content 4b check \n " ) ;
}
/* Test reading of multiple writes after a mode change
( CreateFile always creates a byte mode pipe ) */
lpmode = PIPE_READMODE_MESSAGE ;
if ( pipemode = = PIPE_TYPE_BYTE ) {
/* trying to change the client end of a byte pipe to message mode should fail */
ok ( ! SetNamedPipeHandleState ( hFile , & lpmode , NULL , NULL ) , " Change mode \n " ) ;
}
else {
2014-08-21 05:41:15 +02:00
ok ( SetNamedPipeHandleState ( hFile , & lpmode , NULL , NULL ) , " Change mode \n " ) ;
2004-04-27 01:30:51 +02:00
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hnp , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile5a \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len 3a \n " ) ;
ok ( WriteFile ( hnp , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile5b \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len 3b \n " ) ;
2017-05-21 15:53:52 +02:00
ok ( PeekNamedPipe ( hFile , ibuf , sizeof ( ibuf ) , & readden , & avail , & left ) , " Peek5 \n " ) ;
2017-03-23 15:42:25 +01:00
ok ( readden = = sizeof ( obuf ) , " peek5 got %d bytes \n " , readden ) ;
2014-07-30 18:00:19 +02:00
ok ( avail = = sizeof ( obuf ) + sizeof ( obuf2 ) , " peek5 got %d bytes available \n " , avail ) ;
2017-05-21 15:53:52 +02:00
ok ( left = = 0 , " peek5 got %d bytes left \n " , left ) ;
2004-04-27 01:30:51 +02:00
pbuf = ibuf ;
ok ( memcmp ( obuf , pbuf , sizeof ( obuf ) ) = = 0 , " content 5a check \n " ) ;
ok ( ReadFile ( hFile , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
2017-03-26 12:52:39 +02:00
ok ( readden = = sizeof ( obuf ) , " read 5 got %d bytes \n " , readden ) ;
2004-04-27 01:30:51 +02:00
pbuf = ibuf ;
ok ( memcmp ( obuf , pbuf , sizeof ( obuf ) ) = = 0 , " content 5a check \n " ) ;
2014-09-04 17:10:45 +02:00
if ( readden < = sizeof ( obuf ) )
ok ( ReadFile ( hFile , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
2004-04-27 01:30:51 +02:00
/* Multiple writes in the reverse direction */
/* the write of obuf2 from write4 should still be in the buffer */
ok ( PeekNamedPipe ( hnp , ibuf , sizeof ( ibuf ) , & readden , & avail , NULL ) , " Peek6a \n " ) ;
2017-03-26 12:52:39 +02:00
ok ( readden = = sizeof ( obuf2 ) , " peek6a got %d bytes \n " , readden ) ;
ok ( avail = = sizeof ( obuf2 ) , " peek6a got %d bytes available \n " , avail ) ;
2004-04-27 01:30:51 +02:00
if ( avail > 0 ) {
ok ( ReadFile ( hnp , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
2006-10-10 01:06:48 +02:00
ok ( readden = = sizeof ( obuf2 ) , " read 6a got %d bytes \n " , readden ) ;
2004-04-27 01:30:51 +02:00
pbuf = ibuf ;
ok ( memcmp ( obuf2 , pbuf , sizeof ( obuf2 ) ) = = 0 , " content 6a check \n " ) ;
}
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hFile , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile6a \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len 6a \n " ) ;
ok ( WriteFile ( hFile , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile6b \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len 6b \n " ) ;
ok ( PeekNamedPipe ( hnp , ibuf , sizeof ( ibuf ) , & readden , & avail , NULL ) , " Peek6 \n " ) ;
2017-03-23 15:42:25 +01:00
ok ( readden = = sizeof ( obuf ) , " peek6 got %d bytes \n " , readden ) ;
2015-11-09 06:26:48 +01:00
2014-07-30 18:00:19 +02:00
ok ( avail = = sizeof ( obuf ) + sizeof ( obuf2 ) , " peek6b got %d bytes available \n " , avail ) ;
2004-04-27 01:30:51 +02:00
pbuf = ibuf ;
ok ( memcmp ( obuf , pbuf , sizeof ( obuf ) ) = = 0 , " content 6a check \n " ) ;
ok ( ReadFile ( hnp , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
2017-03-26 12:52:39 +02:00
ok ( readden = = sizeof ( obuf ) , " read 6b got %d bytes \n " , readden ) ;
2004-04-27 01:30:51 +02:00
pbuf = ibuf ;
ok ( memcmp ( obuf , pbuf , sizeof ( obuf ) ) = = 0 , " content 6a check \n " ) ;
2014-09-04 17:10:45 +02:00
if ( readden < = sizeof ( obuf ) )
ok ( ReadFile ( hnp , ibuf , sizeof ( ibuf ) , & readden , NULL ) , " ReadFile \n " ) ;
2014-09-04 17:16:33 +02:00
/* Test how ReadFile behaves when the buffer is not big enough for the whole message */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hnp , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile 7 \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len 7 \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hFile , ibuf , 4 , & readden , NULL ) , " ReadFile 7 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 7 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 7 \n " , readden ) ;
ok ( ReadFile ( hFile , ibuf + 4 , sizeof ( ibuf ) - 4 , & readden , NULL ) , " ReadFile 7 \n " ) ;
ok ( readden = = sizeof ( obuf2 ) - 4 , " read got %d bytes 7 \n " , readden ) ;
ok ( memcmp ( obuf2 , ibuf , written ) = = 0 , " content check 7 \n " ) ;
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hFile , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile 8 \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len 8 \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hnp , ibuf , 4 , & readden , NULL ) , " ReadFile 8 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 8 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 8 \n " , readden ) ;
ok ( ReadFile ( hnp , ibuf + 4 , sizeof ( ibuf ) - 4 , & readden , NULL ) , " ReadFile 8 \n " ) ;
ok ( readden = = sizeof ( obuf ) - 4 , " read got %d bytes 8 \n " , readden ) ;
ok ( memcmp ( obuf , ibuf , written ) = = 0 , " content check 8 \n " ) ;
2014-09-04 17:24:12 +02:00
/* The following test shows that when doing a partial read of a message, the rest
* is still in the pipe , and can be received from a second thread . This shows
* especially that the content is _not_ stored in thread - local - storage until it is
* completely transmitted . The same method works even across multiple processes . */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hnp , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile 9 \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len 9 \n " ) ;
ok ( WriteFile ( hnp , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile 9 \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len 9 \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hFile , ibuf , 4 , & readden , NULL ) , " ReadFile 9 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 9 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 9 \n " , readden ) ;
SetLastError ( 0xdeadbeef ) ;
ret = RpcReadFile ( hFile , ibuf + 4 , 4 , & readden , NULL ) ;
ok ( ! ret , " RpcReadFile 9 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 9 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 9 \n " , readden ) ;
ret = RpcReadFile ( hFile , ibuf + 8 , sizeof ( ibuf ) , & readden , NULL ) ;
ok ( ret , " RpcReadFile 9 \n " ) ;
ok ( readden = = sizeof ( obuf ) - 8 , " read got %d bytes 9 \n " , readden ) ;
ok ( memcmp ( obuf , ibuf , sizeof ( obuf ) ) = = 0 , " content check 9 \n " ) ;
if ( readden < = sizeof ( obuf ) - 8 ) /* blocks forever if second part was already received */
{
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = RpcReadFile ( hFile , ibuf , 4 , & readden , NULL ) ;
ok ( ! ret , " RpcReadFile 9 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 9 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 9 \n " , readden ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hFile , ibuf + 4 , 4 , & readden , NULL ) , " ReadFile 9 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 9 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 9 \n " , readden ) ;
ret = RpcReadFile ( hFile , ibuf + 8 , sizeof ( ibuf ) , & readden , NULL ) ;
ok ( ret , " RpcReadFile 9 \n " ) ;
ok ( readden = = sizeof ( obuf2 ) - 8 , " read got %d bytes 9 \n " , readden ) ;
ok ( memcmp ( obuf2 , ibuf , sizeof ( obuf2 ) ) = = 0 , " content check 9 \n " ) ;
}
/* Now the reverse direction */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
ok ( WriteFile ( hFile , obuf2 , sizeof ( obuf2 ) , & written , NULL ) , " WriteFile 10 \n " ) ;
ok ( written = = sizeof ( obuf2 ) , " write file len 10 \n " ) ;
ok ( WriteFile ( hFile , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile 10 \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len 10 \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hnp , ibuf , 4 , & readden , NULL ) , " ReadFile 10 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 10 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 10 \n " , readden ) ;
SetLastError ( 0xdeadbeef ) ;
ret = RpcReadFile ( hnp , ibuf + 4 , 4 , & readden , NULL ) ;
ok ( ! ret , " RpcReadFile 10 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 10 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 10 \n " , readden ) ;
ret = RpcReadFile ( hnp , ibuf + 8 , sizeof ( ibuf ) , & readden , NULL ) ;
ok ( ret , " RpcReadFile 10 \n " ) ;
ok ( readden = = sizeof ( obuf2 ) - 8 , " read got %d bytes 10 \n " , readden ) ;
ok ( memcmp ( obuf2 , ibuf , sizeof ( obuf2 ) ) = = 0 , " content check 10 \n " ) ;
if ( readden < = sizeof ( obuf2 ) - 8 ) /* blocks forever if second part was already received */
{
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = RpcReadFile ( hnp , ibuf , 4 , & readden , NULL ) ;
ok ( ! ret , " RpcReadFile 10 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 10 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 10 \n " , readden ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ! ReadFile ( hnp , ibuf + 4 , 4 , & readden , NULL ) , " ReadFile 10 \n " ) ;
ok ( GetLastError ( ) = = ERROR_MORE_DATA , " wrong error 10 \n " ) ;
ok ( readden = = 4 , " read got %d bytes 10 \n " , readden ) ;
ret = RpcReadFile ( hnp , ibuf + 8 , sizeof ( ibuf ) , & readden , NULL ) ;
ok ( ret , " RpcReadFile 10 \n " ) ;
ok ( readden = = sizeof ( obuf ) - 8 , " read got %d bytes 10 \n " , readden ) ;
ok ( memcmp ( obuf , ibuf , sizeof ( obuf ) ) = = 0 , " content check 10 \n " ) ;
}
2004-04-27 01:30:51 +02:00
}
2003-05-16 00:52:41 +02:00
/* Picky conformance tests */
/* Verify that you can't connect to pipe again
* until server calls DisconnectNamedPipe + ConnectNamedPipe
* or creates a new pipe
* case 1 : other client not yet closed
*/
hFile2 = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hFile2 = = INVALID_HANDLE_VALUE ,
2004-02-06 06:24:34 +01:00
" connecting to named pipe after other client closes but before DisconnectNamedPipe should fail \n " ) ;
2003-05-16 00:52:41 +02:00
ok ( GetLastError ( ) = = ERROR_PIPE_BUSY ,
2004-02-06 06:24:34 +01:00
" connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY \n " ) ;
2003-05-16 00:52:41 +02:00
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hFile ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
/* case 2: other client already closed */
hFile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hFile = = INVALID_HANDLE_VALUE ,
2004-02-06 06:24:34 +01:00
" connecting to named pipe after other client closes but before DisconnectNamedPipe should fail \n " ) ;
2003-05-16 00:52:41 +02:00
ok ( GetLastError ( ) = = ERROR_PIPE_BUSY ,
2004-02-06 06:24:34 +01:00
" connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY \n " ) ;
2003-05-16 00:52:41 +02:00
2004-02-06 06:24:34 +01:00
ok ( DisconnectNamedPipe ( hnp ) , " DisconnectNamedPipe \n " ) ;
2003-05-16 00:52:41 +02:00
/* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
hFile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hFile = = INVALID_HANDLE_VALUE ,
2004-02-06 06:24:34 +01:00
" connecting to named pipe after other client closes but before DisconnectNamedPipe should fail \n " ) ;
2003-05-16 00:52:41 +02:00
ok ( GetLastError ( ) = = ERROR_PIPE_BUSY ,
2004-02-06 06:24:34 +01:00
" connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY \n " ) ;
2003-05-16 00:52:41 +02:00
/* to be complete, we'd call ConnectNamedPipe here and loop,
* but by default that ' s blocking , so we ' d either have
* to turn on the uncommon nonblocking mode , or
* use another thread .
*/
}
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hnp ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
2018-08-20 19:29:16 +02:00
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_INBOUND , pipemode | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
test_signaled ( hnp ) ;
test_file_access ( hnp , SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_PROPERTIES
| FILE_READ_DATA ) ;
CloseHandle ( hnp ) ;
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_OUTBOUND , pipemode | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
test_signaled ( hnp ) ;
test_file_access ( hnp , SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
| FILE_WRITE_PROPERTIES | FILE_APPEND_DATA | FILE_WRITE_DATA ) ;
2018-08-20 19:29:46 +02:00
hFile = CreateFileA ( PIPENAME , 0 , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hFile ! = INVALID_HANDLE_VALUE , " CreateFile failed: %u \n " , GetLastError ( ) ) ;
test_file_access ( hFile , SYNCHRONIZE | FILE_READ_ATTRIBUTES ) ;
CloseHandle ( hFile ) ;
2018-08-20 19:29:16 +02:00
CloseHandle ( hnp ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " test_CreateNamedPipe returning \n " ) ;
2003-05-16 00:52:41 +02:00
}
2005-06-20 17:35:54 +02:00
static void test_CreateNamedPipe_instances_must_match ( void )
2003-05-16 00:52:41 +02:00
{
HANDLE hnp , hnp2 ;
/* Check no mismatch */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_WAIT ,
2003-05-16 00:52:41 +02:00
/* nMaxInstances */ 2 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2003-05-16 00:52:41 +02:00
2013-10-21 10:02:23 +02:00
hnp2 = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_WAIT ,
2003-05-16 00:52:41 +02:00
/* nMaxInstances */ 2 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnp2 ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2003-05-16 00:52:41 +02:00
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hnp ) , " CloseHandle \n " ) ;
ok ( CloseHandle ( hnp2 ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
/* Check nMaxInstances */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_WAIT ,
2003-05-16 00:52:41 +02:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2003-05-16 00:52:41 +02:00
2013-10-21 10:02:23 +02:00
hnp2 = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_WAIT ,
2003-05-16 00:52:41 +02:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( hnp2 = = INVALID_HANDLE_VALUE
2004-02-06 06:24:34 +01:00
& & GetLastError ( ) = = ERROR_PIPE_BUSY , " nMaxInstances not obeyed \n " ) ;
2003-05-16 00:52:41 +02:00
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hnp ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
/* Check PIPE_ACCESS_* */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_WAIT ,
2003-05-16 00:52:41 +02:00
/* nMaxInstances */ 2 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2003-05-16 00:52:41 +02:00
2013-10-21 10:02:23 +02:00
hnp2 = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_INBOUND , PIPE_TYPE_BYTE | PIPE_WAIT ,
2011-09-26 13:57:29 +02:00
/* nMaxInstances */ 2 ,
2003-05-16 00:52:41 +02:00
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( hnp2 = = INVALID_HANDLE_VALUE
2004-02-06 06:24:34 +01:00
& & GetLastError ( ) = = ERROR_ACCESS_DENIED , " PIPE_ACCESS_* mismatch allowed \n " ) ;
2003-05-16 00:52:41 +02:00
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hnp ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
2011-09-26 13:57:29 +02:00
/* check everything else */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_WAIT ,
2011-09-26 13:57:29 +02:00
/* nMaxInstances */ 4 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2013-10-21 10:02:23 +02:00
hnp2 = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_MESSAGE ,
2011-09-26 13:57:29 +02:00
/* nMaxInstances */ 3 ,
/* nOutBufSize */ 102 ,
/* nInBufSize */ 24 ,
/* nDefaultWait */ 1234 ,
/* lpSecurityAttrib */ NULL ) ;
ok ( hnp2 ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
ok ( CloseHandle ( hnp ) , " CloseHandle \n " ) ;
ok ( CloseHandle ( hnp2 ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
}
2018-01-23 15:51:31 +01:00
static void test_ReadFile ( void )
{
HANDLE server , client ;
OVERLAPPED overlapped ;
DWORD size ;
BOOL res ;
static char buf [ 512 ] ;
server = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_WAIT_FOREVER , NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed with %u \n " , GetLastError ( ) ) ;
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL ,
OPEN_EXISTING , 0 , 0 ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " CreateFile failed with %u \n " , GetLastError ( ) ) ;
ok ( WriteFile ( client , buf , sizeof ( buf ) , & size , NULL ) , " WriteFile \n " ) ;
res = ReadFile ( server , buf , 1 , & size , NULL ) ;
ok ( ! res & & GetLastError ( ) = = ERROR_MORE_DATA , " ReadFile returned %x(%u) \n " , res , GetLastError ( ) ) ;
ok ( size = = 1 , " size = %u \n " , size ) ;
/* pass both overlapped and ret read */
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
res = ReadFile ( server , buf , 1 , & size , & overlapped ) ;
ok ( ! res & & GetLastError ( ) = = ERROR_MORE_DATA , " ReadFile returned %x(%u) \n " , res , GetLastError ( ) ) ;
ok ( size = = 0 , " size = %u \n " , size ) ;
ok ( ( NTSTATUS ) overlapped . Internal = = STATUS_BUFFER_OVERFLOW , " Internal = %lx \n " , overlapped . Internal ) ;
ok ( overlapped . InternalHigh = = 1 , " InternalHigh = %lx \n " , overlapped . InternalHigh ) ;
DisconnectNamedPipe ( server ) ;
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . InternalHigh = 0xdeadbeef ;
res = ReadFile ( server , buf , 1 , & size , & overlapped ) ;
ok ( ! res & & GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " ReadFile returned %x(%u) \n " , res , GetLastError ( ) ) ;
ok ( size = = 0 , " size = %u \n " , size ) ;
ok ( overlapped . Internal = = STATUS_PENDING , " Internal = %lx \n " , overlapped . Internal ) ;
ok ( overlapped . InternalHigh = = 0xdeadbeef , " InternalHigh = %lx \n " , overlapped . InternalHigh ) ;
2018-01-23 15:52:05 +01:00
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . InternalHigh = 0xdeadbeef ;
res = WriteFile ( server , buf , 1 , & size , & overlapped ) ;
ok ( ! res & & GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " ReadFile returned %x(%u) \n " , res , GetLastError ( ) ) ;
ok ( size = = 0 , " size = %u \n " , size ) ;
ok ( overlapped . Internal = = STATUS_PENDING , " Internal = %lx \n " , overlapped . Internal ) ;
ok ( overlapped . InternalHigh = = 0xdeadbeef , " InternalHigh = %lx \n " , overlapped . InternalHigh ) ;
2018-01-23 15:51:31 +01:00
CloseHandle ( server ) ;
CloseHandle ( client ) ;
}
2003-05-16 00:52:41 +02:00
/** implementation of alarm() */
static DWORD CALLBACK alarmThreadMain ( LPVOID arg )
{
2009-01-03 20:17:31 +01:00
DWORD_PTR timeout = ( DWORD_PTR ) arg ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " alarmThreadMain \n " ) ;
2004-05-04 02:43:46 +02:00
if ( WaitForSingleObject ( alarm_event , timeout ) = = WAIT_TIMEOUT )
{
ok ( FALSE , " alarm \n " ) ;
ExitProcess ( 1 ) ;
}
2003-05-16 00:52:41 +02:00
return 1 ;
}
2010-10-01 13:36:35 +02:00
static HANDLE hnp = INVALID_HANDLE_VALUE ;
2003-05-16 00:52:41 +02:00
/** Trivial byte echo server - disconnects after each session */
static DWORD CALLBACK serverThreadMain1 ( LPVOID arg )
{
int i ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " serverThreadMain1 start \n " ) ;
2003-05-16 00:52:41 +02:00
/* Set up a simple echo server */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME " serverThreadMain1 " , PIPE_ACCESS_DUPLEX ,
2003-05-16 00:52:41 +02:00
PIPE_TYPE_BYTE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2004-05-04 02:43:46 +02:00
for ( i = 0 ; i < NB_SERVER_LOOPS ; i + + ) {
2003-05-16 00:52:41 +02:00
char buf [ 512 ] ;
DWORD written ;
DWORD readden ;
2013-11-19 01:05:54 +01:00
BOOL success ;
2003-05-16 00:52:41 +02:00
/* Wait for client to connect */
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server calling ConnectNamedPipe... \n " ) ;
2003-05-16 00:52:41 +02:00
ok ( ConnectNamedPipe ( hnp , NULL )
2004-02-06 06:24:34 +01:00
| | GetLastError ( ) = = ERROR_PIPE_CONNECTED , " ConnectNamedPipe \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " ConnectNamedPipe returned. \n " ) ;
2003-05-16 00:52:41 +02:00
/* Echo bytes once */
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server reading... \n " ) ;
2003-05-16 00:52:41 +02:00
success = ReadFile ( hnp , buf , sizeof ( buf ) , & readden , NULL ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done reading. \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( success , " ReadFile \n " ) ;
ok ( readden , " short read \n " ) ;
2003-05-16 00:52:41 +02:00
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server writing... \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( WriteFile ( hnp , buf , readden , & written , NULL ) , " WriteFile \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done writing. \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( written = = readden , " write file len \n " ) ;
2003-05-16 00:52:41 +02:00
/* finish this connection, wait for next one */
2004-02-06 06:24:34 +01:00
ok ( FlushFileBuffers ( hnp ) , " FlushFileBuffers \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done flushing. \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( DisconnectNamedPipe ( hnp ) , " DisconnectNamedPipe \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done disconnecting. \n " ) ;
2003-05-16 00:52:41 +02:00
}
2004-05-04 02:43:46 +02:00
return 0 ;
2003-05-16 00:52:41 +02:00
}
/** Trivial byte echo server - closes after each connection */
static DWORD CALLBACK serverThreadMain2 ( LPVOID arg )
{
int i ;
HANDLE hnpNext = 0 ;
2003-05-20 05:58:35 +02:00
trace ( " serverThreadMain2 \n " ) ;
2003-05-16 00:52:41 +02:00
/* Set up a simple echo server */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME " serverThreadMain2 " , PIPE_ACCESS_DUPLEX ,
2003-05-16 00:52:41 +02:00
PIPE_TYPE_BYTE | PIPE_WAIT ,
/* nMaxInstances */ 2 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2003-05-16 00:52:41 +02:00
2004-05-04 02:43:46 +02:00
for ( i = 0 ; i < NB_SERVER_LOOPS ; i + + ) {
2003-05-16 00:52:41 +02:00
char buf [ 512 ] ;
DWORD written ;
DWORD readden ;
2013-11-19 01:05:54 +01:00
DWORD ret ;
BOOL success ;
2003-05-16 00:52:41 +02:00
2011-08-22 11:02:51 +02:00
user_apc_ran = FALSE ;
2020-09-22 12:24:19 +02:00
if ( i = = 0 )
{
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Queueing an user APC \n " ) ; /* verify the pipe is non alerable */
2020-09-22 12:24:19 +02:00
ret = QueueUserAPC ( & user_apc , GetCurrentThread ( ) , 0 ) ;
2013-11-19 01:05:54 +01:00
ok ( ret , " QueueUserAPC failed: %d \n " , GetLastError ( ) ) ;
2011-08-22 11:02:51 +02:00
}
2003-05-16 00:52:41 +02:00
/* Wait for client to connect */
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server calling ConnectNamedPipe... \n " ) ;
2003-05-16 00:52:41 +02:00
ok ( ConnectNamedPipe ( hnp , NULL )
2004-02-06 06:24:34 +01:00
| | GetLastError ( ) = = ERROR_PIPE_CONNECTED , " ConnectNamedPipe \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " ConnectNamedPipe returned. \n " ) ;
2003-05-16 00:52:41 +02:00
/* Echo bytes once */
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server reading... \n " ) ;
2003-05-16 00:52:41 +02:00
success = ReadFile ( hnp , buf , sizeof ( buf ) , & readden , NULL ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done reading. \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( success , " ReadFile \n " ) ;
2003-05-16 00:52:41 +02:00
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server writing... \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( WriteFile ( hnp , buf , readden , & written , NULL ) , " WriteFile \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done writing. \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( written = = readden , " write file len \n " ) ;
2003-05-16 00:52:41 +02:00
/* finish this connection, wait for next one */
2004-02-06 06:24:34 +01:00
ok ( FlushFileBuffers ( hnp ) , " FlushFileBuffers \n " ) ;
ok ( DisconnectNamedPipe ( hnp ) , " DisconnectNamedPipe \n " ) ;
2003-05-16 00:52:41 +02:00
2011-08-22 11:02:51 +02:00
ok ( user_apc_ran = = FALSE , " UserAPC ran, pipe using alertable io mode \n " ) ;
2020-09-22 12:24:19 +02:00
if ( i = = 0 )
2011-08-22 11:02:51 +02:00
SleepEx ( 0 , TRUE ) ; /* get rid of apc */
2003-05-16 00:52:41 +02:00
/* Set up next echo server */
hnpNext =
2013-10-21 10:02:23 +02:00
CreateNamedPipeA ( PIPENAME " serverThreadMain2 " , PIPE_ACCESS_DUPLEX ,
2003-05-16 00:52:41 +02:00
PIPE_TYPE_BYTE | PIPE_WAIT ,
/* nMaxInstances */ 2 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnpNext ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2003-05-16 00:52:41 +02:00
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hnp ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
hnp = hnpNext ;
}
2004-05-04 02:43:46 +02:00
return 0 ;
2003-05-16 00:52:41 +02:00
}
/** Trivial byte echo server - uses overlapped named pipe calls */
static DWORD CALLBACK serverThreadMain3 ( LPVOID arg )
{
int i ;
HANDLE hEvent ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " serverThreadMain3 \n " ) ;
2003-05-16 00:52:41 +02:00
/* Set up a simple echo server */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME " serverThreadMain3 " , PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED ,
2003-05-16 00:52:41 +02:00
PIPE_TYPE_BYTE | PIPE_WAIT ,
2003-02-19 23:06:36 +01:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2004-02-06 06:24:34 +01:00
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2003-02-19 23:06:36 +01:00
2013-10-21 10:02:23 +02:00
hEvent = CreateEventW ( NULL , /* security attribute */
2003-05-16 00:52:41 +02:00
TRUE , /* manual reset event */
FALSE , /* initial state */
NULL ) ; /* name */
2004-02-06 06:24:34 +01:00
ok ( hEvent ! = NULL , " CreateEvent \n " ) ;
2003-05-16 00:52:41 +02:00
2004-05-04 02:43:46 +02:00
for ( i = 0 ; i < NB_SERVER_LOOPS ; i + + ) {
2003-05-16 00:52:41 +02:00
char buf [ 512 ] ;
DWORD written ;
DWORD readden ;
DWORD dummy ;
2013-11-19 01:05:54 +01:00
BOOL success ;
2003-05-16 00:52:41 +02:00
OVERLAPPED oOverlap ;
int letWFSOEwait = ( i & 2 ) ;
int letGORwait = ( i & 1 ) ;
2009-02-19 23:49:55 +01:00
DWORD err ;
2003-05-16 00:52:41 +02:00
memset ( & oOverlap , 0 , sizeof ( oOverlap ) ) ;
oOverlap . hEvent = hEvent ;
/* Wait for client to connect */
2010-05-22 20:00:59 +02:00
if ( i = = 0 ) {
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server calling non-overlapped ConnectNamedPipe on overlapped pipe... \n " ) ;
2010-05-22 20:00:59 +02:00
success = ConnectNamedPipe ( hnp , NULL ) ;
err = GetLastError ( ) ;
ok ( success | | ( err = = ERROR_PIPE_CONNECTED ) , " ConnectNamedPipe failed: %d \n " , err ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " ConnectNamedPipe operation complete. \n " ) ;
2010-05-22 20:00:59 +02:00
} else {
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server calling overlapped ConnectNamedPipe... \n " ) ;
2010-05-22 20:00:59 +02:00
success = ConnectNamedPipe ( hnp , & oOverlap ) ;
err = GetLastError ( ) ;
ok ( ! success & & ( err = = ERROR_IO_PENDING | | err = = ERROR_PIPE_CONNECTED ) , " overlapped ConnectNamedPipe \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " overlapped ConnectNamedPipe returned. \n " ) ;
2010-05-22 20:00:59 +02:00
if ( ! success & & ( err = = ERROR_IO_PENDING ) ) {
if ( letWFSOEwait )
{
DWORD ret ;
do {
ret = WaitForSingleObjectEx ( hEvent , INFINITE , TRUE ) ;
} while ( ret = = WAIT_IO_COMPLETION ) ;
ok ( ret = = 0 , " wait ConnectNamedPipe returned %x \n " , ret ) ;
}
success = GetOverlappedResult ( hnp , & oOverlap , & dummy , letGORwait ) ;
if ( ! letGORwait & & ! letWFSOEwait & & ! success ) {
ok ( GetLastError ( ) = = ERROR_IO_INCOMPLETE , " GetOverlappedResult \n " ) ;
success = GetOverlappedResult ( hnp , & oOverlap , & dummy , TRUE ) ;
}
2009-02-19 23:49:55 +01:00
}
2010-05-22 20:00:59 +02:00
ok ( success | | ( err = = ERROR_PIPE_CONNECTED ) , " GetOverlappedResult ConnectNamedPipe \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " overlapped ConnectNamedPipe operation complete. \n " ) ;
2009-02-19 23:49:55 +01:00
}
2003-05-16 00:52:41 +02:00
/* Echo bytes once */
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server reading... \n " ) ;
2009-02-19 23:49:55 +01:00
success = ReadFile ( hnp , buf , sizeof ( buf ) , & readden , & oOverlap ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server ReadFile returned... \n " ) ;
2003-05-16 00:52:41 +02:00
err = GetLastError ( ) ;
2004-02-06 06:24:34 +01:00
ok ( success | | err = = ERROR_IO_PENDING , " overlapped ReadFile \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " overlapped ReadFile returned. \n " ) ;
2009-02-19 23:49:55 +01:00
if ( ! success & & ( err = = ERROR_IO_PENDING ) ) {
if ( letWFSOEwait )
{
DWORD ret ;
do {
ret = WaitForSingleObjectEx ( hEvent , INFINITE , TRUE ) ;
} while ( ret = = WAIT_IO_COMPLETION ) ;
ok ( ret = = 0 , " wait ReadFile returned %x \n " , ret ) ;
}
success = GetOverlappedResult ( hnp , & oOverlap , & readden , letGORwait ) ;
if ( ! letGORwait & & ! letWFSOEwait & & ! success ) {
ok ( GetLastError ( ) = = ERROR_IO_INCOMPLETE , " GetOverlappedResult \n " ) ;
success = GetOverlappedResult ( hnp , & oOverlap , & readden , TRUE ) ;
}
}
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done reading. \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( success , " overlapped ReadFile \n " ) ;
2003-05-16 00:52:41 +02:00
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server writing... \n " ) ;
2009-02-19 23:49:55 +01:00
success = WriteFile ( hnp , buf , readden , & written , & oOverlap ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server WriteFile returned... \n " ) ;
2003-05-16 00:52:41 +02:00
err = GetLastError ( ) ;
2004-02-06 06:24:34 +01:00
ok ( success | | err = = ERROR_IO_PENDING , " overlapped WriteFile \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " overlapped WriteFile returned. \n " ) ;
2009-02-19 23:49:55 +01:00
if ( ! success & & ( err = = ERROR_IO_PENDING ) ) {
if ( letWFSOEwait )
{
DWORD ret ;
do {
ret = WaitForSingleObjectEx ( hEvent , INFINITE , TRUE ) ;
} while ( ret = = WAIT_IO_COMPLETION ) ;
ok ( ret = = 0 , " wait WriteFile returned %x \n " , ret ) ;
}
success = GetOverlappedResult ( hnp , & oOverlap , & written , letGORwait ) ;
if ( ! letGORwait & & ! letWFSOEwait & & ! success ) {
ok ( GetLastError ( ) = = ERROR_IO_INCOMPLETE , " GetOverlappedResult \n " ) ;
success = GetOverlappedResult ( hnp , & oOverlap , & written , TRUE ) ;
}
}
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done writing. \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( success , " overlapped WriteFile \n " ) ;
ok ( written = = readden , " write file len \n " ) ;
2003-05-16 00:52:41 +02:00
/* finish this connection, wait for next one */
2004-02-06 06:24:34 +01:00
ok ( FlushFileBuffers ( hnp ) , " FlushFileBuffers \n " ) ;
ok ( DisconnectNamedPipe ( hnp ) , " DisconnectNamedPipe \n " ) ;
2003-05-16 00:52:41 +02:00
}
2004-05-04 02:43:46 +02:00
return 0 ;
2003-05-16 00:52:41 +02:00
}
2009-02-20 20:39:44 +01:00
/** Trivial byte echo server - uses i/o completion ports */
static DWORD CALLBACK serverThreadMain4 ( LPVOID arg )
{
int i ;
HANDLE hcompletion ;
2011-01-11 20:30:00 +01:00
BOOL ret ;
2009-02-20 20:39:44 +01:00
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " serverThreadMain4 \n " ) ;
2009-02-20 20:39:44 +01:00
/* Set up a simple echo server */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME " serverThreadMain4 " , PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED ,
2009-02-20 20:39:44 +01:00
PIPE_TYPE_BYTE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
hcompletion = CreateIoCompletionPort ( hnp , NULL , 12345 , 1 ) ;
ok ( hcompletion ! = NULL , " CreateIoCompletionPort failed, error=%i \n " , GetLastError ( ) ) ;
for ( i = 0 ; i < NB_SERVER_LOOPS ; i + + ) {
char buf [ 512 ] ;
DWORD written ;
DWORD readden ;
DWORD dummy ;
2013-11-19 01:05:54 +01:00
BOOL success ;
2009-02-20 20:39:44 +01:00
OVERLAPPED oConnect ;
OVERLAPPED oRead ;
OVERLAPPED oWrite ;
OVERLAPPED * oResult ;
DWORD err ;
ULONG_PTR compkey ;
memset ( & oConnect , 0 , sizeof ( oConnect ) ) ;
memset ( & oRead , 0 , sizeof ( oRead ) ) ;
memset ( & oWrite , 0 , sizeof ( oWrite ) ) ;
/* Wait for client to connect */
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server calling overlapped ConnectNamedPipe... \n " ) ;
2009-02-20 20:39:44 +01:00
success = ConnectNamedPipe ( hnp , & oConnect ) ;
err = GetLastError ( ) ;
2009-03-04 15:45:48 +01:00
ok ( ! success & & ( err = = ERROR_IO_PENDING | | err = = ERROR_PIPE_CONNECTED ) ,
" overlapped ConnectNamedPipe got %u err %u \n " , success , err ) ;
2009-02-20 20:39:44 +01:00
if ( ! success & & err = = ERROR_IO_PENDING ) {
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " ConnectNamedPipe GetQueuedCompletionStatus \n " ) ;
2009-02-20 20:39:44 +01:00
success = GetQueuedCompletionStatus ( hcompletion , & dummy , & compkey , & oResult , 0 ) ;
if ( ! success )
{
ok ( GetLastError ( ) = = WAIT_TIMEOUT ,
" ConnectNamedPipe GetQueuedCompletionStatus wrong error %u \n " , GetLastError ( ) ) ;
success = GetQueuedCompletionStatus ( hcompletion , & dummy , & compkey , & oResult , 10000 ) ;
}
ok ( success , " ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i \n " , GetLastError ( ) ) ;
if ( success )
{
ok ( compkey = = 12345 , " got completion key %i instead of 12345 \n " , ( int ) compkey ) ;
ok ( oResult = = & oConnect , " got overlapped pointer %p instead of %p \n " , oResult , & oConnect ) ;
}
}
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " overlapped ConnectNamedPipe operation complete. \n " ) ;
2009-02-20 20:39:44 +01:00
/* Echo bytes once */
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server reading... \n " ) ;
2009-02-20 20:39:44 +01:00
success = ReadFile ( hnp , buf , sizeof ( buf ) , & readden , & oRead ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server ReadFile returned... \n " ) ;
2009-02-20 20:39:44 +01:00
err = GetLastError ( ) ;
ok ( success | | err = = ERROR_IO_PENDING , " overlapped ReadFile, err=%i \n " , err ) ;
success = GetQueuedCompletionStatus ( hcompletion , & readden , & compkey ,
& oResult , 10000 ) ;
ok ( success , " ReadFile GetQueuedCompletionStatus failed, errno=%i \n " , GetLastError ( ) ) ;
if ( success )
{
ok ( compkey = = 12345 , " got completion key %i instead of 12345 \n " , ( int ) compkey ) ;
ok ( oResult = = & oRead , " got overlapped pointer %p instead of %p \n " , oResult , & oRead ) ;
}
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done reading. \n " ) ;
2009-02-20 20:39:44 +01:00
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server writing... \n " ) ;
2009-02-20 20:39:44 +01:00
success = WriteFile ( hnp , buf , readden , & written , & oWrite ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server WriteFile returned... \n " ) ;
2009-02-20 20:39:44 +01:00
err = GetLastError ( ) ;
2009-03-04 15:45:48 +01:00
ok ( success | | err = = ERROR_IO_PENDING , " overlapped WriteFile failed, err=%u \n " , err ) ;
2009-02-20 20:39:44 +01:00
success = GetQueuedCompletionStatus ( hcompletion , & written , & compkey ,
& oResult , 10000 ) ;
ok ( success , " WriteFile GetQueuedCompletionStatus failed, errno=%i \n " , GetLastError ( ) ) ;
if ( success )
{
ok ( compkey = = 12345 , " got completion key %i instead of 12345 \n " , ( int ) compkey ) ;
ok ( oResult = = & oWrite , " got overlapped pointer %p instead of %p \n " , oResult , & oWrite ) ;
ok ( written = = readden , " write file len \n " ) ;
}
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done writing. \n " ) ;
2009-02-20 20:39:44 +01:00
2017-09-22 12:13:25 +02:00
/* Client will finish this connection, the following ops will trigger broken pipe errors. */
/* Wait for the pipe to break. */
while ( PeekNamedPipe ( hnp , NULL , 0 , NULL , & written , & written ) ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server writing on disconnected pipe... \n " ) ;
2017-09-22 12:13:25 +02:00
SetLastError ( ERROR_SUCCESS ) ;
success = WriteFile ( hnp , buf , readden , & written , & oWrite ) ;
err = GetLastError ( ) ;
2018-08-08 22:00:55 +02:00
ok ( ! success & & err = = ERROR_NO_DATA ,
2017-09-22 12:13:25 +02:00
" overlapped WriteFile on disconnected pipe returned %u, err=%i \n " , success , err ) ;
/* No completion status is queued on immediate error. */
SetLastError ( ERROR_SUCCESS ) ;
oResult = ( OVERLAPPED * ) 0xdeadbeef ;
success = GetQueuedCompletionStatus ( hcompletion , & written , & compkey ,
& oResult , 0 ) ;
err = GetLastError ( ) ;
ok ( ! success & & err = = WAIT_TIMEOUT & & ! oResult ,
" WriteFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p \n " ,
success , err , oResult ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server reading from disconnected pipe... \n " ) ;
2017-09-22 12:13:25 +02:00
SetLastError ( ERROR_SUCCESS ) ;
success = ReadFile ( hnp , buf , sizeof ( buf ) , & readden , & oRead ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server ReadFile from disconnected pipe returned... \n " ) ;
2017-09-22 12:13:25 +02:00
err = GetLastError ( ) ;
ok ( ! success & & err = = ERROR_BROKEN_PIPE ,
" overlapped ReadFile on disconnected pipe returned %u, err=%i \n " , success , err ) ;
SetLastError ( ERROR_SUCCESS ) ;
oResult = ( OVERLAPPED * ) 0xdeadbeef ;
success = GetQueuedCompletionStatus ( hcompletion , & readden , & compkey ,
& oResult , 0 ) ;
err = GetLastError ( ) ;
ok ( ! success & & err = = WAIT_TIMEOUT & & ! oResult ,
" ReadFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p \n " ,
success , err , oResult ) ;
2009-02-20 20:39:44 +01:00
/* finish this connection, wait for next one */
ok ( FlushFileBuffers ( hnp ) , " FlushFileBuffers \n " ) ;
2009-03-04 15:45:48 +01:00
success = DisconnectNamedPipe ( hnp ) ;
ok ( success , " DisconnectNamedPipe failed, err %u \n " , GetLastError ( ) ) ;
2009-02-20 20:39:44 +01:00
}
2011-01-11 20:30:00 +01:00
ret = CloseHandle ( hnp ) ;
ok ( ret , " CloseHandle named pipe failed, err=%i \n " , GetLastError ( ) ) ;
ret = CloseHandle ( hcompletion ) ;
ok ( ret , " CloseHandle completion failed, err=%i \n " , GetLastError ( ) ) ;
2009-02-20 20:39:44 +01:00
return 0 ;
}
2012-06-14 20:38:19 +02:00
static int completion_called ;
static DWORD completion_errorcode ;
static DWORD completion_num_bytes ;
static LPOVERLAPPED completion_lpoverlapped ;
static VOID WINAPI completion_routine ( DWORD errorcode , DWORD num_bytes , LPOVERLAPPED lpoverlapped )
{
completion_called + + ;
completion_errorcode = errorcode ;
completion_num_bytes = num_bytes ;
completion_lpoverlapped = lpoverlapped ;
SetEvent ( lpoverlapped - > hEvent ) ;
}
/** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
static DWORD CALLBACK serverThreadMain5 ( LPVOID arg )
{
int i ;
HANDLE hEvent ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " serverThreadMain5 \n " ) ;
2012-06-14 20:38:19 +02:00
/* Set up a simple echo server */
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME " serverThreadMain5 " , PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED ,
2012-06-14 20:38:19 +02:00
PIPE_TYPE_BYTE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( hnp ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
2013-10-21 10:02:23 +02:00
hEvent = CreateEventW ( NULL , /* security attribute */
2012-06-14 20:38:19 +02:00
TRUE , /* manual reset event */
FALSE , /* initial state */
NULL ) ; /* name */
ok ( hEvent ! = NULL , " CreateEvent \n " ) ;
for ( i = 0 ; i < NB_SERVER_LOOPS ; i + + ) {
char buf [ 512 ] ;
DWORD readden ;
2013-11-19 01:05:54 +01:00
BOOL success ;
2012-06-14 20:38:19 +02:00
OVERLAPPED oOverlap ;
DWORD err ;
memset ( & oOverlap , 0 , sizeof ( oOverlap ) ) ;
oOverlap . hEvent = hEvent ;
/* Wait for client to connect */
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server calling ConnectNamedPipe... \n " ) ;
2012-06-14 20:38:19 +02:00
success = ConnectNamedPipe ( hnp , NULL ) ;
err = GetLastError ( ) ;
ok ( success | | ( err = = ERROR_PIPE_CONNECTED ) , " ConnectNamedPipe failed: %d \n " , err ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " ConnectNamedPipe operation complete. \n " ) ;
2012-06-14 20:38:19 +02:00
/* Echo bytes once */
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server reading... \n " ) ;
2012-06-14 20:38:19 +02:00
completion_called = 0 ;
ResetEvent ( hEvent ) ;
success = ReadFileEx ( hnp , buf , sizeof ( buf ) , & oOverlap , completion_routine ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server ReadFileEx returned... \n " ) ;
2012-06-14 20:38:19 +02:00
ok ( success , " ReadFileEx failed, err=%i \n " , GetLastError ( ) ) ;
ok ( completion_called = = 0 , " completion routine called before ReadFileEx return \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " ReadFileEx returned. \n " ) ;
2012-06-14 20:38:19 +02:00
if ( success ) {
DWORD ret ;
do {
ret = WaitForSingleObjectEx ( hEvent , INFINITE , TRUE ) ;
} while ( ret = = WAIT_IO_COMPLETION ) ;
ok ( ret = = 0 , " wait ReadFileEx returned %x \n " , ret ) ;
}
ok ( completion_called = = 1 , " completion routine called %i times \n " , completion_called ) ;
ok ( completion_errorcode = = ERROR_SUCCESS , " completion routine got error %d \n " , completion_errorcode ) ;
2012-06-18 11:38:38 +02:00
ok ( completion_num_bytes ! = 0 , " read 0 bytes \n " ) ;
2012-06-14 20:38:19 +02:00
ok ( completion_lpoverlapped = = & oOverlap , " got wrong overlapped pointer %p \n " , completion_lpoverlapped ) ;
readden = completion_num_bytes ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done reading. \n " ) ;
2012-06-14 20:38:19 +02:00
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server writing... \n " ) ;
2012-06-14 20:38:19 +02:00
completion_called = 0 ;
ResetEvent ( hEvent ) ;
success = WriteFileEx ( hnp , buf , readden , & oOverlap , completion_routine ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server WriteFileEx returned... \n " ) ;
2012-06-14 20:38:19 +02:00
ok ( success , " WriteFileEx failed, err=%i \n " , GetLastError ( ) ) ;
ok ( completion_called = = 0 , " completion routine called before ReadFileEx return \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " overlapped WriteFile returned. \n " ) ;
2012-06-14 20:38:19 +02:00
if ( success ) {
DWORD ret ;
do {
ret = WaitForSingleObjectEx ( hEvent , INFINITE , TRUE ) ;
} while ( ret = = WAIT_IO_COMPLETION ) ;
ok ( ret = = 0 , " wait WriteFileEx returned %x \n " , ret ) ;
}
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Server done writing. \n " ) ;
2012-06-14 20:38:19 +02:00
ok ( completion_called = = 1 , " completion routine called %i times \n " , completion_called ) ;
ok ( completion_errorcode = = ERROR_SUCCESS , " completion routine got error %d \n " , completion_errorcode ) ;
ok ( completion_num_bytes = = readden , " read %i bytes wrote %i \n " , readden , completion_num_bytes ) ;
ok ( completion_lpoverlapped = = & oOverlap , " got wrong overlapped pointer %p \n " , completion_lpoverlapped ) ;
/* finish this connection, wait for next one */
ok ( FlushFileBuffers ( hnp ) , " FlushFileBuffers \n " ) ;
ok ( DisconnectNamedPipe ( hnp ) , " DisconnectNamedPipe \n " ) ;
}
return 0 ;
}
2019-09-22 23:21:01 +02:00
static void exerciseServer ( const char * pipename , HANDLE serverThread )
2003-05-16 00:52:41 +02:00
{
int i ;
2019-09-22 23:21:01 +02:00
if ( winetest_debug > 1 ) trace ( " exerciseServer starting \n " ) ;
2004-05-04 02:43:46 +02:00
for ( i = 0 ; i < NB_SERVER_LOOPS ; i + + ) {
2003-05-21 20:23:20 +02:00
HANDLE hFile = INVALID_HANDLE_VALUE ;
2004-05-04 06:13:05 +02:00
static const char obuf [ ] = " Bit Bucket " ;
2003-05-16 00:52:41 +02:00
char ibuf [ 32 ] ;
DWORD written ;
DWORD readden ;
int loop ;
for ( loop = 0 ; loop < 3 ; loop + + ) {
DWORD err ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Client connecting... \n " ) ;
2003-05-16 00:52:41 +02:00
/* Connect to the server */
hFile = CreateFileA ( pipename , GENERIC_READ | GENERIC_WRITE , 0 ,
NULL , OPEN_EXISTING , 0 , 0 ) ;
if ( hFile ! = INVALID_HANDLE_VALUE )
break ;
err = GetLastError ( ) ;
if ( loop = = 0 )
2004-02-06 06:24:34 +01:00
ok ( err = = ERROR_PIPE_BUSY | | err = = ERROR_FILE_NOT_FOUND , " connecting to pipe \n " ) ;
2003-05-16 00:52:41 +02:00
else
2004-02-06 06:24:34 +01:00
ok ( err = = ERROR_PIPE_BUSY , " connecting to pipe \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " connect failed, retrying \n " ) ;
2003-05-16 00:52:41 +02:00
Sleep ( 200 ) ;
}
2004-02-06 06:24:34 +01:00
ok ( hFile ! = INVALID_HANDLE_VALUE , " client opening named pipe \n " ) ;
2003-05-16 00:52:41 +02:00
/* Make sure it can echo */
memset ( ibuf , 0 , sizeof ( ibuf ) ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Client writing... \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( WriteFile ( hFile , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile to client end of pipe \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len \n " ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Client reading... \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( ReadFile ( hFile , ibuf , sizeof ( obuf ) , & readden , NULL ) , " ReadFile from client end of pipe \n " ) ;
ok ( readden = = sizeof ( obuf ) , " read file len \n " ) ;
ok ( memcmp ( obuf , ibuf , written ) = = 0 , " content check \n " ) ;
2003-05-16 00:52:41 +02:00
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " Client closing... \n " ) ;
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hFile ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
}
2004-05-04 02:43:46 +02:00
ok ( WaitForSingleObject ( serverThread , INFINITE ) = = WAIT_OBJECT_0 , " WaitForSingleObject \n " ) ;
2003-05-16 00:52:41 +02:00
CloseHandle ( hnp ) ;
2019-09-22 23:21:01 +02:00
if ( winetest_debug > 1 ) trace ( " exerciseServer returning \n " ) ;
2003-05-16 00:52:41 +02:00
}
2004-05-04 06:13:05 +02:00
static void test_NamedPipe_2 ( void )
2003-05-16 00:52:41 +02:00
{
HANDLE serverThread ;
DWORD serverThreadId ;
HANDLE alarmThread ;
DWORD alarmThreadId ;
2003-05-20 05:58:35 +02:00
trace ( " test_NamedPipe_2 starting \n " ) ;
2010-04-30 18:38:59 +02:00
/* Set up a twenty second timeout */
2013-10-21 10:02:23 +02:00
alarm_event = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
2010-05-22 21:06:32 +02:00
SetLastError ( 0xdeadbeef ) ;
2010-04-30 18:38:59 +02:00
alarmThread = CreateThread ( NULL , 0 , alarmThreadMain , ( void * ) 20000 , 0 , & alarmThreadId ) ;
2010-05-22 21:06:32 +02:00
ok ( alarmThread ! = NULL , " CreateThread failed: %d \n " , GetLastError ( ) ) ;
2003-05-16 00:52:41 +02:00
2010-05-22 21:06:32 +02:00
/* The servers we're about to exercise do try to clean up carefully,
* but to reduce the chance of a test failure due to a pipe handle
2003-05-16 00:52:41 +02:00
* leak in the test code , we ' ll use a different pipe name for each server .
*/
/* Try server #1 */
2010-05-22 21:06:32 +02:00
SetLastError ( 0xdeadbeef ) ;
2004-05-04 02:43:46 +02:00
serverThread = CreateThread ( NULL , 0 , serverThreadMain1 , ( void * ) 8 , 0 , & serverThreadId ) ;
2010-05-22 21:06:32 +02:00
ok ( serverThread ! = NULL , " CreateThread failed: %d \n " , GetLastError ( ) ) ;
2019-09-22 23:21:01 +02:00
exerciseServer ( PIPENAME " serverThreadMain1 " , serverThread ) ;
2003-05-16 00:52:41 +02:00
/* Try server #2 */
2010-05-22 21:06:32 +02:00
SetLastError ( 0xdeadbeef ) ;
2003-05-16 00:52:41 +02:00
serverThread = CreateThread ( NULL , 0 , serverThreadMain2 , 0 , 0 , & serverThreadId ) ;
2010-05-22 21:06:32 +02:00
ok ( serverThread ! = NULL , " CreateThread failed: %d \n " , GetLastError ( ) ) ;
2019-09-22 23:21:01 +02:00
exerciseServer ( PIPENAME " serverThreadMain2 " , serverThread ) ;
2003-05-16 00:52:41 +02:00
/* Try server #3 */
2010-05-22 21:06:32 +02:00
SetLastError ( 0xdeadbeef ) ;
2003-05-16 00:52:41 +02:00
serverThread = CreateThread ( NULL , 0 , serverThreadMain3 , 0 , 0 , & serverThreadId ) ;
2010-05-22 21:06:32 +02:00
ok ( serverThread ! = NULL , " CreateThread failed: %d \n " , GetLastError ( ) ) ;
2019-09-22 23:21:01 +02:00
exerciseServer ( PIPENAME " serverThreadMain3 " , serverThread ) ;
2003-05-16 00:52:41 +02:00
2009-02-20 20:39:44 +01:00
/* Try server #4 */
2010-05-22 21:06:32 +02:00
SetLastError ( 0xdeadbeef ) ;
2009-02-20 20:39:44 +01:00
serverThread = CreateThread ( NULL , 0 , serverThreadMain4 , 0 , 0 , & serverThreadId ) ;
2010-05-22 21:06:32 +02:00
ok ( serverThread ! = NULL , " CreateThread failed: %d \n " , GetLastError ( ) ) ;
2019-09-22 23:21:01 +02:00
exerciseServer ( PIPENAME " serverThreadMain4 " , serverThread ) ;
2009-02-20 20:39:44 +01:00
2012-06-14 20:38:19 +02:00
/* Try server #5 */
SetLastError ( 0xdeadbeef ) ;
serverThread = CreateThread ( NULL , 0 , serverThreadMain5 , 0 , 0 , & serverThreadId ) ;
ok ( serverThread ! = NULL , " CreateThread failed: %d \n " , GetLastError ( ) ) ;
2019-09-22 23:21:01 +02:00
exerciseServer ( PIPENAME " serverThreadMain5 " , serverThread ) ;
2012-06-14 20:38:19 +02:00
2004-05-04 02:43:46 +02:00
ok ( SetEvent ( alarm_event ) , " SetEvent \n " ) ;
CloseHandle ( alarm_event ) ;
2017-11-28 17:38:22 +01:00
if ( winetest_debug > 1 ) trace ( " test_NamedPipe_2 returning \n " ) ;
2003-05-16 00:52:41 +02:00
}
2005-03-22 22:14:00 +01:00
static int test_DisconnectNamedPipe ( void )
2003-05-16 00:52:41 +02:00
{
HANDLE hnp ;
HANDLE hFile ;
2004-05-04 06:13:05 +02:00
static const char obuf [ ] = " Bit Bucket " ;
2003-05-16 00:52:41 +02:00
char ibuf [ 32 ] ;
DWORD written ;
DWORD readden ;
2009-06-08 23:23:36 +02:00
DWORD ret ;
2003-05-16 00:52:41 +02:00
2008-09-13 14:05:12 +02:00
SetLastError ( 0xdeadbeef ) ;
2013-10-21 10:02:23 +02:00
hnp = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_WAIT ,
2003-05-16 00:52:41 +02:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
2008-09-13 14:05:12 +02:00
if ( ( hnp = = INVALID_HANDLE_VALUE /* Win98 */ | | ! hnp /* Win95 */ )
& & GetLastError ( ) = = ERROR_CALL_NOT_IMPLEMENTED ) {
win_skip ( " Named pipes are not implemented \n " ) ;
2005-03-22 22:14:00 +01:00
return 1 ;
}
2003-05-16 00:52:41 +02:00
ok ( WriteFile ( hnp , obuf , sizeof ( obuf ) , & written , NULL ) = = 0
2004-02-06 06:24:34 +01:00
& & GetLastError ( ) = = ERROR_PIPE_LISTENING , " WriteFile to not-yet-connected pipe \n " ) ;
2003-05-16 00:52:41 +02:00
ok ( ReadFile ( hnp , ibuf , sizeof ( ibuf ) , & readden , NULL ) = = 0
2004-02-06 06:24:34 +01:00
& & GetLastError ( ) = = ERROR_PIPE_LISTENING , " ReadFile from not-yet-connected pipe \n " ) ;
2003-05-16 00:52:41 +02:00
hFile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
2004-02-06 06:24:34 +01:00
ok ( hFile ! = INVALID_HANDLE_VALUE , " CreateFile failed \n " ) ;
2003-02-19 23:06:36 +01:00
/* don't try to do i/o if one side couldn't be opened, as it hangs */
if ( hFile ! = INVALID_HANDLE_VALUE ) {
2003-05-16 00:52:41 +02:00
/* see what happens if server calls DisconnectNamedPipe
* when there are bytes in the pipe
*/
2004-02-06 06:24:34 +01:00
ok ( WriteFile ( hFile , obuf , sizeof ( obuf ) , & written , NULL ) , " WriteFile \n " ) ;
ok ( written = = sizeof ( obuf ) , " write file len \n " ) ;
ok ( DisconnectNamedPipe ( hnp ) , " DisconnectNamedPipe while messages waiting \n " ) ;
2003-05-16 00:52:41 +02:00
ok ( WriteFile ( hFile , obuf , sizeof ( obuf ) , & written , NULL ) = = 0
2004-02-06 06:24:34 +01:00
& & GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " WriteFile to disconnected pipe \n " ) ;
2018-08-16 15:09:49 +02:00
ok ( WriteFile ( hnp , obuf , sizeof ( obuf ) , & written , NULL ) = = 0
& & GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " WriteFile to disconnected pipe \n " ) ;
ok ( ReadFile ( hFile , ibuf , sizeof ( ibuf ) , & readden , NULL ) = = 0
& & GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED ,
" ReadFile from disconnected pipe with bytes waiting \n " ) ;
2003-05-16 00:52:41 +02:00
ok ( ReadFile ( hnp , ibuf , sizeof ( ibuf ) , & readden , NULL ) = = 0
& & GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED ,
2004-02-06 06:24:34 +01:00
" ReadFile from disconnected pipe with bytes waiting \n " ) ;
2017-10-04 15:17:35 +02:00
2007-04-16 14:51:29 +02:00
ok ( ! DisconnectNamedPipe ( hnp ) & & GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED ,
" DisconnectNamedPipe worked twice \n " ) ;
2009-06-08 23:23:36 +02:00
ret = WaitForSingleObject ( hFile , 0 ) ;
ok ( ret = = WAIT_TIMEOUT , " WaitForSingleObject returned %X \n " , ret ) ;
2017-10-04 15:17:35 +02:00
ret = PeekNamedPipe ( hFile , NULL , 0 , NULL , & readden , NULL ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " PeekNamedPipe returned %x (%u) \n " ,
ret , GetLastError ( ) ) ;
ret = PeekNamedPipe ( hnp , NULL , 0 , NULL , & readden , NULL ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_BAD_PIPE , " PeekNamedPipe returned %x (%u) \n " ,
ret , GetLastError ( ) ) ;
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hFile ) , " CloseHandle \n " ) ;
2003-02-19 23:06:36 +01:00
}
2004-02-06 06:24:34 +01:00
ok ( CloseHandle ( hnp ) , " CloseHandle \n " ) ;
2003-05-16 00:52:41 +02:00
2005-03-22 22:14:00 +01:00
return 0 ;
2003-02-19 23:06:36 +01:00
}
2005-06-05 19:57:10 +02:00
static void test_CreatePipe ( void )
{
SECURITY_ATTRIBUTES pipe_attr ;
HANDLE piperead , pipewrite ;
DWORD written ;
DWORD read ;
2007-01-12 20:59:22 +01:00
DWORD i , size ;
BYTE * buffer ;
2005-06-05 19:57:10 +02:00
char readbuf [ 32 ] ;
2011-08-22 11:02:51 +02:00
user_apc_ran = FALSE ;
2020-09-22 12:24:19 +02:00
ok ( QueueUserAPC ( user_apc , GetCurrentThread ( ) , 0 ) , " couldn't create user apc \n " ) ;
2011-08-22 11:02:51 +02:00
2005-06-05 19:57:10 +02:00
pipe_attr . nLength = sizeof ( SECURITY_ATTRIBUTES ) ;
pipe_attr . bInheritHandle = TRUE ;
2011-08-22 11:02:51 +02:00
pipe_attr . lpSecurityDescriptor = NULL ;
2005-06-05 19:57:10 +02:00
ok ( CreatePipe ( & piperead , & pipewrite , & pipe_attr , 0 ) ! = 0 , " CreatePipe failed \n " ) ;
2017-03-30 14:02:49 +02:00
test_pipe_info ( piperead , FILE_PIPE_SERVER_END , 4096 , 4096 , 1 ) ;
test_pipe_info ( pipewrite , 0 , 4096 , 4096 , 1 ) ;
2018-08-20 19:29:30 +02:00
test_file_access ( piperead , SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
| FILE_READ_ATTRIBUTES | FILE_READ_PROPERTIES | FILE_READ_DATA ) ;
test_file_access ( pipewrite , SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
| FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_APPEND_DATA
| FILE_WRITE_DATA ) ;
2017-03-30 14:02:49 +02:00
2005-06-05 19:57:10 +02:00
ok ( WriteFile ( pipewrite , PIPENAME , sizeof ( PIPENAME ) , & written , NULL ) , " Write to anonymous pipe failed \n " ) ;
2006-10-10 01:06:48 +02:00
ok ( written = = sizeof ( PIPENAME ) , " Write to anonymous pipe wrote %d bytes \n " , written ) ;
2005-06-05 19:57:10 +02:00
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , NULL ) , " Read from non empty pipe failed \n " ) ;
2006-10-10 01:06:48 +02:00
ok ( read = = sizeof ( PIPENAME ) , " Read from anonymous pipe got %d bytes \n " , read ) ;
2007-01-12 20:59:22 +01:00
ok ( CloseHandle ( pipewrite ) , " CloseHandle for the write pipe failed \n " ) ;
ok ( CloseHandle ( piperead ) , " CloseHandle for the read pipe failed \n " ) ;
2005-06-05 19:57:10 +02:00
/* Now write another chunk*/
ok ( CreatePipe ( & piperead , & pipewrite , & pipe_attr , 0 ) ! = 0 , " CreatePipe failed \n " ) ;
ok ( WriteFile ( pipewrite , PIPENAME , sizeof ( PIPENAME ) , & written , NULL ) , " Write to anonymous pipe failed \n " ) ;
2006-10-10 01:06:48 +02:00
ok ( written = = sizeof ( PIPENAME ) , " Write to anonymous pipe wrote %d bytes \n " , written ) ;
2005-06-05 19:57:10 +02:00
/* and close the write end, read should still succeed*/
ok ( CloseHandle ( pipewrite ) , " CloseHandle for the Write Pipe failed \n " ) ;
2017-01-07 14:42:38 +01:00
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , NULL ) , " Read from broken pipe with pending data failed \n " ) ;
ok ( read = = sizeof ( PIPENAME ) , " Read from anonymous pipe got %d bytes \n " , read ) ;
2005-06-05 19:57:10 +02:00
/* But now we need to get informed that the pipe is closed */
2005-11-14 16:11:11 +01:00
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , NULL ) = = 0 , " Broken pipe not detected \n " ) ;
2007-01-12 20:59:22 +01:00
ok ( CloseHandle ( piperead ) , " CloseHandle for the read pipe failed \n " ) ;
/* Try bigger chunks */
size = 32768 ;
buffer = HeapAlloc ( GetProcessHeap ( ) , 0 , size ) ;
for ( i = 0 ; i < size ; i + + ) buffer [ i ] = i ;
2008-11-14 14:00:12 +01:00
ok ( CreatePipe ( & piperead , & pipewrite , & pipe_attr , ( size + 24 ) ) ! = 0 , " CreatePipe failed \n " ) ;
2007-01-12 20:59:22 +01:00
ok ( WriteFile ( pipewrite , buffer , size , & written , NULL ) , " Write to anonymous pipe failed \n " ) ;
ok ( written = = size , " Write to anonymous pipe wrote %d bytes \n " , written ) ;
/* and close the write end, read should still succeed*/
ok ( CloseHandle ( pipewrite ) , " CloseHandle for the Write Pipe failed \n " ) ;
memset ( buffer , 0 , size ) ;
2017-01-07 14:42:38 +01:00
ok ( ReadFile ( piperead , buffer , size , & read , NULL ) , " Read from broken pipe with pending data failed \n " ) ;
ok ( read = = size , " Read from anonymous pipe got %d bytes \n " , read ) ;
2007-01-12 20:59:22 +01:00
for ( i = 0 ; i < size ; i + + ) ok ( buffer [ i ] = = ( BYTE ) i , " invalid data %x at %x \n " , buffer [ i ] , i ) ;
/* But now we need to get informed that the pipe is closed */
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , NULL ) = = 0 , " Broken pipe not detected \n " ) ;
ok ( CloseHandle ( piperead ) , " CloseHandle for the read pipe failed \n " ) ;
2007-10-20 21:22:26 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , buffer ) ;
2011-08-22 11:02:51 +02:00
ok ( user_apc_ran = = FALSE , " user apc ran, pipe using alertable io mode \n " ) ;
SleepEx ( 0 , TRUE ) ; /* get rid of apc */
2017-03-30 14:02:49 +02:00
ok ( CreatePipe ( & piperead , & pipewrite , & pipe_attr , 1 ) ! = 0 , " CreatePipe failed \n " ) ;
test_pipe_info ( piperead , FILE_PIPE_SERVER_END , 1 , 1 , 1 ) ;
test_pipe_info ( pipewrite , 0 , 1 , 1 , 1 ) ;
ok ( CloseHandle ( pipewrite ) , " CloseHandle for the Write Pipe failed \n " ) ;
ok ( CloseHandle ( piperead ) , " CloseHandle for the read pipe failed \n " ) ;
2005-06-05 19:57:10 +02:00
}
2003-02-19 23:06:36 +01:00
2015-11-23 07:22:27 +01:00
static void test_CloseHandle ( void )
{
static const char testdata [ ] = " Hello World " ;
2015-11-23 07:23:45 +01:00
DWORD state , numbytes ;
2015-11-23 07:22:27 +01:00
HANDLE hpipe , hfile ;
char buffer [ 32 ] ;
BOOL ret ;
hpipe = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( hpipe ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed with %u \n " , GetLastError ( ) ) ;
hfile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hfile ! = INVALID_HANDLE_VALUE , " CreateFile failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
ret = WriteFile ( hpipe , testdata , sizeof ( testdata ) , & numbytes , NULL ) ;
ok ( ret , " WriteFile failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) , " expected sizeof(testdata), got %u \n " , numbytes ) ;
numbytes = 0xdeadbeef ;
ret = PeekNamedPipe ( hfile , NULL , 0 , NULL , & numbytes , NULL ) ;
ok ( ret , " PeekNamedPipe failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) , " expected sizeof(testdata), got %u \n " , numbytes ) ;
ret = CloseHandle ( hpipe ) ;
ok ( ret , " CloseHandle failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
ret = ReadFile ( hfile , buffer , 0 , & numbytes , NULL ) ;
2017-03-23 15:42:25 +01:00
ok ( ret , " ReadFile failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:22:27 +01:00
ok ( numbytes = = 0 , " expected 0, got %u \n " , numbytes ) ;
2017-10-04 15:17:35 +02:00
numbytes = 0xdeadbeef ;
ret = PeekNamedPipe ( hfile , NULL , 0 , NULL , & numbytes , NULL ) ;
ok ( ret , " PeekNamedPipe failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) , " expected sizeof(testdata), got %u \n " , numbytes ) ;
2015-11-23 07:22:27 +01:00
numbytes = 0xdeadbeef ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
ret = ReadFile ( hfile , buffer , sizeof ( buffer ) , & numbytes , NULL ) ;
ok ( ret , " ReadFile failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) , " expected sizeof(testdata), got %u \n " , numbytes ) ;
2015-11-23 07:23:45 +01:00
ret = GetNamedPipeHandleStateA ( hfile , & state , NULL , NULL , NULL , NULL , 0 ) ;
ok ( ret , " GetNamedPipeHandleState failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:24:07 +01:00
state = PIPE_READMODE_MESSAGE | PIPE_WAIT ;
ret = SetNamedPipeHandleState ( hfile , & state , NULL , NULL ) ;
ok ( ret , " SetNamedPipeHandleState failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:45 +01:00
2015-11-23 07:22:27 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buffer , 0 , & numbytes , NULL ) ;
ok ( ! ret , " ReadFile unexpectedly succeeded \n " ) ;
ok ( GetLastError ( ) = = ERROR_BROKEN_PIPE , " expected ERROR_BROKEN_PIPE, got %u \n " , GetLastError ( ) ) ;
2017-10-04 15:17:35 +02:00
numbytes = 0xdeadbeef ;
ret = PeekNamedPipe ( hfile , NULL , 0 , NULL , & numbytes , NULL ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_BROKEN_PIPE , " PeekNamedPipe returned %x (%u) \n " ,
ret , GetLastError ( ) ) ;
ok ( numbytes = = 0xdeadbeef , " numbytes = %u \n " , numbytes ) ;
2015-11-23 07:23:04 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( hfile , testdata , sizeof ( testdata ) , & numbytes , NULL ) ;
ok ( ! ret , " WriteFile unexpectedly succeeded \n " ) ;
2018-08-08 22:00:55 +02:00
ok ( GetLastError ( ) = = ERROR_NO_DATA , " expected ERROR_NO_DATA, got %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:04 +01:00
2015-11-23 07:22:27 +01:00
CloseHandle ( hfile ) ;
2015-11-23 07:22:43 +01:00
hpipe = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( hpipe ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed with %u \n " , GetLastError ( ) ) ;
hfile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hfile ! = INVALID_HANDLE_VALUE , " CreateFile failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
ret = WriteFile ( hpipe , testdata , 0 , & numbytes , NULL ) ;
ok ( ret , " WriteFile failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = 0 , " expected 0, got %u \n " , numbytes ) ;
ret = CloseHandle ( hpipe ) ;
ok ( ret , " CloseHandle failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
ret = ReadFile ( hfile , buffer , sizeof ( buffer ) , & numbytes , NULL ) ;
2017-03-23 15:42:25 +01:00
ok ( ret , " ReadFile failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:22:43 +01:00
ok ( numbytes = = 0 , " expected 0, got %u \n " , numbytes ) ;
2017-01-19 18:17:15 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buffer , 0 , & numbytes , NULL ) ;
ok ( ! ret , " ReadFile unexpectedly succeeded \n " ) ;
2017-03-23 15:42:25 +01:00
ok ( GetLastError ( ) = = ERROR_BROKEN_PIPE , " expected ERROR_BROKEN_PIPE, got %u \n " , GetLastError ( ) ) ;
2017-01-19 18:17:15 +01:00
2015-11-23 07:23:45 +01:00
ret = GetNamedPipeHandleStateA ( hfile , & state , NULL , NULL , NULL , NULL , 0 ) ;
ok ( ret , " GetNamedPipeHandleState failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:24:07 +01:00
state = PIPE_READMODE_MESSAGE | PIPE_WAIT ;
ret = SetNamedPipeHandleState ( hfile , & state , NULL , NULL ) ;
ok ( ret , " SetNamedPipeHandleState failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:45 +01:00
2015-11-23 07:22:43 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hfile , buffer , 0 , & numbytes , NULL ) ;
ok ( ! ret , " ReadFile unexpectedly succeeded \n " ) ;
2017-03-23 15:42:25 +01:00
ok ( GetLastError ( ) = = ERROR_BROKEN_PIPE , " expected ERROR_BROKEN_PIPE, got %u \n " , GetLastError ( ) ) ;
2015-11-23 07:22:43 +01:00
2015-11-23 07:23:04 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( hfile , testdata , sizeof ( testdata ) , & numbytes , NULL ) ;
ok ( ! ret , " WriteFile unexpectedly succeeded \n " ) ;
2018-08-08 22:00:55 +02:00
ok ( GetLastError ( ) = = ERROR_NO_DATA , " expected ERROR_NO_DATA, got %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:04 +01:00
2015-11-23 07:22:43 +01:00
CloseHandle ( hfile ) ;
2015-11-23 07:22:27 +01:00
/* repeat test with hpipe <-> hfile swapped */
hpipe = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( hpipe ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed with %u \n " , GetLastError ( ) ) ;
hfile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hfile ! = INVALID_HANDLE_VALUE , " CreateFile failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
ret = WriteFile ( hfile , testdata , sizeof ( testdata ) , & numbytes , NULL ) ;
ok ( ret , " WriteFile failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) , " expected sizeof(testdata), got %u \n " , numbytes ) ;
numbytes = 0xdeadbeef ;
ret = PeekNamedPipe ( hpipe , NULL , 0 , NULL , & numbytes , NULL ) ;
ok ( ret , " PeekNamedPipe failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) , " expected sizeof(testdata), got %u \n " , numbytes ) ;
ret = CloseHandle ( hfile ) ;
ok ( ret , " CloseHandle failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
ret = ReadFile ( hpipe , buffer , 0 , & numbytes , NULL ) ;
2017-03-23 15:42:25 +01:00
ok ( ret | | GetLastError ( ) = = ERROR_MORE_DATA /* >= Win 8 */ ,
2015-11-23 07:22:27 +01:00
" ReadFile failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = 0 , " expected 0, got %u \n " , numbytes ) ;
2017-10-04 15:17:35 +02:00
numbytes = 0xdeadbeef ;
ret = PeekNamedPipe ( hpipe , NULL , 0 , NULL , & numbytes , NULL ) ;
ok ( ret , " PeekNamedPipe failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) , " expected sizeof(testdata), got %u \n " , numbytes ) ;
2015-11-23 07:22:27 +01:00
numbytes = 0xdeadbeef ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
ret = ReadFile ( hpipe , buffer , sizeof ( buffer ) , & numbytes , NULL ) ;
ok ( ret , " ReadFile failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = sizeof ( testdata ) , " expected sizeof(testdata), got %u \n " , numbytes ) ;
2015-11-23 07:23:45 +01:00
ret = GetNamedPipeHandleStateA ( hpipe , & state , NULL , NULL , NULL , NULL , 0 ) ;
ok ( ret , " GetNamedPipeHandleState failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:24:07 +01:00
state = PIPE_READMODE_MESSAGE | PIPE_WAIT ;
ret = SetNamedPipeHandleState ( hpipe , & state , NULL , NULL ) ;
ok ( ret , " SetNamedPipeHandleState failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:45 +01:00
2015-11-23 07:22:27 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hpipe , buffer , 0 , & numbytes , NULL ) ;
ok ( ! ret , " ReadFile unexpectedly succeeded \n " ) ;
ok ( GetLastError ( ) = = ERROR_BROKEN_PIPE , " expected ERROR_BROKEN_PIPE, got %u \n " , GetLastError ( ) ) ;
2017-10-04 15:17:35 +02:00
numbytes = 0xdeadbeef ;
ret = PeekNamedPipe ( hpipe , NULL , 0 , NULL , & numbytes , NULL ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_BROKEN_PIPE , " PeekNamedPipe returned %x (%u) \n " ,
ret , GetLastError ( ) ) ;
ok ( numbytes = = 0xdeadbeef , " numbytes = %u \n " , numbytes ) ;
2015-11-23 07:23:04 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( hpipe , testdata , sizeof ( testdata ) , & numbytes , NULL ) ;
ok ( ! ret , " WriteFile unexpectedly succeeded \n " ) ;
2018-08-08 22:00:55 +02:00
ok ( GetLastError ( ) = = ERROR_NO_DATA , " expected ERROR_NO_DATA, got %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:04 +01:00
2015-11-23 07:22:27 +01:00
CloseHandle ( hpipe ) ;
2015-11-23 07:22:43 +01:00
hpipe = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( hpipe ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed with %u \n " , GetLastError ( ) ) ;
hfile = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( hfile ! = INVALID_HANDLE_VALUE , " CreateFile failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
ret = WriteFile ( hfile , testdata , 0 , & numbytes , NULL ) ;
ok ( ret , " WriteFile failed with %u \n " , GetLastError ( ) ) ;
ok ( numbytes = = 0 , " expected 0, got %u \n " , numbytes ) ;
ret = CloseHandle ( hfile ) ;
ok ( ret , " CloseHandle failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
ret = ReadFile ( hpipe , buffer , sizeof ( buffer ) , & numbytes , NULL ) ;
2017-03-23 15:42:25 +01:00
ok ( ret , " ReadFile failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:22:43 +01:00
ok ( numbytes = = 0 , " expected 0, got %u \n " , numbytes ) ;
2017-01-19 18:17:15 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hpipe , buffer , 0 , & numbytes , NULL ) ;
ok ( ! ret , " ReadFile unexpectedly succeeded \n " ) ;
ok ( GetLastError ( ) = = ERROR_BROKEN_PIPE , " expected ERROR_BROKEN_PIPE, got %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:45 +01:00
ret = GetNamedPipeHandleStateA ( hpipe , & state , NULL , NULL , NULL , NULL , 0 ) ;
ok ( ret , " GetNamedPipeHandleState failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:24:07 +01:00
state = PIPE_READMODE_MESSAGE | PIPE_WAIT ;
ret = SetNamedPipeHandleState ( hpipe , & state , NULL , NULL ) ;
ok ( ret , " SetNamedPipeHandleState failed with %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:45 +01:00
2015-11-23 07:22:43 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( hpipe , buffer , 0 , & numbytes , NULL ) ;
ok ( ! ret , " ReadFile unexpectedly succeeded \n " ) ;
ok ( GetLastError ( ) = = ERROR_BROKEN_PIPE , " expected ERROR_BROKEN_PIPE, got %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:04 +01:00
SetLastError ( 0xdeadbeef ) ;
ret = WriteFile ( hpipe , testdata , sizeof ( testdata ) , & numbytes , NULL ) ;
ok ( ! ret , " WriteFile unexpectedly succeeded \n " ) ;
2018-08-08 22:00:55 +02:00
ok ( GetLastError ( ) = = ERROR_NO_DATA , " expected ERROR_NO_DATA, got %u \n " , GetLastError ( ) ) ;
2015-11-23 07:23:04 +01:00
2015-11-23 07:22:43 +01:00
CloseHandle ( hpipe ) ;
2015-11-23 07:22:27 +01:00
}
2007-03-06 19:00:15 +01:00
struct named_pipe_client_params
{
DWORD security_flags ;
HANDLE token ;
BOOL revert ;
} ;
# define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
static DWORD CALLBACK named_pipe_client_func ( LPVOID p )
{
2009-03-11 09:39:16 +01:00
struct named_pipe_client_params * params = p ;
2007-03-06 19:00:15 +01:00
HANDLE pipe ;
BOOL ret ;
const char message [ ] = " Test " ;
DWORD bytes_read , bytes_written ;
char dummy ;
TOKEN_PRIVILEGES * Privileges = NULL ;
if ( params - > token )
{
if ( params - > revert )
{
/* modify the token so we can tell if the pipe impersonation
* token reverts to the process token */
ret = AdjustTokenPrivileges ( params - > token , TRUE , NULL , 0 , NULL , NULL ) ;
ok ( ret , " AdjustTokenPrivileges failed with error %d \n " , GetLastError ( ) ) ;
}
ret = SetThreadToken ( NULL , params - > token ) ;
ok ( ret , " SetThreadToken failed with error %d \n " , GetLastError ( ) ) ;
}
else
{
DWORD Size = 0 ;
HANDLE process_token ;
ret = OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES , & process_token ) ;
ok ( ret , " OpenProcessToken failed with error %d \n " , GetLastError ( ) ) ;
ret = GetTokenInformation ( process_token , TokenPrivileges , NULL , 0 , & Size ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_INSUFFICIENT_BUFFER , " GetTokenInformation(TokenPrivileges) failed with %d \n " , GetLastError ( ) ) ;
2007-06-27 00:12:59 +02:00
Privileges = HeapAlloc ( GetProcessHeap ( ) , 0 , Size ) ;
2007-03-06 19:00:15 +01:00
ret = GetTokenInformation ( process_token , TokenPrivileges , Privileges , Size , & Size ) ;
ok ( ret , " GetTokenInformation(TokenPrivileges) failed with %d \n " , GetLastError ( ) ) ;
ret = AdjustTokenPrivileges ( process_token , TRUE , NULL , 0 , NULL , NULL ) ;
ok ( ret , " AdjustTokenPrivileges failed with error %d \n " , GetLastError ( ) ) ;
CloseHandle ( process_token ) ;
}
2013-10-21 10:02:23 +02:00
pipe = CreateFileA ( PIPE_NAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , params - > security_flags , NULL ) ;
2007-03-06 19:00:15 +01:00
ok ( pipe ! = INVALID_HANDLE_VALUE , " CreateFile for pipe failed with error %d \n " , GetLastError ( ) ) ;
ret = WriteFile ( pipe , message , sizeof ( message ) , & bytes_written , NULL ) ;
ok ( ret , " WriteFile failed with error %d \n " , GetLastError ( ) ) ;
ret = ReadFile ( pipe , & dummy , sizeof ( dummy ) , & bytes_read , NULL ) ;
ok ( ret , " ReadFile failed with error %d \n " , GetLastError ( ) ) ;
if ( params - > token )
{
if ( params - > revert )
{
ret = RevertToSelf ( ) ;
ok ( ret , " RevertToSelf failed with error %d \n " , GetLastError ( ) ) ;
}
else
{
ret = AdjustTokenPrivileges ( params - > token , TRUE , NULL , 0 , NULL , NULL ) ;
ok ( ret , " AdjustTokenPrivileges failed with error %d \n " , GetLastError ( ) ) ;
}
}
else
{
HANDLE process_token ;
ret = OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_ADJUST_PRIVILEGES , & process_token ) ;
ok ( ret , " OpenProcessToken failed with error %d \n " , GetLastError ( ) ) ;
ret = AdjustTokenPrivileges ( process_token , FALSE , Privileges , 0 , NULL , NULL ) ;
ok ( ret , " AdjustTokenPrivileges failed with error %d \n " , GetLastError ( ) ) ;
HeapFree ( GetProcessHeap ( ) , 0 , Privileges ) ;
CloseHandle ( process_token ) ;
}
ret = WriteFile ( pipe , message , sizeof ( message ) , & bytes_written , NULL ) ;
ok ( ret , " WriteFile failed with error %d \n " , GetLastError ( ) ) ;
ret = ReadFile ( pipe , & dummy , sizeof ( dummy ) , & bytes_read , NULL ) ;
ok ( ret , " ReadFile failed with error %d \n " , GetLastError ( ) ) ;
CloseHandle ( pipe ) ;
return 0 ;
}
static HANDLE make_impersonation_token ( DWORD Access , SECURITY_IMPERSONATION_LEVEL ImpersonationLevel )
{
HANDLE ProcessToken ;
HANDLE Token = NULL ;
BOOL ret ;
ret = OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_DUPLICATE , & ProcessToken ) ;
ok ( ret , " OpenProcessToken failed with error %d \n " , GetLastError ( ) ) ;
2007-03-16 22:37:46 +01:00
ret = pDuplicateTokenEx ( ProcessToken , Access , NULL , ImpersonationLevel , TokenImpersonation , & Token ) ;
2007-03-06 19:00:15 +01:00
ok ( ret , " DuplicateToken failed with error %d \n " , GetLastError ( ) ) ;
CloseHandle ( ProcessToken ) ;
return Token ;
}
static void test_ImpersonateNamedPipeClient ( HANDLE hClientToken , DWORD security_flags , BOOL revert , void ( * test_func ) ( int , HANDLE ) )
{
HANDLE hPipeServer ;
BOOL ret ;
DWORD dwTid ;
HANDLE hThread ;
char buffer [ 256 ] ;
DWORD dwBytesRead ;
DWORD error ;
struct named_pipe_client_params params ;
char dummy = 0 ;
DWORD dwBytesWritten ;
HANDLE hToken = NULL ;
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel ;
DWORD size ;
2013-10-21 10:02:23 +02:00
hPipeServer = CreateNamedPipeA ( PIPE_NAME , PIPE_ACCESS_DUPLEX , PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT , 1 , 100 , 100 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
2007-03-06 19:00:15 +01:00
ok ( hPipeServer ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed with error %d \n " , GetLastError ( ) ) ;
params . security_flags = security_flags ;
params . token = hClientToken ;
params . revert = revert ;
hThread = CreateThread ( NULL , 0 , named_pipe_client_func , & params , 0 , & dwTid ) ;
ok ( hThread ! = NULL , " CreateThread failed with error %d \n " , GetLastError ( ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = ImpersonateNamedPipeClient ( hPipeServer ) ;
error = GetLastError ( ) ;
2008-11-17 13:16:26 +01:00
ok ( ret /* win2k3 */ | | ( error = = ERROR_CANNOT_IMPERSONATE ) ,
2008-09-02 08:02:39 +02:00
" ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d \n " , GetLastError ( ) ) ;
2007-03-06 19:00:15 +01:00
ret = ConnectNamedPipe ( hPipeServer , NULL ) ;
ok ( ret | | ( GetLastError ( ) = = ERROR_PIPE_CONNECTED ) , " ConnectNamedPipe failed with error %d \n " , GetLastError ( ) ) ;
ret = ReadFile ( hPipeServer , buffer , sizeof ( buffer ) , & dwBytesRead , NULL ) ;
ok ( ret , " ReadFile failed with error %d \n " , GetLastError ( ) ) ;
ret = ImpersonateNamedPipeClient ( hPipeServer ) ;
ok ( ret , " ImpersonateNamedPipeClient failed with error %d \n " , GetLastError ( ) ) ;
ret = OpenThreadToken ( GetCurrentThread ( ) , TOKEN_QUERY , FALSE , & hToken ) ;
ok ( ret , " OpenThreadToken failed with error %d \n " , GetLastError ( ) ) ;
( * test_func ) ( 0 , hToken ) ;
2007-08-15 17:08:50 +02:00
ImpersonationLevel = 0xdeadbeef ; /* to avoid false positives */
2007-03-06 19:00:15 +01:00
ret = GetTokenInformation ( hToken , TokenImpersonationLevel , & ImpersonationLevel , sizeof ( ImpersonationLevel ) , & size ) ;
ok ( ret , " GetTokenInformation(TokenImpersonationLevel) failed with error %d \n " , GetLastError ( ) ) ;
2007-08-15 17:08:50 +02:00
ok ( ImpersonationLevel = = SecurityImpersonation , " ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d \n " , SecurityImpersonation , ImpersonationLevel ) ;
2007-03-06 19:00:15 +01:00
CloseHandle ( hToken ) ;
RevertToSelf ( ) ;
ret = WriteFile ( hPipeServer , & dummy , sizeof ( dummy ) , & dwBytesWritten , NULL ) ;
ok ( ret , " WriteFile failed with error %d \n " , GetLastError ( ) ) ;
ret = ReadFile ( hPipeServer , buffer , sizeof ( buffer ) , & dwBytesRead , NULL ) ;
ok ( ret , " ReadFile failed with error %d \n " , GetLastError ( ) ) ;
ret = ImpersonateNamedPipeClient ( hPipeServer ) ;
ok ( ret , " ImpersonateNamedPipeClient failed with error %d \n " , GetLastError ( ) ) ;
ret = OpenThreadToken ( GetCurrentThread ( ) , TOKEN_QUERY , FALSE , & hToken ) ;
ok ( ret , " OpenThreadToken failed with error %d \n " , GetLastError ( ) ) ;
( * test_func ) ( 1 , hToken ) ;
CloseHandle ( hToken ) ;
RevertToSelf ( ) ;
ret = WriteFile ( hPipeServer , & dummy , sizeof ( dummy ) , & dwBytesWritten , NULL ) ;
ok ( ret , " WriteFile failed with error %d \n " , GetLastError ( ) ) ;
WaitForSingleObject ( hThread , INFINITE ) ;
ret = ImpersonateNamedPipeClient ( hPipeServer ) ;
ok ( ret , " ImpersonateNamedPipeClient failed with error %d \n " , GetLastError ( ) ) ;
RevertToSelf ( ) ;
CloseHandle ( hThread ) ;
CloseHandle ( hPipeServer ) ;
}
static BOOL are_all_privileges_disabled ( HANDLE hToken )
{
BOOL ret ;
TOKEN_PRIVILEGES * Privileges = NULL ;
DWORD Size = 0 ;
BOOL all_privs_disabled = TRUE ;
DWORD i ;
ret = GetTokenInformation ( hToken , TokenPrivileges , NULL , 0 , & Size ) ;
if ( ! ret & & GetLastError ( ) = = ERROR_INSUFFICIENT_BUFFER )
{
Privileges = HeapAlloc ( GetProcessHeap ( ) , 0 , Size ) ;
ret = GetTokenInformation ( hToken , TokenPrivileges , Privileges , Size , & Size ) ;
2007-10-20 21:22:26 +02:00
if ( ! ret )
{
HeapFree ( GetProcessHeap ( ) , 0 , Privileges ) ;
return FALSE ;
}
2007-03-06 19:00:15 +01:00
}
else
return FALSE ;
for ( i = 0 ; i < Privileges - > PrivilegeCount ; i + + )
{
if ( Privileges - > Privileges [ i ] . Attributes & SE_PRIVILEGE_ENABLED )
{
all_privs_disabled = FALSE ;
break ;
}
}
HeapFree ( GetProcessHeap ( ) , 0 , Privileges ) ;
return all_privs_disabled ;
}
static DWORD get_privilege_count ( HANDLE hToken )
{
TOKEN_STATISTICS Statistics ;
DWORD Size = sizeof ( Statistics ) ;
BOOL ret ;
ret = GetTokenInformation ( hToken , TokenStatistics , & Statistics , Size , & Size ) ;
ok ( ret , " GetTokenInformation(TokenStatistics) \n " ) ;
if ( ! ret ) return - 1 ;
return Statistics . PrivilegeCount ;
}
static void test_no_sqos_no_token ( int call_index , HANDLE hToken )
{
DWORD priv_count ;
switch ( call_index )
{
case 0 :
priv_count = get_privilege_count ( hToken ) ;
todo_wine
ok ( priv_count = = 0 , " privilege count should have been 0 instead of %d \n " , priv_count ) ;
break ;
case 1 :
priv_count = get_privilege_count ( hToken ) ;
ok ( priv_count > 0 , " privilege count should now be > 0 instead of 0 \n " ) ;
ok ( ! are_all_privileges_disabled ( hToken ) , " impersonated token should not have been modified \n " ) ;
break ;
default :
ok ( 0 , " shouldn't happen \n " ) ;
}
}
static void test_no_sqos ( int call_index , HANDLE hToken )
{
switch ( call_index )
{
case 0 :
ok ( ! are_all_privileges_disabled ( hToken ) , " token should be a copy of the process one \n " ) ;
break ;
case 1 :
todo_wine
ok ( are_all_privileges_disabled ( hToken ) , " impersonated token should have been modified \n " ) ;
break ;
default :
ok ( 0 , " shouldn't happen \n " ) ;
}
}
static void test_static_context ( int call_index , HANDLE hToken )
{
switch ( call_index )
{
case 0 :
ok ( ! are_all_privileges_disabled ( hToken ) , " token should be a copy of the process one \n " ) ;
break ;
case 1 :
ok ( ! are_all_privileges_disabled ( hToken ) , " impersonated token should not have been modified \n " ) ;
break ;
default :
ok ( 0 , " shouldn't happen \n " ) ;
}
}
static void test_dynamic_context ( int call_index , HANDLE hToken )
{
switch ( call_index )
{
case 0 :
ok ( ! are_all_privileges_disabled ( hToken ) , " token should be a copy of the process one \n " ) ;
break ;
case 1 :
todo_wine
ok ( are_all_privileges_disabled ( hToken ) , " impersonated token should have been modified \n " ) ;
break ;
default :
ok ( 0 , " shouldn't happen \n " ) ;
}
}
static void test_dynamic_context_no_token ( int call_index , HANDLE hToken )
{
switch ( call_index )
{
case 0 :
ok ( are_all_privileges_disabled ( hToken ) , " token should be a copy of the process one \n " ) ;
break ;
case 1 :
ok ( ! are_all_privileges_disabled ( hToken ) , " process token modification should have been detected and impersonation token updated \n " ) ;
break ;
default :
ok ( 0 , " shouldn't happen \n " ) ;
}
}
static void test_no_sqos_revert ( int call_index , HANDLE hToken )
{
DWORD priv_count ;
switch ( call_index )
{
case 0 :
priv_count = get_privilege_count ( hToken ) ;
todo_wine
ok ( priv_count = = 0 , " privilege count should have been 0 instead of %d \n " , priv_count ) ;
break ;
case 1 :
priv_count = get_privilege_count ( hToken ) ;
ok ( priv_count > 0 , " privilege count should now be > 0 instead of 0 \n " ) ;
ok ( ! are_all_privileges_disabled ( hToken ) , " impersonated token should not have been modified \n " ) ;
break ;
default :
ok ( 0 , " shouldn't happen \n " ) ;
}
}
static void test_static_context_revert ( int call_index , HANDLE hToken )
{
switch ( call_index )
{
case 0 :
todo_wine
ok ( are_all_privileges_disabled ( hToken ) , " privileges should have been disabled \n " ) ;
break ;
case 1 :
todo_wine
ok ( are_all_privileges_disabled ( hToken ) , " impersonated token should not have been modified \n " ) ;
break ;
default :
ok ( 0 , " shouldn't happen \n " ) ;
}
}
static void test_dynamic_context_revert ( int call_index , HANDLE hToken )
{
switch ( call_index )
{
case 0 :
todo_wine
ok ( are_all_privileges_disabled ( hToken ) , " privileges should have been disabled \n " ) ;
break ;
case 1 :
ok ( ! are_all_privileges_disabled ( hToken ) , " impersonated token should now be process token \n " ) ;
break ;
default :
ok ( 0 , " shouldn't happen \n " ) ;
}
}
static void test_impersonation ( void )
{
HANDLE hClientToken ;
HANDLE hProcessToken ;
BOOL ret ;
2007-03-16 22:37:46 +01:00
if ( ! pDuplicateTokenEx ) {
skip ( " DuplicateTokenEx not found \n " ) ;
return ;
}
2007-03-06 19:00:15 +01:00
ret = OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_QUERY , & hProcessToken ) ;
if ( ! ret )
{
skip ( " couldn't open process token, skipping impersonation tests \n " ) ;
return ;
}
if ( ! get_privilege_count ( hProcessToken ) | | are_all_privileges_disabled ( hProcessToken ) )
{
skip ( " token didn't have any privileges or they were all disabled. token not suitable for impersonation tests \n " ) ;
CloseHandle ( hProcessToken ) ;
return ;
}
CloseHandle ( hProcessToken ) ;
test_ImpersonateNamedPipeClient ( NULL , 0 , FALSE , test_no_sqos_no_token ) ;
hClientToken = make_impersonation_token ( TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , SecurityImpersonation ) ;
test_ImpersonateNamedPipeClient ( hClientToken , 0 , FALSE , test_no_sqos ) ;
CloseHandle ( hClientToken ) ;
hClientToken = make_impersonation_token ( TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , SecurityImpersonation ) ;
test_ImpersonateNamedPipeClient ( hClientToken ,
SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION , FALSE ,
test_static_context ) ;
CloseHandle ( hClientToken ) ;
hClientToken = make_impersonation_token ( TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , SecurityImpersonation ) ;
test_ImpersonateNamedPipeClient ( hClientToken ,
SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION ,
FALSE , test_dynamic_context ) ;
CloseHandle ( hClientToken ) ;
test_ImpersonateNamedPipeClient ( NULL ,
SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION ,
FALSE , test_dynamic_context_no_token ) ;
hClientToken = make_impersonation_token ( TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , SecurityImpersonation ) ;
test_ImpersonateNamedPipeClient ( hClientToken , 0 , TRUE , test_no_sqos_revert ) ;
CloseHandle ( hClientToken ) ;
hClientToken = make_impersonation_token ( TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , SecurityImpersonation ) ;
test_ImpersonateNamedPipeClient ( hClientToken ,
SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION , TRUE ,
test_static_context_revert ) ;
CloseHandle ( hClientToken ) ;
hClientToken = make_impersonation_token ( TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , SecurityImpersonation ) ;
test_ImpersonateNamedPipeClient ( hClientToken ,
SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION ,
TRUE , test_dynamic_context_revert ) ;
CloseHandle ( hClientToken ) ;
}
2007-07-16 13:12:18 +02:00
struct overlapped_server_args
{
HANDLE pipe_created ;
} ;
static DWORD CALLBACK overlapped_server ( LPVOID arg )
{
OVERLAPPED ol ;
HANDLE pipe ;
int ret , err ;
2009-03-11 09:39:16 +01:00
struct overlapped_server_args * a = arg ;
2007-07-16 13:12:18 +02:00
DWORD num ;
char buf [ 100 ] ;
pipe = CreateNamedPipeA ( " \\ \\ . \\ pipe \\ my pipe " , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX , PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE , 1 , 0 , 0 , 100000 , NULL ) ;
ok ( pipe ! = NULL , " pipe NULL \n " ) ;
ol . hEvent = CreateEventA ( 0 , 1 , 0 , 0 ) ;
ok ( ol . hEvent ! = NULL , " event NULL \n " ) ;
ret = ConnectNamedPipe ( pipe , & ol ) ;
err = GetLastError ( ) ;
ok ( ret = = 0 , " ret %d \n " , ret ) ;
ok ( err = = ERROR_IO_PENDING , " gle %d \n " , err ) ;
SetEvent ( a - > pipe_created ) ;
ret = WaitForSingleObjectEx ( ol . hEvent , INFINITE , 1 ) ;
2007-07-16 16:14:45 +02:00
ok ( ret = = WAIT_OBJECT_0 , " ret %x \n " , ret ) ;
2007-07-16 13:12:18 +02:00
ret = GetOverlappedResult ( pipe , & ol , & num , 1 ) ;
ok ( ret = = 1 , " ret %d \n " , ret ) ;
/* This should block */
ret = ReadFile ( pipe , buf , sizeof ( buf ) , & num , NULL ) ;
2007-07-16 15:27:53 +02:00
ok ( ret = = 1 , " ret %d \n " , ret ) ;
2007-07-16 13:12:18 +02:00
DisconnectNamedPipe ( pipe ) ;
2016-10-20 21:31:51 +02:00
ret = ConnectNamedPipe ( pipe , & ol ) ;
err = GetLastError ( ) ;
ok ( ret = = 0 , " ret %d \n " , ret ) ;
ok ( err = = ERROR_IO_PENDING , " gle %d \n " , err ) ;
CancelIo ( pipe ) ;
ret = WaitForSingleObjectEx ( ol . hEvent , INFINITE , 1 ) ;
ok ( ret = = WAIT_OBJECT_0 , " ret %x \n " , ret ) ;
ret = GetOverlappedResult ( pipe , & ol , & num , 1 ) ;
err = GetLastError ( ) ;
ok ( ret = = 0 , " ret %d \n " , ret ) ;
ok ( err = = ERROR_OPERATION_ABORTED , " gle %d \n " , err ) ;
2007-07-16 13:12:18 +02:00
CloseHandle ( ol . hEvent ) ;
CloseHandle ( pipe ) ;
return 1 ;
}
static void test_overlapped ( void )
{
DWORD tid , num ;
HANDLE thread , pipe ;
2011-01-12 20:54:24 +01:00
BOOL ret ;
2007-07-16 13:12:18 +02:00
struct overlapped_server_args args ;
args . pipe_created = CreateEventA ( 0 , 1 , 0 , 0 ) ;
thread = CreateThread ( NULL , 0 , overlapped_server , & args , 0 , & tid ) ;
WaitForSingleObject ( args . pipe_created , INFINITE ) ;
pipe = CreateFileA ( " \\ \\ . \\ pipe \\ my pipe " , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , NULL ) ;
ok ( pipe ! = INVALID_HANDLE_VALUE , " cf failed \n " ) ;
/* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
Sleep ( 1 ) ;
ret = WriteFile ( pipe , " x " , 1 , & num , NULL ) ;
2011-01-12 20:54:24 +01:00
ok ( ret , " WriteFile failed with error %d \n " , GetLastError ( ) ) ;
2007-07-16 13:12:18 +02:00
WaitForSingleObject ( thread , INFINITE ) ;
CloseHandle ( pipe ) ;
CloseHandle ( args . pipe_created ) ;
CloseHandle ( thread ) ;
}
2016-04-07 08:45:53 +02:00
static void test_overlapped_error ( void )
{
HANDLE pipe , file , event ;
DWORD err , numbytes ;
OVERLAPPED overlapped ;
BOOL ret ;
event = CreateEventA ( NULL , TRUE , FALSE , NULL ) ;
ok ( event ! = NULL , " CreateEventA failed with %u \n " , GetLastError ( ) ) ;
pipe = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_WAIT_FOREVER , NULL ) ;
ok ( pipe ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed with %u \n " , GetLastError ( ) ) ;
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = event ;
ret = ConnectNamedPipe ( pipe , & overlapped ) ;
err = GetLastError ( ) ;
ok ( ret = = FALSE , " ConnectNamedPipe succeeded \n " ) ;
ok ( err = = ERROR_IO_PENDING , " expected ERROR_IO_PENDING, got %u \n " , err ) ;
file = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL ,
OPEN_EXISTING , FILE_FLAG_OVERLAPPED , 0 ) ;
ok ( file ! = INVALID_HANDLE_VALUE , " CreateFile failed with %u \n " , GetLastError ( ) ) ;
numbytes = 0xdeadbeef ;
ret = GetOverlappedResult ( pipe , & overlapped , & numbytes , TRUE ) ;
ok ( ret = = TRUE , " GetOverlappedResult failed \n " ) ;
ok ( numbytes = = 0 , " expected 0, got %u \n " , numbytes ) ;
ok ( overlapped . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %08lx \n " , overlapped . Internal ) ;
CloseHandle ( file ) ;
CloseHandle ( pipe ) ;
pipe = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED ,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
1 , 1024 , 1024 , NMPWAIT_WAIT_FOREVER , NULL ) ;
ok ( pipe ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed with %u \n " , GetLastError ( ) ) ;
file = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL ,
OPEN_EXISTING , FILE_FLAG_OVERLAPPED , 0 ) ;
ok ( file ! = INVALID_HANDLE_VALUE , " CreateFile failed with %u \n " , GetLastError ( ) ) ;
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = event ;
ret = ConnectNamedPipe ( pipe , & overlapped ) ;
err = GetLastError ( ) ;
ok ( ret = = FALSE , " ConnectNamedPipe succeeded \n " ) ;
ok ( err = = ERROR_PIPE_CONNECTED , " expected ERROR_PIPE_CONNECTED, got %u \n " , err ) ;
2016-04-07 10:02:42 +02:00
ok ( overlapped . Internal = = STATUS_PENDING , " expected STATUS_PENDING, got %08lx \n " , overlapped . Internal ) ;
2016-04-07 08:45:53 +02:00
CloseHandle ( file ) ;
CloseHandle ( pipe ) ;
CloseHandle ( event ) ;
}
2009-02-11 19:12:31 +01:00
static void test_NamedPipeHandleState ( void )
{
HANDLE server , client ;
BOOL ret ;
DWORD state , instances , maxCollectionCount , collectDataTimeout ;
char userName [ MAX_PATH ] ;
2013-10-21 10:02:23 +02:00
server = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
2009-02-11 19:12:31 +01:00
/* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " cf failed \n " ) ;
2013-10-21 10:02:23 +02:00
ret = GetNamedPipeHandleStateA ( server , NULL , NULL , NULL , NULL , NULL , 0 ) ;
2009-02-11 19:12:31 +01:00
ok ( ret , " GetNamedPipeHandleState failed: %d \n " , GetLastError ( ) ) ;
2013-10-21 10:02:23 +02:00
ret = GetNamedPipeHandleStateA ( server , & state , & instances , NULL , NULL , NULL ,
2009-02-11 19:12:31 +01:00
0 ) ;
ok ( ret , " GetNamedPipeHandleState failed: %d \n " , GetLastError ( ) ) ;
if ( ret )
{
ok ( state = = 0 , " unexpected state %08x \n " , state ) ;
ok ( instances = = 1 , " expected 1 instances, got %d \n " , instances ) ;
}
/* Some parameters have no meaning, and therefore can't be retrieved,
* on a local pipe .
*/
SetLastError ( 0xdeadbeef ) ;
2018-06-27 20:56:45 +02:00
ret = GetNamedPipeHandleStateA ( server , & state , & instances , & maxCollectionCount ,
& collectDataTimeout , userName , ARRAY_SIZE ( userName ) ) ;
2009-02-11 19:12:31 +01:00
todo_wine
ok ( ! ret & & GetLastError ( ) = = ERROR_INVALID_PARAMETER ,
" expected ERROR_INVALID_PARAMETER, got %d \n " , GetLastError ( ) ) ;
/* A byte-mode pipe server can't be changed to message mode. */
state = PIPE_READMODE_MESSAGE ;
SetLastError ( 0xdeadbeef ) ;
ret = SetNamedPipeHandleState ( server , & state , NULL , NULL ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_INVALID_PARAMETER ,
" expected ERROR_INVALID_PARAMETER, got %d \n " , GetLastError ( ) ) ;
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL ,
OPEN_EXISTING , 0 , NULL ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " cf failed \n " ) ;
state = PIPE_READMODE_BYTE ;
ret = SetNamedPipeHandleState ( client , & state , NULL , NULL ) ;
ok ( ret , " SetNamedPipeHandleState failed: %d \n " , GetLastError ( ) ) ;
/* A byte-mode pipe client can't be changed to message mode, either. */
state = PIPE_READMODE_MESSAGE ;
SetLastError ( 0xdeadbeef ) ;
ret = SetNamedPipeHandleState ( server , & state , NULL , NULL ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_INVALID_PARAMETER ,
" expected ERROR_INVALID_PARAMETER, got %d \n " , GetLastError ( ) ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
2013-10-21 10:02:23 +02:00
server = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
2009-02-11 19:12:31 +01:00
/* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " cf failed \n " ) ;
2013-10-21 10:02:23 +02:00
ret = GetNamedPipeHandleStateA ( server , NULL , NULL , NULL , NULL , NULL , 0 ) ;
2009-02-11 19:12:31 +01:00
ok ( ret , " GetNamedPipeHandleState failed: %d \n " , GetLastError ( ) ) ;
2013-10-21 10:02:23 +02:00
ret = GetNamedPipeHandleStateA ( server , & state , & instances , NULL , NULL , NULL ,
2009-02-11 19:12:31 +01:00
0 ) ;
ok ( ret , " GetNamedPipeHandleState failed: %d \n " , GetLastError ( ) ) ;
if ( ret )
{
ok ( state = = 0 , " unexpected state %08x \n " , state ) ;
ok ( instances = = 1 , " expected 1 instances, got %d \n " , instances ) ;
}
/* In contrast to byte-mode pipes, a message-mode pipe server can be
* changed to byte mode .
*/
state = PIPE_READMODE_BYTE ;
ret = SetNamedPipeHandleState ( server , & state , NULL , NULL ) ;
ok ( ret , " SetNamedPipeHandleState failed: %d \n " , GetLastError ( ) ) ;
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL ,
OPEN_EXISTING , 0 , NULL ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " cf failed \n " ) ;
state = PIPE_READMODE_MESSAGE ;
ret = SetNamedPipeHandleState ( client , & state , NULL , NULL ) ;
ok ( ret , " SetNamedPipeHandleState failed: %d \n " , GetLastError ( ) ) ;
/* A message-mode pipe client can also be changed to byte mode.
*/
state = PIPE_READMODE_BYTE ;
ret = SetNamedPipeHandleState ( client , & state , NULL , NULL ) ;
ok ( ret , " SetNamedPipeHandleState failed: %d \n " , GetLastError ( ) ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
}
2016-10-05 21:27:06 +02:00
static void test_GetNamedPipeInfo ( void )
{
HANDLE server ;
server = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
/* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
test_pipe_info ( server , PIPE_SERVER_END | PIPE_TYPE_BYTE , 1024 , 1024 , 1 ) ;
CloseHandle ( server ) ;
server = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX ,
/* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT ,
/* nMaxInstances */ 3 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
test_pipe_info ( server , PIPE_SERVER_END | PIPE_TYPE_MESSAGE , 1024 , 1024 , 3 ) ;
CloseHandle ( server ) ;
server = CreateNamedPipeA ( PIPENAME , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX ,
/* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 0 ,
/* nInBufSize */ 0 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
test_pipe_info ( server , PIPE_SERVER_END | PIPE_TYPE_MESSAGE , 0 , 0 , 1 ) ;
CloseHandle ( server ) ;
server = CreateNamedPipeA ( PIPENAME , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX ,
/* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 0xf000 ,
/* nInBufSize */ 0xf000 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
test_pipe_info ( server , PIPE_SERVER_END | PIPE_TYPE_MESSAGE , 0xf000 , 0xf000 , 1 ) ;
CloseHandle ( server ) ;
}
2012-06-14 21:35:27 +02:00
static void test_readfileex_pending ( void )
{
HANDLE server , client , event ;
BOOL ret ;
DWORD err , wait , num_bytes ;
OVERLAPPED overlapped ;
char read_buf [ 1024 ] ;
char write_buf [ 1024 ] ;
2012-06-20 20:10:12 +02:00
const char test_string [ ] = " test " ;
2012-06-14 21:35:27 +02:00
int i ;
2013-10-21 10:02:23 +02:00
server = CreateNamedPipeA ( PIPENAME , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX ,
2012-06-14 21:35:27 +02:00
/* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT ,
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 1024 ,
/* nInBufSize */ 1024 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " cf failed \n " ) ;
event = CreateEventA ( NULL , TRUE , FALSE , NULL ) ;
ok ( event ! = NULL , " CreateEventA failed \n " ) ;
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = event ;
ret = ConnectNamedPipe ( server , & overlapped ) ;
err = GetLastError ( ) ;
ok ( ret = = FALSE , " ConnectNamedPipe succeeded \n " ) ;
ok ( err = = ERROR_IO_PENDING , " ConnectNamedPipe set error %i \n " , err ) ;
wait = WaitForSingleObject ( event , 0 ) ;
ok ( wait = = WAIT_TIMEOUT , " WaitForSingleObject returned %x \n " , wait ) ;
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL ,
OPEN_EXISTING , 0 , NULL ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " cf failed \n " ) ;
wait = WaitForSingleObject ( event , 0 ) ;
ok ( wait = = WAIT_OBJECT_0 , " WaitForSingleObject returned %x \n " , wait ) ;
/* Start a read that can't complete immediately. */
completion_called = 0 ;
ResetEvent ( event ) ;
ret = ReadFileEx ( server , read_buf , sizeof ( read_buf ) , & overlapped , completion_routine ) ;
2012-06-14 21:42:47 +02:00
ok ( ret = = TRUE , " ReadFileEx failed, err=%i \n " , GetLastError ( ) ) ;
2012-06-14 21:35:27 +02:00
ok ( completion_called = = 0 , " completion routine called before ReadFileEx returned \n " ) ;
2012-06-20 20:10:12 +02:00
ret = WriteFile ( client , test_string , strlen ( test_string ) , & num_bytes , NULL ) ;
2012-06-14 21:35:27 +02:00
ok ( ret = = TRUE , " WriteFile failed \n " ) ;
2012-06-20 20:10:12 +02:00
ok ( num_bytes = = strlen ( test_string ) , " only %i bytes written \n " , num_bytes ) ;
2012-06-14 21:35:27 +02:00
ok ( completion_called = = 0 , " completion routine called during WriteFile \n " ) ;
wait = WaitForSingleObjectEx ( event , 0 , TRUE ) ;
ok ( wait = = WAIT_IO_COMPLETION | | wait = = WAIT_OBJECT_0 , " WaitForSingleObjectEx returned %x \n " , wait ) ;
ok ( completion_called = = 1 , " completion not called after writing pipe \n " ) ;
ok ( completion_errorcode = = 0 , " completion called with error %x \n " , completion_errorcode ) ;
2012-06-20 20:10:12 +02:00
ok ( completion_num_bytes = = strlen ( test_string ) , " ReadFileEx returned only %d bytes \n " , completion_num_bytes ) ;
2012-06-14 21:35:27 +02:00
ok ( completion_lpoverlapped = = & overlapped , " completion called with wrong overlapped pointer \n " ) ;
2012-06-20 20:10:12 +02:00
ok ( ! memcmp ( test_string , read_buf , strlen ( test_string ) ) , " ReadFileEx read wrong bytes \n " ) ;
2012-06-14 21:35:27 +02:00
/* Make writes until the pipe is full and the write fails */
memset ( write_buf , 0xaa , sizeof ( write_buf ) ) ;
for ( i = 0 ; i < 256 ; i + + )
{
completion_called = 0 ;
ResetEvent ( event ) ;
ret = WriteFileEx ( server , write_buf , sizeof ( write_buf ) , & overlapped , completion_routine ) ;
err = GetLastError ( ) ;
ok ( completion_called = = 0 , " completion routine called during WriteFileEx \n " ) ;
wait = WaitForSingleObjectEx ( event , 0 , TRUE ) ;
if ( wait = = WAIT_TIMEOUT )
/* write couldn't complete immediately, presumably the pipe is full */
break ;
ok ( wait = = WAIT_IO_COMPLETION | | wait = = WAIT_OBJECT_0 , " WaitForSingleObject returned %x \n " , wait ) ;
ok ( ret = = TRUE , " WriteFileEx failed, err=%i \n " , err ) ;
ok ( completion_errorcode = = 0 , " completion called with error %x \n " , completion_errorcode ) ;
ok ( completion_lpoverlapped = = & overlapped , " completion called with wrong overlapped pointer \n " ) ;
}
2012-06-14 21:42:47 +02:00
ok ( ret = = TRUE , " WriteFileEx failed, err=%i \n " , err ) ;
2012-06-14 21:35:27 +02:00
ok ( completion_called = = 0 , " completion routine called but wait timed out \n " ) ;
ok ( completion_errorcode = = 0 , " completion called with error %x \n " , completion_errorcode ) ;
ok ( completion_lpoverlapped = = & overlapped , " completion called with wrong overlapped pointer \n " ) ;
/* free up some space in the pipe */
2015-02-24 13:55:09 +01:00
for ( i = 0 ; i < 256 ; i + + )
2014-07-30 18:00:19 +02:00
{
ret = ReadFile ( client , read_buf , sizeof ( read_buf ) , & num_bytes , NULL ) ;
ok ( ret = = TRUE , " ReadFile failed \n " ) ;
2015-02-24 13:55:09 +01:00
2014-07-30 18:00:19 +02:00
ok ( completion_called = = 0 , " completion routine called during ReadFile \n " ) ;
2015-02-24 13:55:09 +01:00
2014-07-30 18:00:19 +02:00
wait = WaitForSingleObjectEx ( event , 0 , TRUE ) ;
2015-02-24 13:55:09 +01:00
ok ( wait = = WAIT_IO_COMPLETION | | wait = = WAIT_OBJECT_0 | | wait = = WAIT_TIMEOUT ,
" WaitForSingleObject returned %x \n " , wait ) ;
if ( wait ! = WAIT_TIMEOUT ) break ;
2014-07-30 18:00:19 +02:00
}
2012-06-14 21:35:27 +02:00
ok ( completion_called = = 1 , " completion routine not called \n " ) ;
ok ( completion_errorcode = = 0 , " completion called with error %x \n " , completion_errorcode ) ;
ok ( completion_lpoverlapped = = & overlapped , " completion called with wrong overlapped pointer \n " ) ;
2013-09-18 08:54:32 +02:00
num_bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( INVALID_HANDLE_VALUE , read_buf , 0 , & num_bytes , NULL ) ;
ok ( ! ret , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_HANDLE , " wrong error %u \n " , GetLastError ( ) ) ;
ok ( num_bytes = = 0 , " expected 0, got %u \n " , num_bytes ) ;
S ( U ( overlapped ) ) . Offset = 0 ;
S ( U ( overlapped ) ) . OffsetHigh = 0 ;
overlapped . Internal = - 1 ;
overlapped . InternalHigh = - 1 ;
overlapped . hEvent = event ;
num_bytes = 0xdeadbeef ;
SetLastError ( 0xdeadbeef ) ;
ret = ReadFile ( server , read_buf , 0 , & num_bytes , & overlapped ) ;
2015-03-04 09:39:10 +01:00
ok ( ! ret , " ReadFile should fail \n " ) ;
2013-09-18 08:54:32 +02:00
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " expected ERROR_IO_PENDING, got %d \n " , GetLastError ( ) ) ;
ok ( num_bytes = = 0 , " bytes %u \n " , num_bytes ) ;
ok ( ( NTSTATUS ) overlapped . Internal = = STATUS_PENDING , " expected STATUS_PENDING, got %#lx \n " , overlapped . Internal ) ;
ok ( overlapped . InternalHigh = = - 1 , " expected -1, got %lu \n " , overlapped . InternalHigh ) ;
wait = WaitForSingleObject ( event , 100 ) ;
ok ( wait = = WAIT_TIMEOUT , " WaitForSingleObject returned %x \n " , wait ) ;
num_bytes = 0xdeadbeef ;
ret = WriteFile ( client , test_string , 1 , & num_bytes , NULL ) ;
ok ( ret , " WriteFile failed \n " ) ;
ok ( num_bytes = = 1 , " bytes %u \n " , num_bytes ) ;
2013-09-18 08:55:20 +02:00
wait = WaitForSingleObject ( event , 100 ) ;
2013-09-18 08:54:32 +02:00
ok ( wait = = WAIT_OBJECT_0 , " WaitForSingleObject returned %x \n " , wait ) ;
ok ( num_bytes = = 1 , " bytes %u \n " , num_bytes ) ;
ok ( ( NTSTATUS ) overlapped . Internal = = STATUS_SUCCESS , " expected STATUS_SUCCESS, got %#lx \n " , overlapped . Internal ) ;
ok ( overlapped . InternalHigh = = 0 , " expected 0, got %lu \n " , overlapped . InternalHigh ) ;
/* read the pending byte and clear the pipe */
num_bytes = 0xdeadbeef ;
ret = ReadFile ( server , read_buf , 1 , & num_bytes , & overlapped ) ;
ok ( ret , " ReadFile failed \n " ) ;
ok ( num_bytes = = 1 , " bytes %u \n " , num_bytes ) ;
2012-06-14 21:35:27 +02:00
CloseHandle ( client ) ;
CloseHandle ( server ) ;
CloseHandle ( event ) ;
}
2017-05-22 13:40:58 +02:00
# define test_peek_pipe(a,b,c,d) _test_peek_pipe(__LINE__,a,b,c,d)
static void _test_peek_pipe ( unsigned line , HANDLE pipe , DWORD expected_read , DWORD expected_avail , DWORD expected_message_length )
2017-03-23 15:42:47 +01:00
{
2017-05-22 13:40:58 +02:00
DWORD bytes_read = 0xdeadbeed , avail = 0xdeadbeef , left = 0xdeadbeed ;
2018-10-20 19:18:12 +02:00
char buf [ 12000 ] ;
2017-05-22 13:40:58 +02:00
FILE_PIPE_PEEK_BUFFER * peek_buf = ( void * ) buf ;
IO_STATUS_BLOCK io ;
NTSTATUS status ;
2017-03-23 15:42:47 +01:00
BOOL r ;
2017-05-22 13:40:58 +02:00
r = PeekNamedPipe ( pipe , buf , sizeof ( buf ) , & bytes_read , & avail , & left ) ;
2017-03-23 15:42:47 +01:00
ok_ ( __FILE__ , line ) ( r , " PeekNamedPipe failed: %u \n " , GetLastError ( ) ) ;
ok_ ( __FILE__ , line ) ( bytes_read = = expected_read , " bytes_read = %u, expected %u \n " , bytes_read , expected_read ) ;
ok_ ( __FILE__ , line ) ( avail = = expected_avail , " avail = %u, expected %u \n " , avail , expected_avail ) ;
2017-05-22 13:40:58 +02:00
ok_ ( __FILE__ , line ) ( left = = expected_message_length - expected_read , " left = %d, expected %d \n " ,
left , expected_message_length - expected_read ) ;
status = NtFsControlFile ( pipe , 0 , NULL , NULL , & io , FSCTL_PIPE_PEEK , NULL , 0 , buf , sizeof ( buf ) ) ;
ok_ ( __FILE__ , line ) ( ! status | | status = = STATUS_PENDING , " NtFsControlFile(FSCTL_PIPE_PEEK) failed: %x \n " , status ) ;
ok_ ( __FILE__ , line ) ( io . Information = = FIELD_OFFSET ( FILE_PIPE_PEEK_BUFFER , Data [ expected_read ] ) ,
" io.Information = %lu \n " , io . Information ) ;
ok_ ( __FILE__ , line ) ( peek_buf - > ReadDataAvailable = = expected_avail , " ReadDataAvailable = %u, expected %u \n " ,
peek_buf - > ReadDataAvailable , expected_avail ) ;
ok_ ( __FILE__ , line ) ( peek_buf - > MessageLength = = expected_message_length , " MessageLength = %u, expected %u \n " ,
peek_buf - > MessageLength , expected_message_length ) ;
if ( expected_read )
{
r = PeekNamedPipe ( pipe , buf , 1 , & bytes_read , & avail , & left ) ;
ok_ ( __FILE__ , line ) ( r , " PeekNamedPipe failed: %u \n " , GetLastError ( ) ) ;
ok_ ( __FILE__ , line ) ( bytes_read = = 1 , " bytes_read = %u, expected %u \n " , bytes_read , expected_read ) ;
ok_ ( __FILE__ , line ) ( avail = = expected_avail , " avail = %u, expected %u \n " , avail , expected_avail ) ;
ok_ ( __FILE__ , line ) ( left = = expected_message_length - 1 , " left = %d, expected %d \n " , left , expected_message_length - 1 ) ;
}
2017-03-23 15:42:47 +01:00
}
# define overlapped_read_sync(a,b,c,d,e) _overlapped_read_sync(__LINE__,a,b,c,d,e)
static void _overlapped_read_sync ( unsigned line , HANDLE reader , void * buf , DWORD buf_size , DWORD expected_result , BOOL partial_read )
{
DWORD read_bytes = 0xdeadbeef ;
OVERLAPPED overlapped ;
BOOL res ;
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
res = ReadFile ( reader , buf , buf_size , & read_bytes , & overlapped ) ;
if ( partial_read )
ok_ ( __FILE__ , line ) ( ! res & & GetLastError ( ) = = ERROR_MORE_DATA , " ReadFile returned: %x (%u) \n " , res , GetLastError ( ) ) ;
else
ok_ ( __FILE__ , line ) ( res , " ReadFile failed: %u \n " , GetLastError ( ) ) ;
if ( partial_read )
2018-01-23 15:51:31 +01:00
ok_ ( __FILE__ , line ) ( ! read_bytes , " read_bytes %u expected 0 \n " , read_bytes ) ;
2017-03-23 15:42:47 +01:00
else
ok_ ( __FILE__ , line ) ( read_bytes = = expected_result , " read_bytes %u expected %u \n " , read_bytes , expected_result ) ;
read_bytes = 0xdeadbeef ;
res = GetOverlappedResult ( reader , & overlapped , & read_bytes , FALSE ) ;
if ( partial_read )
ok_ ( __FILE__ , line ) ( ! res & & GetLastError ( ) = = ERROR_MORE_DATA ,
" GetOverlappedResult returned: %x (%u) \n " , res , GetLastError ( ) ) ;
else
ok_ ( __FILE__ , line ) ( res , " GetOverlappedResult failed: %u \n " , GetLastError ( ) ) ;
ok_ ( __FILE__ , line ) ( read_bytes = = expected_result , " read_bytes %u expected %u \n " , read_bytes , expected_result ) ;
CloseHandle ( overlapped . hEvent ) ;
}
# define overlapped_read_async(a,b,c,d) _overlapped_read_async(__LINE__,a,b,c,d)
static void _overlapped_read_async ( unsigned line , HANDLE reader , void * buf , DWORD buf_size , OVERLAPPED * overlapped )
{
DWORD read_bytes = 0xdeadbeef ;
BOOL res ;
memset ( overlapped , 0 , sizeof ( * overlapped ) ) ;
overlapped - > hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
res = ReadFile ( reader , buf , buf_size , & read_bytes , overlapped ) ;
ok_ ( __FILE__ , line ) ( ! res & & GetLastError ( ) = = ERROR_IO_PENDING , " ReadFile returned %x(%u) \n " , res , GetLastError ( ) ) ;
ok_ ( __FILE__ , line ) ( ! read_bytes , " read_bytes %u expected 0 \n " , read_bytes ) ;
_test_not_signaled ( line , overlapped - > hEvent ) ;
}
# define overlapped_write_sync(a,b,c) _overlapped_write_sync(__LINE__,a,b,c)
static void _overlapped_write_sync ( unsigned line , HANDLE writer , void * buf , DWORD size )
{
DWORD written_bytes = 0xdeadbeef ;
OVERLAPPED overlapped ;
BOOL res ;
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
res = WriteFile ( writer , buf , size , & written_bytes , & overlapped ) ;
ok_ ( __FILE__ , line ) ( res , " WriteFile returned %x(%u) \n " , res , GetLastError ( ) ) ;
ok_ ( __FILE__ , line ) ( written_bytes = = size , " WriteFile returned written_bytes = %u \n " , written_bytes ) ;
written_bytes = 0xdeadbeef ;
res = GetOverlappedResult ( writer , & overlapped , & written_bytes , FALSE ) ;
ok_ ( __FILE__ , line ) ( res , " GetOverlappedResult failed: %u \n " , GetLastError ( ) ) ;
ok_ ( __FILE__ , line ) ( written_bytes = = size , " GetOverlappedResult returned written_bytes %u expected %u \n " , written_bytes , size ) ;
CloseHandle ( overlapped . hEvent ) ;
}
# define overlapped_write_async(a,b,c,d) _overlapped_write_async(__LINE__,a,b,c,d)
static void _overlapped_write_async ( unsigned line , HANDLE writer , void * buf , DWORD size , OVERLAPPED * overlapped )
{
DWORD written_bytes = 0xdeadbeef ;
BOOL res ;
memset ( overlapped , 0 , sizeof ( * overlapped ) ) ;
overlapped - > hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
res = WriteFile ( writer , buf , size , & written_bytes , overlapped ) ;
ok_ ( __FILE__ , line ) ( ! res & & GetLastError ( ) = = ERROR_IO_PENDING , " WriteFile returned %x(%u) \n " , res , GetLastError ( ) ) ;
2018-01-23 15:51:58 +01:00
ok_ ( __FILE__ , line ) ( ! written_bytes , " written_bytes = %u \n " , written_bytes ) ;
2017-03-23 15:42:47 +01:00
_test_not_signaled ( line , overlapped - > hEvent ) ;
}
# define test_flush_sync(a) _test_flush_sync(__LINE__,a)
static void _test_flush_sync ( unsigned line , HANDLE pipe )
{
BOOL res ;
res = FlushFileBuffers ( pipe ) ;
ok_ ( __FILE__ , line ) ( res , " FlushFileBuffers failed: %u \n " , GetLastError ( ) ) ;
}
static DWORD expected_flush_error ;
static DWORD CALLBACK flush_proc ( HANDLE pipe )
{
BOOL res ;
res = FlushFileBuffers ( pipe ) ;
if ( expected_flush_error = = ERROR_SUCCESS )
ok ( res , " FlushFileBuffers failed: %u \n " , GetLastError ( ) ) ;
else
2018-10-30 16:08:48 +01:00
ok ( ! res & & GetLastError ( ) = = expected_flush_error , " FlushFileBuffers failed: %u \n " , GetLastError ( ) ) ;
2017-03-23 15:42:47 +01:00
return 0 ;
}
# define test_flush_async(a,b) _test_flush_async(__LINE__,a,b)
static HANDLE _test_flush_async ( unsigned line , HANDLE pipe , DWORD error )
{
HANDLE thread ;
DWORD tid ;
expected_flush_error = error ;
thread = CreateThread ( NULL , 0 , flush_proc , pipe , 0 , & tid ) ;
ok_ ( __FILE__ , line ) ( thread ! = NULL , " CreateThread failed: %u \n " , GetLastError ( ) ) ;
Sleep ( 50 ) ;
_test_not_signaled ( line , thread ) ;
return thread ;
}
# define test_flush_done(a) _test_flush_done(__LINE__,a)
static void _test_flush_done ( unsigned line , HANDLE thread )
{
DWORD res = WaitForSingleObject ( thread , 1000 ) ;
ok_ ( __FILE__ , line ) ( res = = WAIT_OBJECT_0 , " WaitForSingleObject returned %u (%u) \n " , res , GetLastError ( ) ) ;
CloseHandle ( thread ) ;
}
# define test_overlapped_result(a,b,c,d) _test_overlapped_result(__LINE__,a,b,c,d)
static void _test_overlapped_result ( unsigned line , HANDLE handle , OVERLAPPED * overlapped , DWORD expected_result , BOOL partial_read )
{
DWORD result = 0xdeadbeef ;
BOOL res ;
_test_signaled ( line , overlapped - > hEvent ) ;
res = GetOverlappedResult ( handle , overlapped , & result , FALSE ) ;
if ( partial_read )
ok_ ( __FILE__ , line ) ( ! res & & GetLastError ( ) = = ERROR_MORE_DATA , " GetOverlappedResult returned: %x (%u) \n " , res , GetLastError ( ) ) ;
else
ok_ ( __FILE__ , line ) ( res , " GetOverlappedResult failed: %u \n " , GetLastError ( ) ) ;
ok_ ( __FILE__ , line ) ( result = = expected_result , " read_bytes = %u, expected %u \n " , result , expected_result ) ;
CloseHandle ( overlapped - > hEvent ) ;
}
# define test_overlapped_failure(a,b,c) _test_overlapped_failure(__LINE__,a,b,c)
static void _test_overlapped_failure ( unsigned line , HANDLE handle , OVERLAPPED * overlapped , DWORD error )
{
DWORD result ;
BOOL res ;
_test_signaled ( line , overlapped - > hEvent ) ;
res = GetOverlappedResult ( handle , overlapped , & result , FALSE ) ;
ok_ ( __FILE__ , line ) ( ! res & & GetLastError ( ) = = error , " GetOverlappedResult returned: %x (%u), expected error %u \n " ,
res , GetLastError ( ) , error ) ;
ok_ ( __FILE__ , line ) ( ! result , " result = %u \n " , result ) ;
CloseHandle ( overlapped - > hEvent ) ;
}
# define cancel_overlapped(a,b) _cancel_overlapped(__LINE__,a,b)
static void _cancel_overlapped ( unsigned line , HANDLE handle , OVERLAPPED * overlapped )
{
BOOL res ;
res = pCancelIoEx ( handle , overlapped ) ;
ok_ ( __FILE__ , line ) ( res , " CancelIoEx failed: %u \n " , GetLastError ( ) ) ;
_test_overlapped_failure ( line , handle , overlapped , ERROR_OPERATION_ABORTED ) ;
}
static void test_blocking_rw ( HANDLE writer , HANDLE reader , DWORD buf_size , BOOL msg_mode , BOOL msg_read )
{
OVERLAPPED read_overlapped , read_overlapped2 , write_overlapped , write_overlapped2 ;
char buf [ 10000 ] , read_buf [ 10000 ] ;
HANDLE flush_thread ;
memset ( buf , 0xaa , sizeof ( buf ) ) ;
/* test pending read with overlapped event */
overlapped_read_async ( reader , read_buf , 1000 , & read_overlapped ) ;
test_flush_sync ( writer ) ;
2017-05-22 13:40:58 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
2017-03-23 15:42:47 +01:00
/* write more data than needed for read */
overlapped_write_sync ( writer , buf , 4000 ) ;
test_overlapped_result ( reader , & read_overlapped , 1000 , msg_read ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 3000 , 3000 , msg_mode ? 3000 : 0 ) ;
2017-03-23 15:42:47 +01:00
/* test pending write with overlapped event */
overlapped_write_async ( writer , buf , buf_size , & write_overlapped ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 3000 + ( msg_mode ? 0 : buf_size ) , 3000 + buf_size , msg_mode ? 3000 : 0 ) ;
2017-03-23 15:42:47 +01:00
/* write one more byte */
overlapped_write_async ( writer , buf , 1 , & write_overlapped2 ) ;
flush_thread = test_flush_async ( writer , ERROR_SUCCESS ) ;
test_not_signaled ( write_overlapped . hEvent ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 3000 + ( msg_mode ? 0 : buf_size + 1 ) , 3000 + buf_size + 1 ,
msg_mode ? 3000 : 0 ) ;
2017-03-23 15:42:47 +01:00
/* empty write will not block */
overlapped_write_sync ( writer , buf , 0 ) ;
test_not_signaled ( write_overlapped . hEvent ) ;
test_not_signaled ( write_overlapped2 . hEvent ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 3000 + ( msg_mode ? 0 : buf_size + 1 ) , 3000 + buf_size + 1 ,
msg_mode ? 3000 : 0 ) ;
2017-03-23 15:42:47 +01:00
/* read remaining data from the first write */
overlapped_read_sync ( reader , read_buf , 3000 , 3000 , FALSE ) ;
test_overlapped_result ( writer , & write_overlapped , buf_size , FALSE ) ;
test_not_signaled ( write_overlapped2 . hEvent ) ;
test_not_signaled ( flush_thread ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , buf_size + ( msg_mode ? 0 : 1 ) , buf_size + 1 , msg_mode ? buf_size : 0 ) ;
2017-03-23 15:42:47 +01:00
/* read one byte so that the next write fits the buffer */
overlapped_read_sync ( reader , read_buf , 1 , 1 , msg_read ) ;
test_overlapped_result ( writer , & write_overlapped2 , 1 , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , buf_size + ( msg_mode ? - 1 : 0 ) , buf_size , msg_mode ? buf_size - 1 : 0 ) ;
2017-03-23 15:42:47 +01:00
/* read the whole buffer */
overlapped_read_sync ( reader , read_buf , buf_size , buf_size - msg_read , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , msg_read ? 1 : 0 , msg_read ? 1 : 0 , msg_read ? 1 : 0 ) ;
2017-03-23 15:42:47 +01:00
if ( msg_read )
2018-10-20 19:18:12 +02:00
{
2017-03-23 15:42:47 +01:00
overlapped_read_sync ( reader , read_buf , 1000 , 1 , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
}
2017-03-23 15:42:47 +01:00
2018-10-20 19:18:12 +02:00
if ( msg_mode )
{
2017-03-23 15:42:47 +01:00
/* we still have an empty message in queue */
overlapped_read_sync ( reader , read_buf , 1000 , 0 , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
2017-03-23 15:42:47 +01:00
}
test_flush_done ( flush_thread ) ;
/* pipe is empty, the next read will block */
overlapped_read_async ( reader , read_buf , 0 , & read_overlapped ) ;
overlapped_read_async ( reader , read_buf , 1000 , & read_overlapped2 ) ;
/* write one byte */
overlapped_write_sync ( writer , buf , 1 ) ;
test_overlapped_result ( reader , & read_overlapped , 0 , msg_read ) ;
test_overlapped_result ( reader , & read_overlapped2 , 1 , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
2017-03-23 15:42:47 +01:00
/* write a message larger than buffer */
overlapped_write_async ( writer , buf , buf_size + 2000 , & write_overlapped ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , buf_size + 2000 , buf_size + 2000 , msg_mode ? buf_size + 2000 : 0 ) ;
2017-03-23 15:42:47 +01:00
/* read so that pending write is still larger than the buffer */
overlapped_read_sync ( reader , read_buf , 1999 , 1999 , msg_read ) ;
test_not_signaled ( write_overlapped . hEvent ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , buf_size + 1 , buf_size + 1 , msg_mode ? buf_size + 1 : 0 ) ;
2017-03-23 15:42:47 +01:00
/* read one more byte */
overlapped_read_sync ( reader , read_buf , 1 , 1 , msg_read ) ;
test_overlapped_result ( writer , & write_overlapped , buf_size + 2000 , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , buf_size , buf_size , msg_mode ? buf_size : 0 ) ;
2017-03-23 15:42:47 +01:00
/* read remaining data */
overlapped_read_sync ( reader , read_buf , buf_size + 1 , buf_size , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
2017-03-23 15:42:47 +01:00
/* simple pass of empty message */
overlapped_write_sync ( writer , buf , 0 ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
2017-03-23 15:42:47 +01:00
if ( msg_mode )
overlapped_read_sync ( reader , read_buf , 1 , 0 , FALSE ) ;
/* pipe is empty, the next read will block */
test_flush_sync ( writer ) ;
overlapped_read_async ( reader , read_buf , 0 , & read_overlapped ) ;
overlapped_read_async ( reader , read_buf , 1 , & read_overlapped2 ) ;
/* 0 length write wakes one read in msg mode */
overlapped_write_sync ( writer , buf , 0 ) ;
if ( msg_mode )
test_overlapped_result ( reader , & read_overlapped , 0 , FALSE ) ;
else
test_not_signaled ( read_overlapped . hEvent ) ;
test_not_signaled ( read_overlapped2 . hEvent ) ;
overlapped_write_sync ( writer , buf , 1 ) ;
test_overlapped_result ( reader , & read_overlapped2 , 1 , FALSE ) ;
overlapped_write_sync ( writer , buf , 20 ) ;
2017-05-22 13:40:58 +02:00
test_peek_pipe ( reader , 20 , 20 , msg_mode ? 20 : 0 ) ;
2017-03-23 15:42:47 +01:00
overlapped_write_sync ( writer , buf , 15 ) ;
2017-05-22 13:40:58 +02:00
test_peek_pipe ( reader , msg_mode ? 20 : 35 , 35 , msg_mode ? 20 : 0 ) ;
2017-03-23 15:42:47 +01:00
overlapped_read_sync ( reader , read_buf , 10 , 10 , msg_read ) ;
2017-05-22 13:40:58 +02:00
test_peek_pipe ( reader , msg_mode ? 10 : 25 , 25 , msg_mode ? 10 : 0 ) ;
2017-03-23 15:42:47 +01:00
overlapped_read_sync ( reader , read_buf , 10 , 10 , FALSE ) ;
2017-05-22 13:40:58 +02:00
test_peek_pipe ( reader , 15 , 15 , msg_mode ? 15 : 0 ) ;
2017-03-23 15:42:47 +01:00
overlapped_read_sync ( reader , read_buf , 15 , 15 , FALSE ) ;
if ( ! pCancelIoEx ) {
win_skip ( " CancelIoEx not available \n " ) ;
return ;
}
/* add one more pending read, then cancel the first one */
overlapped_read_async ( reader , read_buf , 1 , & read_overlapped ) ;
overlapped_read_async ( reader , read_buf , 1 , & read_overlapped2 ) ;
cancel_overlapped ( reader , & read_overlapped2 ) ;
test_not_signaled ( read_overlapped . hEvent ) ;
overlapped_write_sync ( writer , buf , 1 ) ;
test_overlapped_result ( reader , & read_overlapped , 1 , FALSE ) ;
/* make two async writes, cancel the first one and make sure that we read from the second one */
overlapped_write_async ( writer , buf , buf_size + 2000 , & write_overlapped ) ;
overlapped_write_async ( writer , buf , 1 , & write_overlapped2 ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , buf_size + 2000 + ( msg_mode ? 0 : 1 ) ,
buf_size + 2001 , msg_mode ? buf_size + 2000 : 0 ) ;
2017-03-23 15:42:47 +01:00
cancel_overlapped ( writer , & write_overlapped ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 1 , 1 , msg_mode ? 1 : 0 ) ;
2017-03-23 15:42:47 +01:00
overlapped_read_sync ( reader , read_buf , 1000 , 1 , FALSE ) ;
test_overlapped_result ( writer , & write_overlapped2 , 1 , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
2017-03-23 15:42:47 +01:00
2019-09-22 23:22:25 +02:00
/* same as above, but partially read written data before canceling */
2017-03-23 15:42:47 +01:00
overlapped_write_async ( writer , buf , buf_size + 2000 , & write_overlapped ) ;
overlapped_write_async ( writer , buf , 1 , & write_overlapped2 ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , buf_size + 2000 + ( msg_mode ? 0 : 1 ) ,
buf_size + 2001 , msg_mode ? buf_size + 2000 : 0 ) ;
2017-03-23 15:42:47 +01:00
overlapped_read_sync ( reader , read_buf , 10 , 10 , msg_read ) ;
test_not_signaled ( write_overlapped . hEvent ) ;
cancel_overlapped ( writer , & write_overlapped ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 1 , 1 , msg_mode ? 1 : 0 ) ;
2017-03-23 15:42:47 +01:00
overlapped_read_sync ( reader , read_buf , 1000 , 1 , FALSE ) ;
test_overlapped_result ( writer , & write_overlapped2 , 1 , FALSE ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
2017-03-23 15:42:47 +01:00
/* empty queue by canceling write and make sure that flush is signaled */
overlapped_write_async ( writer , buf , buf_size + 2000 , & write_overlapped ) ;
flush_thread = test_flush_async ( writer , ERROR_SUCCESS ) ;
test_not_signaled ( flush_thread ) ;
cancel_overlapped ( writer , & write_overlapped ) ;
2018-10-20 19:18:12 +02:00
test_peek_pipe ( reader , 0 , 0 , 0 ) ;
2017-03-23 15:42:47 +01:00
test_flush_done ( flush_thread ) ;
}
2018-03-28 22:46:51 +02:00
# define overlapped_transact(a,b,c,d,e,f) _overlapped_transact(__LINE__,a,b,c,d,e,f)
static void _overlapped_transact ( unsigned line , HANDLE caller , void * write_buf , DWORD write_size ,
void * read_buf , DWORD read_size , OVERLAPPED * overlapped )
{
BOOL res ;
memset ( overlapped , 0 , sizeof ( * overlapped ) ) ;
overlapped - > hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
res = TransactNamedPipe ( caller , write_buf , write_size , read_buf , read_size , NULL , overlapped ) ;
ok_ ( __FILE__ , line ) ( ! res & & GetLastError ( ) = = ERROR_IO_PENDING ,
" TransactNamedPipe returned: %x(%u) \n " , res , GetLastError ( ) ) ;
}
# define overlapped_transact_failure(a,b,c,d,e,f) _overlapped_transact_failure(__LINE__,a,b,c,d,e,f)
static void _overlapped_transact_failure ( unsigned line , HANDLE caller , void * write_buf , DWORD write_size ,
void * read_buf , DWORD read_size , DWORD expected_error )
{
OVERLAPPED overlapped ;
BOOL res ;
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
res = TransactNamedPipe ( caller , write_buf , write_size , read_buf , read_size , NULL , & overlapped ) ;
ok_ ( __FILE__ , line ) ( ! res , " TransactNamedPipe succeeded \n " ) ;
if ( GetLastError ( ) = = ERROR_IO_PENDING ) /* win8+ */
{
_test_overlapped_failure ( line , caller , & overlapped , expected_error ) ;
}
else
{
ok_ ( __FILE__ , line ) ( GetLastError ( ) = = expected_error ,
" TransactNamedPipe returned error %u, expected %u \n " ,
GetLastError ( ) , expected_error ) ;
CloseHandle ( overlapped . hEvent ) ;
}
}
2017-03-28 12:29:44 +02:00
static void child_process_write_pipe ( HANDLE pipe )
{
OVERLAPPED overlapped ;
char buf [ 10000 ] ;
memset ( buf , ' x ' , sizeof ( buf ) ) ;
overlapped_write_async ( pipe , buf , sizeof ( buf ) , & overlapped ) ;
/* sleep until parent process terminates this process */
Sleep ( INFINITE ) ;
}
static HANDLE create_writepipe_process ( HANDLE pipe )
{
STARTUPINFOA si = { sizeof ( si ) } ;
PROCESS_INFORMATION info ;
char * * argv , buf [ MAX_PATH ] ;
BOOL res ;
winetest_get_mainargs ( & argv ) ;
sprintf ( buf , " \" %s \" pipe writepipe %lx " , argv [ 0 ] , ( UINT_PTR ) pipe ) ;
res = CreateProcessA ( NULL , buf , NULL , NULL , TRUE , 0L , NULL , NULL , & si , & info ) ;
ok ( res , " CreateProcess failed: %u \n " , GetLastError ( ) ) ;
CloseHandle ( info . hThread ) ;
return info . hProcess ;
}
2017-03-23 15:42:47 +01:00
static void create_overlapped_pipe ( DWORD mode , HANDLE * client , HANDLE * server )
{
SECURITY_ATTRIBUTES sec_attr = { sizeof ( sec_attr ) , NULL , TRUE } ;
DWORD read_mode = mode & ( PIPE_READMODE_BYTE | PIPE_READMODE_MESSAGE ) ;
OVERLAPPED overlapped ;
BOOL res ;
* server = CreateNamedPipeA ( PIPENAME , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX ,
PIPE_WAIT | mode , 1 , 5000 , 6000 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
2018-04-11 12:08:08 +02:00
ok ( * server ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed: %u \n " , GetLastError ( ) ) ;
2017-03-23 15:42:47 +01:00
test_signaled ( * server ) ;
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
res = ConnectNamedPipe ( * server , & overlapped ) ;
ok ( ! res & & GetLastError ( ) = = ERROR_IO_PENDING , " WriteFile returned %x(%u) \n " , res , GetLastError ( ) ) ;
test_not_signaled ( * server ) ;
test_not_signaled ( overlapped . hEvent ) ;
2017-03-28 12:29:44 +02:00
* client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , & sec_attr , OPEN_EXISTING , FILE_FLAG_OVERLAPPED , NULL ) ;
2018-04-11 12:08:08 +02:00
ok ( * client ! = INVALID_HANDLE_VALUE , " CreateFile failed: %u \n " , GetLastError ( ) ) ;
2017-03-23 15:42:47 +01:00
res = SetNamedPipeHandleState ( * client , & read_mode , NULL , NULL ) ;
ok ( res , " SetNamedPipeHandleState failed: %u \n " , GetLastError ( ) ) ;
test_signaled ( * client ) ;
test_not_signaled ( * server ) ;
test_overlapped_result ( * server , & overlapped , 0 , FALSE ) ;
}
static void test_overlapped_transport ( BOOL msg_mode , BOOL msg_read_mode )
{
OVERLAPPED overlapped , overlapped2 ;
HANDLE server , client , flush ;
2017-03-28 12:29:44 +02:00
DWORD read_bytes ;
HANDLE process ;
2017-03-23 15:42:47 +01:00
char buf [ 60000 ] ;
BOOL res ;
DWORD create_flags =
( msg_mode ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE ) |
( msg_read_mode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE ) ;
create_overlapped_pipe ( create_flags , & client , & server ) ;
trace ( " testing %s, %s server->client writes... \n " ,
msg_mode ? " message mode " : " byte mode " , msg_read_mode ? " message read " : " byte read " ) ;
test_blocking_rw ( server , client , 5000 , msg_mode , msg_read_mode ) ;
2017-03-26 12:52:50 +02:00
trace ( " testing %s, %s client->server writes... \n " ,
msg_mode ? " message mode " : " byte mode " , msg_read_mode ? " message read " : " byte read " ) ;
test_blocking_rw ( client , server , 6000 , msg_mode , msg_read_mode ) ;
2017-03-23 15:42:47 +01:00
CloseHandle ( client ) ;
CloseHandle ( server ) ;
/* close client with pending writes */
2019-01-07 13:40:28 +01:00
memset ( buf , 0xaa , sizeof ( buf ) ) ;
2017-03-23 15:42:47 +01:00
create_overlapped_pipe ( create_flags , & client , & server ) ;
overlapped_write_async ( server , buf , 7000 , & overlapped ) ;
flush = test_flush_async ( server , ERROR_BROKEN_PIPE ) ;
CloseHandle ( client ) ;
test_overlapped_failure ( server , & overlapped , ERROR_BROKEN_PIPE ) ;
test_flush_done ( flush ) ;
CloseHandle ( server ) ;
/* close server with pending writes */
create_overlapped_pipe ( create_flags , & client , & server ) ;
overlapped_write_async ( client , buf , 7000 , & overlapped ) ;
2017-03-26 12:52:50 +02:00
flush = test_flush_async ( client , ERROR_BROKEN_PIPE ) ;
2017-03-23 15:42:47 +01:00
CloseHandle ( server ) ;
test_overlapped_failure ( client , & overlapped , ERROR_BROKEN_PIPE ) ;
2017-03-26 12:52:50 +02:00
test_flush_done ( flush ) ;
2017-03-23 15:42:47 +01:00
CloseHandle ( client ) ;
/* disconnect with pending writes */
create_overlapped_pipe ( create_flags , & client , & server ) ;
overlapped_write_async ( client , buf , 7000 , & overlapped ) ;
overlapped_write_async ( server , buf , 7000 , & overlapped2 ) ;
2017-03-26 12:52:50 +02:00
flush = test_flush_async ( client , ERROR_PIPE_NOT_CONNECTED ) ;
2017-03-23 15:42:47 +01:00
res = DisconnectNamedPipe ( server ) ;
ok ( res , " DisconnectNamedPipe failed: %u \n " , GetLastError ( ) ) ;
test_overlapped_failure ( client , & overlapped , ERROR_PIPE_NOT_CONNECTED ) ;
test_overlapped_failure ( client , & overlapped2 , ERROR_PIPE_NOT_CONNECTED ) ;
2017-03-26 12:52:50 +02:00
test_flush_done ( flush ) ;
2017-03-23 15:42:47 +01:00
CloseHandle ( server ) ;
CloseHandle ( client ) ;
2017-03-28 12:29:44 +02:00
/* terminate process with pending write */
create_overlapped_pipe ( create_flags , & client , & server ) ;
process = create_writepipe_process ( client ) ;
2017-04-01 14:36:51 +02:00
/* successfully read part of write that is pending in child process */
2017-03-28 12:29:44 +02:00
res = ReadFile ( server , buf , 10 , & read_bytes , NULL ) ;
if ( ! msg_read_mode )
ok ( res , " ReadFile failed: %u \n " , GetLastError ( ) ) ;
else
ok ( ! res & & GetLastError ( ) = = ERROR_MORE_DATA , " ReadFile returned: %x %u \n " , res , GetLastError ( ) ) ;
ok ( read_bytes = = 10 , " read_bytes = %u \n " , read_bytes ) ;
TerminateProcess ( process , 0 ) ;
2020-03-16 23:52:21 +01:00
wait_child_process ( process ) ;
2017-03-28 12:29:44 +02:00
/* after terminating process, there is no pending write and pipe buffer is empty */
overlapped_read_async ( server , buf , 10 , & overlapped ) ;
overlapped_write_sync ( client , buf , 1 ) ;
test_overlapped_result ( server , & overlapped , 1 , FALSE ) ;
CloseHandle ( process ) ;
CloseHandle ( server ) ;
CloseHandle ( client ) ;
2017-03-23 15:42:47 +01:00
}
2018-03-28 22:46:51 +02:00
static void test_transact ( HANDLE caller , HANDLE callee , DWORD write_buf_size , DWORD read_buf_size )
{
OVERLAPPED overlapped , overlapped2 , read_overlapped , write_overlapped ;
char buf [ 10000 ] , read_buf [ 10000 ] ;
memset ( buf , 0xaa , sizeof ( buf ) ) ;
/* simple transact call */
overlapped_transact ( caller , ( BYTE * ) " abc " , 3 , read_buf , 100 , & overlapped ) ;
overlapped_write_sync ( callee , ( BYTE * ) " test " , 4 ) ;
test_overlapped_result ( caller , & overlapped , 4 , FALSE ) ;
ok ( ! memcmp ( read_buf , " test " , 4 ) , " unexpected read_buf \n " ) ;
overlapped_read_sync ( callee , read_buf , 1000 , 3 , FALSE ) ;
ok ( ! memcmp ( read_buf , " abc " , 3 ) , " unexpected read_buf \n " ) ;
/* transact fails if there is already data in read buffer */
overlapped_write_sync ( callee , buf , 1 ) ;
overlapped_transact_failure ( caller , buf , 2 , read_buf , 1 , ERROR_PIPE_BUSY ) ;
overlapped_read_sync ( caller , read_buf , 1000 , 1 , FALSE ) ;
/* transact doesn't block on write */
overlapped_write_async ( caller , buf , write_buf_size + 2000 , & write_overlapped ) ;
overlapped_transact ( caller , buf , 2 , read_buf , 1 , & overlapped ) ;
test_not_signaled ( overlapped . hEvent ) ;
overlapped_write_sync ( callee , buf , 1 ) ;
test_overlapped_result ( caller , & overlapped , 1 , FALSE ) ;
overlapped_read_sync ( callee , read_buf , sizeof ( read_buf ) , write_buf_size + 2000 , FALSE ) ;
test_overlapped_result ( caller , & write_overlapped , write_buf_size + 2000 , FALSE ) ;
overlapped_read_sync ( callee , read_buf , sizeof ( read_buf ) , 2 , FALSE ) ;
/* transact with already pending read */
overlapped_read_async ( callee , read_buf , 10 , & read_overlapped ) ;
overlapped_transact ( caller , buf , 5 , read_buf , 6 , & overlapped ) ;
test_overlapped_result ( callee , & read_overlapped , 5 , FALSE ) ;
test_not_signaled ( overlapped . hEvent ) ;
overlapped_write_sync ( callee , buf , 10 ) ;
test_overlapped_result ( caller , & overlapped , 6 , TRUE ) ;
overlapped_read_sync ( caller , read_buf , sizeof ( read_buf ) , 4 , FALSE ) ;
/* 0-size messages */
overlapped_transact ( caller , buf , 5 , read_buf , 0 , & overlapped ) ;
overlapped_read_sync ( callee , read_buf , sizeof ( read_buf ) , 5 , FALSE ) ;
overlapped_write_sync ( callee , buf , 0 ) ;
test_overlapped_result ( caller , & overlapped , 0 , FALSE ) ;
overlapped_transact ( caller , buf , 0 , read_buf , 0 , & overlapped ) ;
overlapped_read_sync ( callee , read_buf , sizeof ( read_buf ) , 0 , FALSE ) ;
test_not_signaled ( overlapped . hEvent ) ;
overlapped_write_sync ( callee , buf , 0 ) ;
test_overlapped_result ( caller , & overlapped , 0 , FALSE ) ;
/* reply transact with another transact */
overlapped_transact ( caller , buf , 3 , read_buf , 100 , & overlapped ) ;
overlapped_read_sync ( callee , read_buf , 1000 , 3 , FALSE ) ;
overlapped_transact ( callee , buf , 4 , read_buf , 100 , & overlapped2 ) ;
test_overlapped_result ( caller , & overlapped , 4 , FALSE ) ;
overlapped_write_sync ( caller , buf , 1 ) ;
test_overlapped_result ( caller , & overlapped2 , 1 , FALSE ) ;
if ( ! pCancelIoEx ) return ;
/* cancel keeps written data */
overlapped_write_async ( caller , buf , write_buf_size + 2000 , & write_overlapped ) ;
overlapped_transact ( caller , buf , 2 , read_buf , 1 , & overlapped ) ;
test_not_signaled ( overlapped . hEvent ) ;
cancel_overlapped ( caller , & overlapped ) ;
overlapped_read_sync ( callee , read_buf , sizeof ( read_buf ) , write_buf_size + 2000 , FALSE ) ;
test_overlapped_result ( caller , & write_overlapped , write_buf_size + 2000 , FALSE ) ;
overlapped_read_sync ( callee , read_buf , sizeof ( read_buf ) , 2 , FALSE ) ;
}
static void test_TransactNamedPipe ( void )
{
HANDLE client , server ;
BYTE buf [ 10 ] ;
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
overlapped_transact_failure ( client , buf , 2 , buf , 1 , ERROR_BAD_PIPE ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
create_overlapped_pipe ( PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE , & client , & server ) ;
overlapped_transact_failure ( client , buf , 2 , buf , 1 , ERROR_BAD_PIPE ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
trace ( " testing server->client transaction... \n " ) ;
create_overlapped_pipe ( PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE , & client , & server ) ;
test_transact ( server , client , 5000 , 6000 ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
trace ( " testing client->server transaction... \n " ) ;
create_overlapped_pipe ( PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE , & client , & server ) ;
test_transact ( client , server , 6000 , 5000 ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
}
2018-04-11 14:32:56 +02:00
static HANDLE create_overlapped_server ( OVERLAPPED * overlapped )
{
HANDLE pipe ;
BOOL ret ;
pipe = CreateNamedPipeA ( PIPENAME , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX , PIPE_READMODE_BYTE | PIPE_WAIT ,
1 , 5000 , 6000 , NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( pipe ! = INVALID_HANDLE_VALUE , " got %u \n " , GetLastError ( ) ) ;
ret = ConnectNamedPipe ( pipe , overlapped ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_IO_PENDING , " got %u \n " , GetLastError ( ) ) ;
return pipe ;
}
static void child_process_check_pid ( DWORD server_pid )
{
DWORD current = GetProcessId ( GetCurrentProcess ( ) ) ;
HANDLE pipe ;
ULONG pid ;
BOOL ret ;
pipe = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , NULL ) ;
ok ( pipe ! = INVALID_HANDLE_VALUE , " got %u \n " , GetLastError ( ) ) ;
pid = 0 ;
ret = pGetNamedPipeClientProcessId ( pipe , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x \n " , pid ) ;
pid = 0 ;
ret = pGetNamedPipeServerProcessId ( pipe , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = server_pid , " got %04x expected %04x \n " , pid , server_pid ) ;
CloseHandle ( pipe ) ;
}
static HANDLE create_check_id_process ( const char * verb , DWORD id )
{
STARTUPINFOA si = { sizeof ( si ) } ;
PROCESS_INFORMATION info ;
char * * argv , buf [ MAX_PATH ] ;
BOOL ret ;
winetest_get_mainargs ( & argv ) ;
sprintf ( buf , " \" %s \" pipe %s %x " , argv [ 0 ] , verb , id ) ;
ret = CreateProcessA ( NULL , buf , NULL , NULL , TRUE , 0 , NULL , NULL , & si , & info ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( info . hThread ) ;
return info . hProcess ;
}
static void test_namedpipe_process_id ( void )
{
HANDLE client , server , process ;
DWORD current = GetProcessId ( GetCurrentProcess ( ) ) ;
OVERLAPPED overlapped ;
ULONG pid ;
BOOL ret ;
if ( ! pGetNamedPipeClientProcessId )
{
win_skip ( " GetNamedPipeClientProcessId not available \n " ) ;
return ;
}
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeClientProcessId ( server , NULL ) ;
ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_INSUFFICIENT_BUFFER , " got %u \n " , GetLastError ( ) ) ;
pid = 0 ;
ret = pGetNamedPipeClientProcessId ( server , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
pid = 0 ;
ret = pGetNamedPipeClientProcessId ( client , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeServerProcessId ( server , NULL ) ;
ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_INSUFFICIENT_BUFFER , " got %u \n " , GetLastError ( ) ) ;
pid = 0 ;
ret = pGetNamedPipeServerProcessId ( client , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
pid = 0 ;
ret = pGetNamedPipeServerProcessId ( server , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
/* closed client handle */
CloseHandle ( client ) ;
pid = 0 ;
ret = pGetNamedPipeClientProcessId ( server , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
pid = 0 ;
ret = pGetNamedPipeServerProcessId ( server , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
CloseHandle ( server ) ;
/* disconnected server */
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
DisconnectNamedPipe ( server ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeClientProcessId ( server , & pid ) ;
todo_wine ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_NOT_FOUND , " got %u \n " , GetLastError ( ) ) ;
pid = 0 ;
ret = pGetNamedPipeServerProcessId ( server , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeClientProcessId ( client , & pid ) ;
todo_wine ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " got %u \n " , GetLastError ( ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeServerProcessId ( client , & pid ) ;
todo_wine ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
/* closed server handle */
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
CloseHandle ( server ) ;
pid = 0 ;
ret = pGetNamedPipeClientProcessId ( client , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
pid = 0 ;
ret = pGetNamedPipeServerProcessId ( client , & pid ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( pid = = current , " got %04x expected %04x \n " , pid , current ) ;
CloseHandle ( client ) ;
/* different process */
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
server = create_overlapped_server ( & overlapped ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " got %u \n " , GetLastError ( ) ) ;
process = create_check_id_process ( " checkpid " , GetProcessId ( GetCurrentProcess ( ) ) ) ;
2020-03-16 23:52:21 +01:00
wait_child_process ( process ) ;
2018-04-11 14:32:56 +02:00
CloseHandle ( overlapped . hEvent ) ;
CloseHandle ( process ) ;
CloseHandle ( server ) ;
}
2018-04-11 14:32:57 +02:00
static void child_process_check_session_id ( DWORD server_id )
{
DWORD current ;
HANDLE pipe ;
ULONG id ;
BOOL ret ;
ProcessIdToSessionId ( GetProcessId ( GetCurrentProcess ( ) ) , & current ) ;
pipe = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , NULL ) ;
ok ( pipe ! = INVALID_HANDLE_VALUE , " got %u \n " , GetLastError ( ) ) ;
id = 0 ;
ret = pGetNamedPipeClientSessionId ( pipe , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %04x \n " , id ) ;
id = 0 ;
ret = pGetNamedPipeServerSessionId ( pipe , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = server_id , " got %04x expected %04x \n " , id , server_id ) ;
CloseHandle ( pipe ) ;
}
static void test_namedpipe_session_id ( void )
{
HANDLE client , server , process ;
OVERLAPPED overlapped ;
DWORD current ;
ULONG id ;
BOOL ret ;
if ( ! pGetNamedPipeClientSessionId )
{
win_skip ( " GetNamedPipeClientSessionId not available \n " ) ;
return ;
}
ProcessIdToSessionId ( GetProcessId ( GetCurrentProcess ( ) ) , & current ) ;
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
2019-04-23 19:19:21 +02:00
if ( 0 ) /* crashes on recent Windows */
{
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeClientSessionId ( server , NULL ) ;
ok ( ! ret , " success \n " ) ;
}
2018-04-11 14:32:57 +02:00
id = 0 ;
ret = pGetNamedPipeClientSessionId ( server , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %u expected %u \n " , id , current ) ;
id = 0 ;
ret = pGetNamedPipeClientSessionId ( client , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %u expected %u \n " , id , current ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeServerSessionId ( server , NULL ) ;
ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_INSUFFICIENT_BUFFER , " got %u \n " , GetLastError ( ) ) ;
id = 0 ;
ret = pGetNamedPipeServerSessionId ( client , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %u expected %u \n " , id , current ) ;
id = 0 ;
ret = pGetNamedPipeServerSessionId ( server , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %u expected %u \n " , id , current ) ;
/* closed client handle */
CloseHandle ( client ) ;
id = 0 ;
ret = pGetNamedPipeClientSessionId ( server , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %04x expected %04x \n " , id , current ) ;
id = 0 ;
ret = pGetNamedPipeServerSessionId ( server , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %04x expected %04x \n " , id , current ) ;
CloseHandle ( server ) ;
/* disconnected server */
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
DisconnectNamedPipe ( server ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeClientSessionId ( server , & id ) ;
todo_wine ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_NOT_FOUND , " got %u \n " , GetLastError ( ) ) ;
id = 0 ;
ret = pGetNamedPipeServerSessionId ( server , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %04x expected %04x \n " , id , current ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeClientSessionId ( client , & id ) ;
todo_wine ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " got %u \n " , GetLastError ( ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetNamedPipeServerSessionId ( client , & id ) ;
todo_wine ok ( ! ret , " success \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_PIPE_NOT_CONNECTED , " got %u \n " , GetLastError ( ) ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
/* closed server handle */
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
CloseHandle ( server ) ;
id = 0 ;
ret = pGetNamedPipeClientSessionId ( client , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %04x expected %04x \n " , id , current ) ;
id = 0 ;
ret = pGetNamedPipeServerSessionId ( client , & id ) ;
ok ( ret , " got %u \n " , GetLastError ( ) ) ;
ok ( id = = current , " got %04x expected %04x \n " , id , current ) ;
CloseHandle ( client ) ;
/* different process */
memset ( & overlapped , 0 , sizeof ( overlapped ) ) ;
overlapped . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
server = create_overlapped_server ( & overlapped ) ;
ok ( server ! = INVALID_HANDLE_VALUE , " got %u \n " , GetLastError ( ) ) ;
process = create_check_id_process ( " checksessionid " , current ) ;
2020-03-16 23:52:21 +01:00
wait_child_process ( process ) ;
2018-04-11 14:32:57 +02:00
CloseHandle ( overlapped . hEvent ) ;
CloseHandle ( process ) ;
CloseHandle ( server ) ;
}
2019-02-26 12:06:25 +01:00
static void test_multiple_instances ( void )
{
2019-03-11 17:03:23 +01:00
HANDLE server [ 4 ] , client ;
2019-02-26 12:06:25 +01:00
int i ;
BOOL ret ;
OVERLAPPED ov ;
2019-03-11 17:03:23 +01:00
if ( ! pCancelIoEx )
{
2019-03-16 23:48:21 +01:00
win_skip ( " Skipping multiple instance tests on too old Windows \n " ) ;
2019-03-11 17:03:23 +01:00
return ;
}
2019-02-26 12:06:25 +01:00
for ( i = 0 ; i < ARRAY_SIZE ( server ) ; i + + )
{
server [ i ] = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED ,
2019-03-11 17:03:23 +01:00
PIPE_READMODE_BYTE | PIPE_WAIT , ARRAY_SIZE ( server ) , 1024 , 1024 ,
2019-02-26 12:06:25 +01:00
NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( server [ i ] ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
}
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
2019-03-11 17:03:23 +01:00
/* Show that this has connected to server[0] not any other one */
2019-02-26 12:06:25 +01:00
memset ( & ov , 0 , sizeof ( ov ) ) ;
2019-03-11 17:03:23 +01:00
ret = ConnectNamedPipe ( server [ 2 ] , & ov ) ;
2019-02-26 12:06:25 +01:00
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d \n " , GetLastError ( ) ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 0 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_PIPE_CONNECTED , " got %d \n " , GetLastError ( ) ) ;
2019-03-11 17:03:23 +01:00
CloseHandle ( client ) ;
/* The next connected server is server[1], doesn't matter that server[2] has pending listeners */
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 2 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d \n " , GetLastError ( ) ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 1 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_PIPE_CONNECTED , " got %d \n " , GetLastError ( ) ) ;
CloseHandle ( client ) ;
/* server[2] is connected next */
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 2 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_PIPE_CONNECTED , " got %d \n " , GetLastError ( ) ) ;
CloseHandle ( client ) ;
/* Disconnect in order server[0] and server[2] */
2019-02-26 12:06:25 +01:00
DisconnectNamedPipe ( server [ 0 ] ) ;
2019-03-11 17:03:23 +01:00
DisconnectNamedPipe ( server [ 2 ] ) ;
/* Put into listening state server[2] and server[0] */
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 2 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d \n " , GetLastError ( ) ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 0 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d \n " , GetLastError ( ) ) ;
/* server[3] is connected next */
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 3 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_PIPE_CONNECTED , " got %d \n " , GetLastError ( ) ) ;
CloseHandle ( client ) ;
/* server[2], which stasted listening first, will be connected next */
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 2 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_PIPE_CONNECTED , " got %d \n " , GetLastError ( ) ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 0 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d \n " , GetLastError ( ) ) ;
2019-02-26 12:06:25 +01:00
CloseHandle ( client ) ;
2019-03-11 17:03:23 +01:00
/* Finally server[0] is connected */
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ret = ConnectNamedPipe ( server [ 0 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_PIPE_CONNECTED , " got %d \n " , GetLastError ( ) ) ;
CloseHandle ( client ) ;
/* No more listening pipes available */
DisconnectNamedPipe ( server [ 0 ] ) ;
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( client = = INVALID_HANDLE_VALUE & & GetLastError ( ) = = ERROR_PIPE_BUSY , " got %p(%u) \n " , client , GetLastError ( ) ) ;
for ( i = 0 ; i < ARRAY_SIZE ( server ) ; i + + )
{
DisconnectNamedPipe ( server [ i ] ) ;
CloseHandle ( server [ i ] ) ;
}
2019-02-26 12:06:25 +01:00
}
2019-03-11 17:03:33 +01:00
static DWORD WINAPI wait_pipe_proc ( void * arg )
{
BOOL ret ;
ret = WaitNamedPipeA ( PIPENAME , 1000 ) ;
ok ( ret , " WaitNamedPipe failed (%u) \n " , GetLastError ( ) ) ;
return 0 ;
}
static HANDLE async_wait_pipe ( void )
{
HANDLE thread ;
BOOL ret ;
thread = CreateThread ( NULL , 0 , wait_pipe_proc , NULL , 0 , NULL ) ;
ok ( thread ! = NULL , " CreateThread failed: %u \n " , GetLastError ( ) ) ;
ret = WaitNamedPipeA ( PIPENAME , 1 ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_SEM_TIMEOUT , " WaitNamedPipe failed %x(%u) \n " , ret , GetLastError ( ) ) ;
return thread ;
}
static void test_wait_pipe ( void )
{
HANDLE server [ 2 ] , client , wait ;
OVERLAPPED ov ;
DWORD res ;
BOOL ret ;
ret = WaitNamedPipeA ( PIPENAME , 0 ) ;
ok ( ! ret & & GetLastError ( ) = = ERROR_FILE_NOT_FOUND , " WaitNamedPipe failed %x(%u) \n " , ret , GetLastError ( ) ) ;
server [ 0 ] = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED ,
PIPE_READMODE_BYTE | PIPE_WAIT , ARRAY_SIZE ( server ) , 1024 , 1024 ,
NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( server [ 0 ] ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
ret = WaitNamedPipeA ( PIPENAME , 1 ) ;
ok ( ret , " WaitNamedPipe failed (%u) \n " , GetLastError ( ) ) ;
client = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( client ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
/* Creating a new pipe server wakes waiters */
wait = async_wait_pipe ( ) ;
server [ 1 ] = CreateNamedPipeA ( PIPENAME , PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED ,
PIPE_READMODE_BYTE | PIPE_WAIT , ARRAY_SIZE ( server ) , 1024 , 1024 ,
NMPWAIT_USE_DEFAULT_WAIT , NULL ) ;
ok ( server [ 1 ] ! = INVALID_HANDLE_VALUE , " got invalid handle \n " ) ;
res = WaitForSingleObject ( wait , 100 ) ;
ok ( res = = WAIT_OBJECT_0 , " WaitForSingleObject returned %u \n " , res ) ;
CloseHandle ( wait ) ;
CloseHandle ( server [ 1 ] ) ;
CloseHandle ( client ) ;
ret = DisconnectNamedPipe ( server [ 0 ] ) ;
ok ( ret , " DisconnectNamedPipe failed (%u) \n " , GetLastError ( ) ) ;
/* Putting pipe server into waiting listening state wakes waiters */
wait = async_wait_pipe ( ) ;
memset ( & ov , 0 , sizeof ( ov ) ) ;
ov . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
ret = ConnectNamedPipe ( server [ 0 ] , & ov ) ;
ok ( ret = = FALSE , " got %d \n " , ret ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d \n " , GetLastError ( ) ) ;
res = WaitForSingleObject ( wait , 100 ) ;
ok ( res = = WAIT_OBJECT_0 , " WaitForSingleObject returned %u \n " , res ) ;
CloseHandle ( server [ 0 ] ) ;
res = WaitForSingleObject ( ov . hEvent , 0 ) ;
ok ( res = = WAIT_OBJECT_0 , " WaitForSingleObject returned %u \n " , res ) ;
CloseHandle ( ov . hEvent ) ;
}
2019-10-17 15:17:35 +02:00
static void test_nowait ( DWORD pipe_type )
2019-10-16 14:49:48 +02:00
{
HANDLE piperead , pipewrite , file ;
OVERLAPPED ol , ol2 ;
DWORD read , write ;
char readbuf [ 32768 ] ;
static const char teststring [ ] = " bits " ;
/* CreateNamedPipe with PIPE_NOWAIT, and read from empty pipe */
piperead = CreateNamedPipeA ( PIPENAME , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX ,
2019-10-17 15:17:35 +02:00
/* dwPipeMode */ pipe_type | PIPE_NOWAIT ,
2019-10-16 14:49:48 +02:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 512 ,
/* nInBufSize */ 512 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( piperead ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
pipewrite = CreateFileA ( PIPENAME , GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( pipewrite ! = INVALID_HANDLE_VALUE , " CreateFileA failed \n " ) ;
memset ( & ol , 0 , sizeof ( ol ) ) ;
ol . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , & ol ) = = FALSE , " ReadFile should fail \n " ) ;
2019-10-16 14:50:02 +02:00
ok ( GetLastError ( ) = = ERROR_NO_DATA , " got %d should be ERROR_NO_DATA \n " , GetLastError ( ) ) ;
2019-10-16 14:49:48 +02:00
if ( GetLastError ( ) = = ERROR_IO_PENDING )
CancelIo ( piperead ) ;
/* test a small write/read */
ok ( WriteFile ( pipewrite , teststring , sizeof ( teststring ) , & write , NULL ) , " WriteFile should succeed \n " ) ;
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , & ol ) , " ReadFile should succeed \n " ) ;
ok ( read = = write , " read/write bytes should match \n " ) ;
ok ( CloseHandle ( ol . hEvent ) , " CloseHandle for the event failed \n " ) ;
ok ( CloseHandle ( pipewrite ) , " CloseHandle for the write pipe failed \n " ) ;
ok ( CloseHandle ( piperead ) , " CloseHandle for the read pipe failed \n " ) ;
/* create write side with PIPE_NOWAIT, read side PIPE_WAIT, and test writes */
pipewrite = CreateNamedPipeA ( PIPENAME , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX ,
2019-10-17 15:17:35 +02:00
/* dwPipeMode */ pipe_type | PIPE_NOWAIT ,
2019-10-16 14:49:48 +02:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 512 ,
/* nInBufSize */ 512 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( pipewrite ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
piperead = CreateFileA ( PIPENAME , GENERIC_READ , 0 , NULL , OPEN_EXISTING , FILE_FLAG_OVERLAPPED , 0 ) ;
ok ( piperead ! = INVALID_HANDLE_VALUE , " CreateFileA failed \n " ) ;
memset ( & ol , 0 , sizeof ( ol ) ) ;
ol . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
memset ( & ol2 , 0 , sizeof ( ol2 ) ) ;
ol2 . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
/* write one byte larger than the buffer size, should fail */
SetLastError ( 0xdeadbeef ) ;
2019-10-16 14:50:34 +02:00
ok ( WriteFile ( pipewrite , readbuf , 513 , & write , & ol ) , " WriteFile should succeed \n " ) ;
2019-10-16 14:49:48 +02:00
/* WriteFile only documents that 'write < sizeof(readbuf)' for this case, but Windows
* doesn ' t seem to do partial writes ( ' write = = 0 ' always )
*/
ok ( write < sizeof ( readbuf ) , " WriteFile should fail to write the whole buffer \n " ) ;
ok ( write = = 0 , " WriteFile doesn't do partial writes here \n " ) ;
if ( GetLastError ( ) = = ERROR_IO_PENDING )
CancelIo ( piperead ) ;
/* overlapped read of 32768, non-blocking write of 512 */
SetLastError ( 0xdeadbeef ) ;
2019-10-16 14:50:34 +02:00
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , & ol2 ) = = FALSE , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d should be ERROR_IO_PENDING \n " , GetLastError ( ) ) ;
2019-10-16 14:49:48 +02:00
ok ( WriteFile ( pipewrite , teststring , sizeof ( teststring ) , & write , & ol ) , " WriteFile should succeed \n " ) ;
ok ( write = = sizeof ( teststring ) , " got %d \n " , write ) ;
ok ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) , " GetOverlappedResult should succeed \n " ) ;
2019-10-16 14:50:34 +02:00
ok ( read = = sizeof ( teststring ) , " got %d \n " , read ) ;
2019-10-16 14:49:48 +02:00
if ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) = = FALSE )
CancelIo ( piperead ) ;
/* overlapped read of 32768, non-blocking write of 513 */
SetLastError ( 0xdeadbeef ) ;
2019-10-16 14:50:34 +02:00
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , & ol2 ) = = FALSE , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d should be ERROR_IO_PENDING \n " , GetLastError ( ) ) ;
ok ( WriteFile ( pipewrite , readbuf , 513 , & write , & ol ) , " WriteFile should succeed \n " ) ;
ok ( write = = 513 , " got %d, write should be %d \n " , write , 513 ) ;
2019-10-16 14:49:48 +02:00
ok ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) , " GetOverlappedResult should succeed \n " ) ;
2019-10-16 14:50:34 +02:00
ok ( read = = 513 , " got %d, read should be %d \n " , read , 513 ) ;
2019-10-16 14:49:48 +02:00
if ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) = = FALSE )
CancelIo ( piperead ) ;
/* overlapped read of 1 byte, non-blocking write of 513 bytes */
SetLastError ( 0xdeadbeef ) ;
2019-10-16 14:50:34 +02:00
ok ( ReadFile ( piperead , readbuf , 1 , & read , & ol2 ) = = FALSE , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d should be ERROR_IO_PENDING \n " , GetLastError ( ) ) ;
ok ( WriteFile ( pipewrite , readbuf , 513 , & write , & ol ) , " WriteFile should succeed \n " ) ;
ok ( write = = 513 , " got %d, write should be %d \n " , write , 513 ) ;
2019-10-16 14:49:48 +02:00
ok ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) , " GetOverlappedResult should succeed \n " ) ;
ok ( read = = 1 , " got %d, read should be %d \n " , read , 1 ) ;
if ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) = = FALSE )
CancelIo ( piperead ) ;
/* read the remaining 512 bytes */
SetLastError ( 0xdeadbeef ) ;
ok ( ReadFile ( piperead , readbuf , sizeof ( readbuf ) , & read , & ol2 ) , " ReadFile should succeed \n " ) ;
2019-10-16 14:50:34 +02:00
ok ( read = = 512 , " got %d, write should be %d \n " , write , 512 ) ;
2019-10-16 14:49:48 +02:00
if ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) = = FALSE )
CancelIo ( piperead ) ;
/* overlapped read of 1 byte, non-blocking write of 514 bytes */
SetLastError ( 0xdeadbeef ) ;
ok ( ReadFile ( piperead , readbuf , 1 , & read , & ol2 ) = = FALSE , " ReadFile should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got %d should be ERROR_IO_PENDING \n " , GetLastError ( ) ) ;
2019-10-16 14:50:34 +02:00
ok ( WriteFile ( pipewrite , readbuf , 514 , & write , & ol ) , " WriteFile should succeed \n " ) ;
2019-10-17 15:17:35 +02:00
if ( pipe_type = = PIPE_TYPE_MESSAGE )
{
todo_wine
ok ( write = = 0 , " got %d \n " , write ) ;
todo_wine
ok ( ! GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) , " GetOverlappedResult should fail \n " ) ;
todo_wine
ok ( GetLastError ( ) = = ERROR_IO_INCOMPLETE , " got %d should be ERROR_IO_PENDING \n " , GetLastError ( ) ) ;
todo_wine
ok ( read = = 0 , " got %d, read should be %d \n " , read , 1 ) ;
}
else
{
ok ( write = = 1 , " got %d \n " , write ) ;
ok ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) , " GetOverlappedResult should fail \n " ) ;
ok ( read = = 1 , " got %d, read should be %d \n " , read , 1 ) ;
}
2019-10-16 14:49:48 +02:00
if ( GetOverlappedResult ( piperead , & ol2 , & read , FALSE ) = = FALSE )
CancelIo ( piperead ) ;
/* write the exact buffer size, should succeed */
SetLastError ( 0xdeadbeef ) ;
2019-10-16 14:50:34 +02:00
ok ( WriteFile ( pipewrite , readbuf , 512 , & write , & ol ) , " WriteFile should succeed \n " ) ;
ok ( write = = 512 , " WriteFile should write the whole buffer \n " ) ;
2019-10-16 14:49:48 +02:00
if ( GetLastError ( ) = = ERROR_IO_PENDING )
CancelIo ( piperead ) ;
ok ( CloseHandle ( ol . hEvent ) , " CloseHandle for the event failed \n " ) ;
ok ( CloseHandle ( ol2 . hEvent ) , " CloseHandle for the event failed \n " ) ;
ok ( CloseHandle ( pipewrite ) , " CloseHandle for the write pipe failed \n " ) ;
ok ( CloseHandle ( piperead ) , " CloseHandle for the read pipe failed \n " ) ;
/* CreateNamedPipe with PIPE_NOWAIT, test ConnectNamedPipe */
pipewrite = CreateNamedPipeA ( PIPENAME , FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX ,
2019-10-17 15:17:35 +02:00
/* dwPipeMode */ pipe_type | PIPE_NOWAIT ,
2019-10-16 14:49:48 +02:00
/* nMaxInstances */ 1 ,
/* nOutBufSize */ 512 ,
/* nInBufSize */ 512 ,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT ,
/* lpSecurityAttrib */ NULL ) ;
ok ( pipewrite ! = INVALID_HANDLE_VALUE , " CreateNamedPipe failed \n " ) ;
memset ( & ol , 0 , sizeof ( ol ) ) ;
ol . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ConnectNamedPipe ( pipewrite , & ol ) = = FALSE , " ConnectNamedPipe should fail \n " ) ;
2019-10-16 14:50:45 +02:00
ok ( GetLastError ( ) = = ERROR_PIPE_LISTENING , " got %d should be ERROR_PIPE_LISTENING \n " , GetLastError ( ) ) ;
2019-10-16 14:49:48 +02:00
if ( GetLastError ( ) = = ERROR_IO_PENDING )
CancelIo ( pipewrite ) ;
/* connect and disconnect, then test ConnectNamedPipe again */
file = CreateFileA ( PIPENAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0 ) ;
ok ( file ! = INVALID_HANDLE_VALUE , " CreateFileA failed \n " ) ;
ok ( CloseHandle ( file ) , " CloseHandle failed \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ConnectNamedPipe ( pipewrite , & ol ) = = FALSE , " ConnectNamedPipe should fail \n " ) ;
ok ( GetLastError ( ) = = ERROR_NO_DATA , " got %d should be ERROR_NO_DATA \n " , GetLastError ( ) ) ;
if ( GetLastError ( ) = = ERROR_IO_PENDING )
CancelIo ( pipewrite ) ;
/* call DisconnectNamedPipe and test ConnectNamedPipe again */
ok ( DisconnectNamedPipe ( pipewrite ) = = TRUE , " DisconnectNamedPipe should succeed \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ok ( ConnectNamedPipe ( pipewrite , & ol ) = = FALSE , " ConnectNamedPipe should fail \n " ) ;
2019-10-16 14:50:45 +02:00
ok ( GetLastError ( ) = = ERROR_PIPE_LISTENING , " got %d should be ERROR_PIPE_LISTENING \n " , GetLastError ( ) ) ;
2019-10-16 14:49:48 +02:00
if ( GetLastError ( ) = = ERROR_IO_PENDING )
CancelIo ( pipewrite ) ;
ok ( CloseHandle ( ol . hEvent ) , " CloseHandle for the event failed \n " ) ;
ok ( CloseHandle ( pipewrite ) , " CloseHandle for the write pipe failed \n " ) ;
}
2019-11-29 01:19:21 +01:00
static void test_GetOverlappedResultEx ( void )
{
HANDLE client , server ;
OVERLAPPED ovl ;
char buffer [ 8000 ] ;
DWORD ret_size ;
BOOL ret ;
if ( ! pGetOverlappedResultEx )
{
win_skip ( " GetOverlappedResultEx() is not available \n " ) ;
return ;
}
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
overlapped_write_async ( client , buffer , sizeof ( buffer ) , & ovl ) ;
user_apc_ran = FALSE ;
QueueUserAPC ( user_apc , GetCurrentThread ( ) , 0 ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetOverlappedResultEx ( client , & ovl , & ret_size , 0 , FALSE ) ;
ok ( ! ret , " expected failure \n " ) ;
ok ( GetLastError ( ) = = ERROR_IO_INCOMPLETE , " wrong error %u \n " , GetLastError ( ) ) ;
ok ( ! user_apc_ran , " APC should not have run \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetOverlappedResultEx ( client , & ovl , & ret_size , 0 , TRUE ) ;
ok ( ! ret , " expected failure \n " ) ;
ok ( GetLastError ( ) = = ERROR_IO_INCOMPLETE , " wrong error %u \n " , GetLastError ( ) ) ;
ok ( ! user_apc_ran , " APC should not have run \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetOverlappedResultEx ( client , & ovl , & ret_size , 10 , FALSE ) ;
ok ( ! ret , " expected failure \n " ) ;
ok ( GetLastError ( ) = = WAIT_TIMEOUT , " wrong error %u \n " , GetLastError ( ) ) ;
ok ( ! user_apc_ran , " APC should not have run \n " ) ;
SetLastError ( 0xdeadbeef ) ;
ret = pGetOverlappedResultEx ( client , & ovl , & ret_size , 10 , TRUE ) ;
ok ( ! ret , " expected failure \n " ) ;
ok ( GetLastError ( ) = = WAIT_IO_COMPLETION , " wrong error %u \n " , GetLastError ( ) ) ;
ok ( user_apc_ran , " APC should have run \n " ) ;
CloseHandle ( ovl . hEvent ) ;
CloseHandle ( client ) ;
CloseHandle ( server ) ;
}
2021-02-24 23:11:34 +01:00
static void child_process_exit_process_async ( DWORD parent_pid , HANDLE parent_pipe )
{
OVERLAPPED overlapped = { 0 } ;
static char buffer [ 1 ] ;
HANDLE parent , pipe ;
BOOL ret ;
parent = OpenProcess ( PROCESS_DUP_HANDLE , FALSE , parent_pid ) ;
ok ( ! ! parent , " got parent %p \n " , parent ) ;
ret = DuplicateHandle ( parent , parent_pipe , GetCurrentProcess ( ) , & pipe , 0 ,
FALSE , DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE ) ;
ok ( ret , " got error %u \n " , GetLastError ( ) ) ;
overlapped . hEvent = CreateEventW ( NULL , TRUE , FALSE , NULL ) ;
ret = ReadFile ( pipe , buffer , sizeof ( buffer ) , NULL , & overlapped ) ;
ok ( ! ret , " expected failure \n " ) ;
ok ( GetLastError ( ) = = ERROR_IO_PENDING , " got error %u \n " , GetLastError ( ) ) ;
/* exit without closing the pipe handle */
}
static void test_exit_process_async ( void )
{
HANDLE client , server , port ;
OVERLAPPED * overlapped ;
PROCESS_INFORMATION pi ;
STARTUPINFOA si = { 0 } ;
char cmdline [ 300 ] ;
ULONG_PTR key ;
char * * argv ;
DWORD size ;
BOOL ret ;
winetest_get_mainargs ( & argv ) ;
create_overlapped_pipe ( PIPE_TYPE_BYTE , & client , & server ) ;
port = CreateIoCompletionPort ( client , NULL , 123 , 0 ) ;
sprintf ( cmdline , " %s pipe exit_process_async %x %p " , argv [ 0 ] , GetCurrentProcessId ( ) , client ) ;
ret = CreateProcessA ( NULL , cmdline , NULL , NULL , FALSE , 0 , NULL , NULL , & si , & pi ) ;
ok ( ret , " got error %u \n " , GetLastError ( ) ) ;
ret = WaitForSingleObject ( pi . hProcess , 1000 ) ;
ok ( ! ret , " wait timed out \n " ) ;
CloseHandle ( pi . hThread ) ;
CloseHandle ( pi . hProcess ) ;
key = 0xdeadbeef ;
size = 0xdeadbeef ;
ret = GetQueuedCompletionStatus ( port , & size , & key , & overlapped , 1000 ) ;
ok ( ! ret , " expected failure \n " ) ;
2021-02-24 23:11:35 +01:00
ok ( GetLastError ( ) = = ERROR_OPERATION_ABORTED , " got error %u \n " , GetLastError ( ) ) ;
ok ( ! size , " got size %u \n " , size ) ;
ok ( key = = 123 , " got key %Iu \n " , key ) ;
2021-02-24 23:11:34 +01:00
CloseHandle ( port ) ;
CloseHandle ( server ) ;
}
2003-02-19 23:06:36 +01:00
START_TEST ( pipe )
{
2017-03-28 12:29:44 +02:00
char * * argv ;
int argc ;
2007-03-16 22:37:46 +01:00
HMODULE hmod ;
2013-10-21 10:02:23 +02:00
hmod = GetModuleHandleA ( " advapi32.dll " ) ;
2007-03-16 22:37:46 +01:00
pDuplicateTokenEx = ( void * ) GetProcAddress ( hmod , " DuplicateTokenEx " ) ;
2013-10-21 10:02:23 +02:00
hmod = GetModuleHandleA ( " kernel32.dll " ) ;
2017-03-23 15:42:47 +01:00
pCancelIoEx = ( void * ) GetProcAddress ( hmod , " CancelIoEx " ) ;
2018-04-11 14:32:56 +02:00
pGetNamedPipeClientProcessId = ( void * ) GetProcAddress ( hmod , " GetNamedPipeClientProcessId " ) ;
pGetNamedPipeServerProcessId = ( void * ) GetProcAddress ( hmod , " GetNamedPipeServerProcessId " ) ;
2018-04-11 14:32:57 +02:00
pGetNamedPipeClientSessionId = ( void * ) GetProcAddress ( hmod , " GetNamedPipeClientSessionId " ) ;
pGetNamedPipeServerSessionId = ( void * ) GetProcAddress ( hmod , " GetNamedPipeServerSessionId " ) ;
2019-11-29 01:19:21 +01:00
pGetOverlappedResultEx = ( void * ) GetProcAddress ( hmod , " GetOverlappedResultEx " ) ;
2007-03-16 22:37:46 +01:00
2017-03-28 12:29:44 +02:00
argc = winetest_get_mainargs ( & argv ) ;
2018-04-11 14:32:56 +02:00
if ( argc > 3 )
2017-03-28 12:29:44 +02:00
{
2018-04-11 14:32:56 +02:00
if ( ! strcmp ( argv [ 2 ] , " writepipe " ) )
{
UINT_PTR handle ;
sscanf ( argv [ 3 ] , " %lx " , & handle ) ;
child_process_write_pipe ( ( HANDLE ) handle ) ;
return ;
}
if ( ! strcmp ( argv [ 2 ] , " checkpid " ) )
{
DWORD pid = GetProcessId ( GetCurrentProcess ( ) ) ;
sscanf ( argv [ 3 ] , " %x " , & pid ) ;
child_process_check_pid ( pid ) ;
return ;
}
2018-04-11 14:32:57 +02:00
if ( ! strcmp ( argv [ 2 ] , " checksessionid " ) )
{
DWORD id ;
ProcessIdToSessionId ( GetProcessId ( GetCurrentProcess ( ) ) , & id ) ;
sscanf ( argv [ 3 ] , " %x " , & id ) ;
child_process_check_session_id ( id ) ;
return ;
}
2021-02-24 23:11:34 +01:00
if ( ! strcmp ( argv [ 2 ] , " exit_process_async " ) )
{
HANDLE handle ;
DWORD pid ;
sscanf ( argv [ 3 ] , " %x " , & pid ) ;
sscanf ( argv [ 4 ] , " %p " , & handle ) ;
child_process_exit_process_async ( pid , handle ) ;
return ;
}
2017-03-28 12:29:44 +02:00
}
2005-03-22 22:14:00 +01:00
if ( test_DisconnectNamedPipe ( ) )
return ;
2003-05-16 00:52:41 +02:00
test_CreateNamedPipe_instances_must_match ( ) ;
test_NamedPipe_2 ( ) ;
2004-04-27 01:30:51 +02:00
test_CreateNamedPipe ( PIPE_TYPE_BYTE ) ;
test_CreateNamedPipe ( PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE ) ;
2005-06-05 19:57:10 +02:00
test_CreatePipe ( ) ;
2018-01-23 15:51:31 +01:00
test_ReadFile ( ) ;
2015-11-23 07:22:27 +01:00
test_CloseHandle ( ) ;
2007-03-06 19:00:15 +01:00
test_impersonation ( ) ;
2007-07-16 13:12:18 +02:00
test_overlapped ( ) ;
2016-04-07 08:45:53 +02:00
test_overlapped_error ( ) ;
2009-02-11 19:12:31 +01:00
test_NamedPipeHandleState ( ) ;
2016-10-05 21:27:06 +02:00
test_GetNamedPipeInfo ( ) ;
2012-06-14 21:35:27 +02:00
test_readfileex_pending ( ) ;
2017-03-23 15:42:47 +01:00
test_overlapped_transport ( TRUE , FALSE ) ;
2017-03-26 12:52:39 +02:00
test_overlapped_transport ( TRUE , TRUE ) ;
2017-10-04 15:18:29 +02:00
test_overlapped_transport ( FALSE , FALSE ) ;
2018-03-28 22:46:51 +02:00
test_TransactNamedPipe ( ) ;
2018-04-11 14:32:56 +02:00
test_namedpipe_process_id ( ) ;
2018-04-11 14:32:57 +02:00
test_namedpipe_session_id ( ) ;
2019-02-26 12:06:25 +01:00
test_multiple_instances ( ) ;
2019-03-11 17:03:33 +01:00
test_wait_pipe ( ) ;
2019-10-17 15:17:35 +02:00
test_nowait ( PIPE_TYPE_BYTE ) ;
test_nowait ( PIPE_TYPE_MESSAGE ) ;
2019-11-29 01:19:21 +01:00
test_GetOverlappedResultEx ( ) ;
2021-02-24 23:11:34 +01:00
test_exit_process_async ( ) ;
2003-02-19 23:06:36 +01:00
}