kernel32: Moved PeekNamedPipe implementation to ntdll.
This commit is contained in:
parent
2cb4361c06
commit
313d93e491
|
@ -26,18 +26,6 @@
|
|||
# include <unistd.h>
|
||||
#endif
|
||||
#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 <stdio.h>
|
||||
|
||||
|
@ -54,7 +42,6 @@
|
|||
#include "winioctl.h"
|
||||
#include "ddk/wdm.h"
|
||||
|
||||
#include "wine/server.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/winbase16.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,
|
||||
LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
|
||||
{
|
||||
#ifdef FIONREAD
|
||||
int avail=0, fd, ret, flags;
|
||||
FILE_PIPE_PEEK_BUFFER local_buffer;
|
||||
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);
|
||||
|
||||
ret = wine_server_handle_to_fd( hPipe, FILE_READ_DATA, &fd, &flags );
|
||||
if (ret)
|
||||
if (cbBuffer && !(buffer = HeapAlloc( GetProcessHeap(), 0,
|
||||
FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ))))
|
||||
{
|
||||
SetLastError( RtlNtStatusToDosError(ret) );
|
||||
return FALSE;
|
||||
}
|
||||
if (flags & FD_FLAG_RECV_SHUTDOWN)
|
||||
{
|
||||
wine_server_release_fd( hPipe, fd );
|
||||
SetLastError ( ERROR_PIPE_NOT_CONNECTED );
|
||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||
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));
|
||||
wine_server_release_fd( hPipe, fd );
|
||||
return FALSE;
|
||||
ULONG read_size = io.Information - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
|
||||
if (lpcbAvail) *lpcbAvail = buffer->ReadDataAvailable;
|
||||
if (lpcbRead) *lpcbRead = read_size;
|
||||
if (lpcbMessage) *lpcbMessage = 0; /* FIXME */
|
||||
if (lpvBuffer) memcpy( lpvBuffer, buffer->Data, read_size );
|
||||
}
|
||||
if (!avail) /* check for closed pipe */
|
||||
{
|
||||
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) */
|
||||
else SetLastError( RtlNtStatusToDosError(status) );
|
||||
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
FIXME("function not implemented\n");
|
||||
return FALSE;
|
||||
if (buffer != &local_buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||
return !status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -42,6 +42,15 @@
|
|||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.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
|
||||
#ifdef HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#endif
|
||||
|
@ -1014,6 +1023,71 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
|
|||
}
|
||||
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:
|
||||
SERVER_START_REQ(disconnect_named_pipe)
|
||||
{
|
||||
|
|
|
@ -411,6 +411,14 @@ typedef struct _FILE_PIPE_WAIT_FOR_BUFFER {
|
|||
WCHAR Name[1];
|
||||
} 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 */
|
||||
#ifdef DEFINE_GUID
|
||||
|
||||
|
|
Loading…
Reference in New Issue