Alexandre Julliard : kernel32: Moved PeekNamedPipe implementation to ntdll.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Nov 2 05:46:44 CST 2006


Module: wine
Branch: master
Commit: 313d93e491f72d8dbbe71a0581c0cbe98a44f944
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=313d93e491f72d8dbbe71a0581c0cbe98a44f944

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Nov  1 16:24:36 2006 +0100

kernel32: Moved PeekNamedPipe implementation to ntdll.

---

 dlls/kernel32/sync.c |   92 ++++++++++----------------------------------------
 dlls/ntdll/file.c    |   74 ++++++++++++++++++++++++++++++++++++++++
 include/winioctl.h   |    8 ++++
 3 files changed, 100 insertions(+), 74 deletions(-)

diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
index 8b90abb..eaa0f70 100644
--- a/dlls/kernel32/sync.c
+++ b/dlls/kernel32/sync.c
@@ -26,18 +26,6 @@ #ifdef HAVE_UNISTD_H
 # 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 "winternl.h"
 #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
 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
                            LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
 {
-#ifdef FIONREAD
-    int avail=0, fd, ret, flags;
-
-    TRACE("(%p,%p,%u,%p,%p,%p)\n", hPipe, lpvBuffer, cbBuffer, lpcbRead, lpcbAvail, lpcbMessage);
+    FILE_PIPE_PEEK_BUFFER local_buffer;
+    FILE_PIPE_PEEK_BUFFER *buffer = &local_buffer;
+    IO_STATUS_BLOCK io;
+    NTSTATUS status;
 
-    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)
-    {
-        TRACE("FIONREAD failed reason: %s\n",strerror(errno));
-        wine_server_release_fd( hPipe, fd );
-        return FALSE;
-    }
-    if (!avail)  /* check for closed pipe */
+    status = NtFsControlFile( hPipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0,
+                              buffer, FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ) );
+    if (!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;
-        }
+        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 );
     }
-    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;
 }
 
 /***********************************************************************
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 18a0e09..a2157d3 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -42,6 +42,15 @@ #endif
 #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 h
         }
         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)
         {
diff --git a/include/winioctl.h b/include/winioctl.h
index 161d8b7..a54c5a5 100644
--- a/include/winioctl.h
+++ b/include/winioctl.h
@@ -411,6 +411,14 @@ typedef struct _FILE_PIPE_WAIT_FOR_BUFFE
     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
 




More information about the wine-cvs mailing list