[PATCH] [NtDll/Kernel32]: pipe information

Eric Pouech eric.pouech at wanadoo.fr
Sat May 20 07:42:23 CDT 2006


Subject: [PATCH] [NtDll/Kernel32]: pipe information
- implemented ntdll!NtQueryInformationFile's FilePipeLocalInformation 
control code
- reimplemented kernel32!GetNamedPipeInfo on top of it
- enhance current features of server protocol:
         - now works both on client and server handles
         - now also returns the number of instances

A+

  dlls/kernel/sync.c             |   39 
++++++++++++++++++---------------------
  dlls/ntdll/file.c              |   35 +++++++++++++++++++++++++++++++----
  include/winbase.h              |    7 ++++---
  include/winternl.h             |   16 ++++++++++++++--
  server/named_pipe.c            |   20 ++++++++++++++++----
  server/protocol.def            |    3 ++-
  6 files changed, 88 insertions(+), 36 deletions(-)


-- 
Eric Pouech
-------------- next part --------------
diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c
index 8c43e53..a4032ea 100644
--- a/dlls/kernel/sync.c
+++ b/dlls/kernel/sync.c
@@ -1460,32 +1460,29 @@ BOOL WINAPI GetNamedPipeInfo(
     HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
     LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
 {
-    BOOL ret;
+    FILE_PIPE_LOCAL_INFORMATION fpli;
+    IO_STATUS_BLOCK iosb;
+    NTSTATUS status;
 
-    TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
-          lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
+    status = NtQueryInformationFile(hNamedPipe, &iosb, &fpli, sizeof(fpli),
+                                    FilePipeLocalInformation);
+    if (status)
+    {
+        SetLastError( RtlNtStatusToDosError(status) );
+        return FALSE;
+    }
 
-    SERVER_START_REQ( get_named_pipe_info )
+    if (lpFlags)
     {
-        req->handle = hNamedPipe;
-        ret = !wine_server_call_err( req );
-        if (lpFlags)
-        {
-            *lpFlags = 0;
-            if (reply->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)
-                *lpFlags |= PIPE_TYPE_MESSAGE;
-            if (reply->flags & NAMED_PIPE_MESSAGE_STREAM_READ)
-                *lpFlags |= PIPE_READMODE_MESSAGE;
-            if (reply->flags & NAMED_PIPE_NONBLOCKING_MODE)
-                *lpFlags |= PIPE_NOWAIT;
-        }
-        if (lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
-        if (lpInputBufferSize) *lpInputBufferSize = reply->outsize;
-        if (lpMaxInstances) *lpMaxInstances = reply->maxinstances;
+        *lpFlags = (fpli.NamedPipeEnd == 1) ? PIPE_SERVER_END : PIPE_CLIENT_END;
+        *lpFlags |= (fpli.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
     }
-    SERVER_END_REQ;
 
-    return ret;
+    if (lpOutputBufferSize) *lpOutputBufferSize = fpli.OutboundQuota;
+    if (lpInputBufferSize) *lpInputBufferSize = fpli.InboundQuota;
+    if (lpMaxInstances) *lpMaxInstances = fpli.MaximumInstances;
+
+    return TRUE;
 }
 
 /***********************************************************************
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index a1ab4e8..52c069c 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -1120,7 +1120,7 @@ NTSTATUS WINAPI NtQueryInformationFile( 
         0,                                             /* FileAlternateNameInformation */
         sizeof(FILE_STREAM_INFORMATION)-sizeof(WCHAR), /* FileStreamInformation */
         0,                                             /* FilePipeInformation */
-        0,                                             /* FilePipeLocalInformation */
+        sizeof(FILE_PIPE_LOCAL_INFORMATION),           /* FilePipeLocalInformation */
         0,                                             /* FilePipeRemoteInformation */
         sizeof(FILE_MAILSLOT_QUERY_INFORMATION),       /* FileMailslotQueryInformation */
         0,                                             /* FileMailslotSetInformation */
@@ -1152,8 +1152,11 @@ NTSTATUS WINAPI NtQueryInformationFile( 
     if (len < info_sizes[class])
         return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
 
-    if ((io->u.Status = wine_server_handle_to_fd( hFile, 0, &fd, NULL )))
-        return io->u.Status;
+    if (class != FilePipeLocalInformation)
+    {
+        if ((io->u.Status = wine_server_handle_to_fd( hFile, 0, &fd, NULL )))
+            return io->u.Status;
+    } else fd = -1;
 
     switch (class)
     {
@@ -1295,12 +1298,36 @@ NTSTATUS WINAPI NtQueryInformationFile( 
             SERVER_END_REQ;
         }
         break;
+    case FilePipeLocalInformation:
+        {
+            FILE_PIPE_LOCAL_INFORMATION* pli = ptr;
+
+            SERVER_START_REQ( get_named_pipe_info )
+            {
+                req->handle = hFile;
+                if (!(io->u.Status = wine_server_call( req )))
+                {
+                    pli->NamedPipeType = (reply->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE) ? 1 : 0;
+                    pli->NamedPipeConfiguration = 0; /* FIXME */
+                    pli->MaximumInstances = reply->maxinstances;
+                    pli->CurrentInstances = reply->instances;
+                    pli->InboundQuota = reply->insize;
+                    pli->ReadDataAvailable = 0; /* FIXME */
+                    pli->OutboundQuota = reply->outsize;
+                    pli->WriteQuotaAvailable = 0; /* FIXME */
+                    pli->NamedPipeState = 0; /* FIXME */
+                    pli->NamedPipeEnd = (reply->flags & NAMED_PIPE_SERVER_END) ? 1 : 0;
+                }
+            }
+            SERVER_END_REQ;
+        }
+        break;
     default:
         FIXME("Unsupported class (%d)\n", class);
         io->u.Status = STATUS_NOT_IMPLEMENTED;
         break;
     }
-    wine_server_release_fd( hFile, fd );
+    if (fd != -1) wine_server_release_fd( hFile, fd );
     if (io->u.Status == STATUS_SUCCESS && !io->Information) io->Information = info_sizes[class];
     return io->u.Status;
 }
diff --git a/include/winbase.h b/include/winbase.h
index fbbbbcd..89dfa1e 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -665,11 +665,12 @@ typedef struct _BY_HANDLE_FILE_INFORMATI
 #define PIPE_ACCESS_OUTBOUND 2
 #define PIPE_ACCESS_DUPLEX   3
 
-#define PIPE_TYPE_BYTE    0
-#define PIPE_TYPE_MESSAGE 4
-
+#define PIPE_CLIENT_END	  0
+#define PIPE_SERVER_END   1
 #define PIPE_READMODE_BYTE    0
 #define PIPE_READMODE_MESSAGE 2
+#define PIPE_TYPE_BYTE    0
+#define PIPE_TYPE_MESSAGE 4
 
 #define PIPE_WAIT   0
 #define PIPE_NOWAIT 1
diff --git a/include/winternl.h b/include/winternl.h
index 973f3e7..0b91c22 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -534,8 +534,20 @@ typedef struct _FILE_MAILSLOT_SET_INFORM
     LARGE_INTEGER ReadTimeout;
 } FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION;
 
-typedef struct _FILE_ALL_INFORMATION
-{
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+    ULONG NamedPipeType;
+    ULONG NamedPipeConfiguration;
+    ULONG MaximumInstances;
+    ULONG CurrentInstances;
+    ULONG InboundQuota;
+    ULONG ReadDataAvailable;
+    ULONG OutboundQuota;
+    ULONG WriteQuotaAvailable;
+    ULONG NamedPipeState;
+    ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _FILE_ALL_INFORMATION {
     FILE_BASIC_INFORMATION     BasicInformation;
     FILE_STANDARD_INFORMATION  StandardInformation;
     FILE_INTERNAL_INFORMATION  InternalInformation;
diff --git a/server/named_pipe.c b/server/named_pipe.c
index c3937b2..7cb8ee6 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -721,7 +721,7 @@ DECL_HANDLER(create_named_pipe)
             release_object( pipe );
             return;
         }
-        set_error( 0 );  /* clear the name collision */
+        clear_error(); /* clear the name collision */
     }
 
     server = create_pipe_server( pipe, req->options );
@@ -930,15 +930,27 @@ DECL_HANDLER(disconnect_named_pipe)
 DECL_HANDLER(get_named_pipe_info)
 {
     struct pipe_server *server;
+    struct pipe_client *client = NULL;
 
-    server = get_pipe_server_obj( current->process, req->handle, 0 );
+    server = get_pipe_server_obj( current->process, req->handle, FILE_READ_ATTRIBUTES );
     if (!server)
-        return;
+    {
+        clear_error();
+        client = (struct named_pipe_client*)get_handle_obj( current->process, req->handle,
+                                                            FILE_READ_ATTRIBUTES, &pipe_client_ops );
+        if (!client) return;
+        server = client->server;
+    }
 
     reply->flags        = server->pipe->flags;
+    reply->flags       |= (client) ? 0 : NAMED_PIPE_SERVER_END;
     reply->maxinstances = server->pipe->maxinstances;
+    reply->instances    = server->pipe->instances;
     reply->insize       = server->pipe->insize;
     reply->outsize      = server->pipe->outsize;
 
-    release_object(server);
+    if (client)
+        release_object(client);
+    else
+        release_object(server);
 }
diff --git a/server/protocol.def b/server/protocol.def
index b7dce66..5fb5f9d 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1736,7 +1736,7 @@ enum message_type
 #define NAMED_PIPE_MESSAGE_STREAM_WRITE 0x0001
 #define NAMED_PIPE_MESSAGE_STREAM_READ  0x0002
 #define NAMED_PIPE_NONBLOCKING_MODE     0x0004
-
+#define NAMED_PIPE_SERVER_END           0x8000
 
 /* Open an existing named pipe */
 @REQ(open_named_pipe)
@@ -1781,6 +1781,7 @@ enum message_type
 @REPLY
     unsigned int   flags;
     unsigned int   maxinstances;
+    unsigned int   instances;
     unsigned int   outsize;
     unsigned int   insize;
 @END



More information about the wine-patches mailing list