kernel32: Moved PeekNamedPipe implementation to ntdll.

This commit is contained in:
Alexandre Julliard 2006-11-01 16:24:36 +01:00
parent 2cb4361c06
commit 313d93e491
3 changed files with 100 additions and 74 deletions

View file

@ -26,18 +26,6 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#include <errno.h> #include <errno.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
@ -54,7 +42,6 @@
#include "winioctl.h" #include "winioctl.h"
#include "ddk/wdm.h" #include "ddk/wdm.h"
#include "wine/server.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "kernel_private.h" #include "kernel_private.h"
@ -1194,75 +1181,32 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer, BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage ) LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
{ {
#ifdef FIONREAD FILE_PIPE_PEEK_BUFFER local_buffer;
int avail=0, fd, ret, flags; FILE_PIPE_PEEK_BUFFER *buffer = &local_buffer;
IO_STATUS_BLOCK io;
NTSTATUS status;
TRACE("(%p,%p,%u,%p,%p,%p)\n", hPipe, lpvBuffer, cbBuffer, lpcbRead, lpcbAvail, lpcbMessage); if (cbBuffer && !(buffer = HeapAlloc( GetProcessHeap(), 0,
FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ))))
ret = wine_server_handle_to_fd( hPipe, FILE_READ_DATA, &fd, &flags );
if (ret)
{ {
SetLastError( RtlNtStatusToDosError(ret) ); SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
if (flags & FD_FLAG_RECV_SHUTDOWN)
{
wine_server_release_fd( hPipe, fd );
SetLastError ( ERROR_PIPE_NOT_CONNECTED );
return FALSE; return FALSE;
} }
if (ioctl(fd,FIONREAD, &avail ) != 0) status = NtFsControlFile( hPipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0,
buffer, FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ) );
if (!status)
{ {
TRACE("FIONREAD failed reason: %s\n",strerror(errno)); ULONG read_size = io.Information - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
wine_server_release_fd( hPipe, fd ); if (lpcbAvail) *lpcbAvail = buffer->ReadDataAvailable;
return FALSE; if (lpcbRead) *lpcbRead = read_size;
if (lpcbMessage) *lpcbMessage = 0; /* FIXME */
if (lpvBuffer) memcpy( lpvBuffer, buffer->Data, read_size );
} }
if (!avail) /* check for closed pipe */ else SetLastError( RtlNtStatusToDosError(status) );
{
struct pollfd pollfd;
pollfd.fd = fd;
pollfd.events = POLLIN;
pollfd.revents = 0;
switch (poll( &pollfd, 1, 0 ))
{
case 0:
break;
case 1: /* got something */
if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
TRACE("POLLHUP | POLLERR\n");
/* fall through */
case -1:
wine_server_release_fd( hPipe, fd );
SetLastError(ERROR_BROKEN_PIPE);
return FALSE;
}
}
TRACE(" 0x%08x bytes available\n", avail );
ret = TRUE;
if (lpcbAvail)
*lpcbAvail = avail;
if (lpcbRead)
*lpcbRead = 0;
if (avail && lpvBuffer && cbBuffer)
{
int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
if (readbytes < 0)
{
WARN("failed to peek socket (%d)\n", errno);
ret = FALSE;
}
else if (lpcbRead)
*lpcbRead = readbytes;
}
wine_server_release_fd( hPipe, fd );
return ret;
#endif /* defined(FIONREAD) */
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); if (buffer != &local_buffer) HeapFree( GetProcessHeap(), 0, buffer );
FIXME("function not implemented\n"); return !status;
return FALSE;
} }
/*********************************************************************** /***********************************************************************

View file

@ -42,6 +42,15 @@
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
#endif #endif
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_UTIME_H #ifdef HAVE_UTIME_H
# include <utime.h> # include <utime.h>
#endif #endif
@ -1014,6 +1023,71 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
} }
break; break;
case FSCTL_PIPE_PEEK:
{
FILE_PIPE_PEEK_BUFFER *buffer = out_buffer;
int avail = 0, fd, flags;
if (out_size < FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data ))
{
io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if ((io->u.Status = wine_server_handle_to_fd( handle, FILE_READ_DATA, &fd, &flags )))
break;
if (flags & FD_FLAG_RECV_SHUTDOWN)
{
wine_server_release_fd( handle, fd );
io->u.Status = STATUS_PIPE_DISCONNECTED;
break;
}
#ifdef FIONREAD
if (ioctl( fd, FIONREAD, &avail ) != 0)
{
TRACE("FIONREAD failed reason: %s\n",strerror(errno));
wine_server_release_fd( handle, fd );
io->u.Status = FILE_GetNtStatus();
break;
}
#endif
if (!avail) /* check for closed pipe */
{
struct pollfd pollfd;
int ret;
pollfd.fd = fd;
pollfd.events = POLLIN;
pollfd.revents = 0;
ret = poll( &pollfd, 1, 0 );
if (ret == -1 || (ret == 1 && (pollfd.revents & (POLLHUP|POLLERR))))
{
wine_server_release_fd( handle, fd );
io->u.Status = STATUS_PIPE_BROKEN;
break;
}
}
buffer->NamedPipeState = 0; /* FIXME */
buffer->ReadDataAvailable = avail;
buffer->NumberOfMessages = 0; /* FIXME */
buffer->MessageLength = 0; /* FIXME */
io->Information = FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
io->u.Status = STATUS_SUCCESS;
if (avail)
{
ULONG data_size = out_size - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
if (data_size)
{
int res = recv( fd, buffer->Data, data_size, MSG_PEEK );
if (res >= 0) io->Information += res;
}
}
wine_server_release_fd( handle, fd );
}
break;
case FSCTL_PIPE_DISCONNECT: case FSCTL_PIPE_DISCONNECT:
SERVER_START_REQ(disconnect_named_pipe) SERVER_START_REQ(disconnect_named_pipe)
{ {

View file

@ -411,6 +411,14 @@ typedef struct _FILE_PIPE_WAIT_FOR_BUFFER {
WCHAR Name[1]; WCHAR Name[1];
} FILE_PIPE_WAIT_FOR_BUFFER, *PFILE_PIPE_WAIT_FOR_BUFFER; } FILE_PIPE_WAIT_FOR_BUFFER, *PFILE_PIPE_WAIT_FOR_BUFFER;
typedef struct _FILE_PIPE_PEEK_BUFFER {
ULONG NamedPipeState;
ULONG ReadDataAvailable;
ULONG NumberOfMessages;
ULONG MessageLength;
CHAR Data[1];
} FILE_PIPE_PEEK_BUFFER, *PFILE_PIPE_PEEK_BUFFER;
/* Device GUIDs */ /* Device GUIDs */
#ifdef DEFINE_GUID #ifdef DEFINE_GUID