From de7c3003e22013edc8af8e12a1e9ee09a4961a34 Mon Sep 17 00:00:00 2001
From: Mike McCormack <mike_mccormack@start.com.au>
Date: Tue, 10 Jul 2001 19:16:49 +0000
Subject: [PATCH] Start implementing named pipes.

---
 dlls/kernel/kernel32.spec |   4 +-
 dlls/kernel/sync.c        | 111 +++++++++++++-
 files/file.c              |  34 ++++-
 include/server.h          |  35 ++++-
 include/winbase.h         |  14 ++
 server/Makefile.in        |   1 +
 server/named_pipe.c       | 299 ++++++++++++++++++++++++++++++++++++++
 server/request.h          |   6 +
 server/trace.c            |  44 ++++++
 9 files changed, 537 insertions(+), 11 deletions(-)
 create mode 100644 server/named_pipe.c

diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec
index aa6484b7659..d693cb36f19 100644
--- a/dlls/kernel/kernel32.spec
+++ b/dlls/kernel/kernel32.spec
@@ -186,7 +186,7 @@ debug_channels (comm debugstr dll int resource stress thunk toolhelp win32)
 @ stdcall CompareFileTime(ptr ptr) CompareFileTime
 @ stdcall CompareStringA(long long str long str long) CompareStringA
 @ stdcall CompareStringW(long long wstr long wstr long) CompareStringW
-@ stub ConnectNamedPipe
+@ stdcall ConnectNamedPipe(long ptr) ConnectNamedPipe
 @ stdcall ContinueDebugEvent(long long long) ContinueDebugEvent
 @ stdcall ConvertDefaultLocale (long) ConvertDefaultLocale
 @ stdcall ConvertToGlobalHandle(long) ConvertToGlobalHandle
@@ -231,7 +231,7 @@ debug_channels (comm debugstr dll int resource stress thunk toolhelp win32)
 @ stdcall DeleteFileW(wstr) DeleteFileW
 @ stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) DeviceIoControl
 @ stdcall DisableThreadLibraryCalls(long) DisableThreadLibraryCalls
-@ stub DisconnectNamedPipe
+@ stdcall DisconnectNamedPipe(long) DisconnectNamedPipe
 @ stdcall DosDateTimeToFileTime(long long ptr) DosDateTimeToFileTime
 @ stdcall DuplicateHandle(long long long ptr long long long) DuplicateHandle
 @ stub EndUpdateResourceA
diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c
index b19f6e54785..f4fb1857065 100644
--- a/dlls/kernel/sync.c
+++ b/dlls/kernel/sync.c
@@ -512,11 +512,35 @@ HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
                                 DWORD nOutBufferSize, DWORD nInBufferSize,
                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
 {
-    FIXME("(Name=%s, OpenMode=%#08lx, dwPipeMode=%#08lx, MaxInst=%ld, OutBSize=%ld, InBuffSize=%ld, DefTimeOut=%ld, SecAttr=%p): stub\n",
+    HANDLE ret;
+    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
+
+    TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p): stub\n",
           debugstr_a(name), dwOpenMode, dwPipeMode, nMaxInstances,
           nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
-    SetLastError (ERROR_UNKNOWN);
-    return INVALID_HANDLE_VALUE;
+
+    if (len >= MAX_PATH)
+    {
+        SetLastError( ERROR_FILENAME_EXCED_RANGE );
+        return 0;
+    }
+    SERVER_START_VAR_REQ( create_named_pipe, len * sizeof(WCHAR) )
+    {
+        req->openmode = dwOpenMode;
+        req->pipemode = dwPipeMode;
+        req->maxinstances = nMaxInstances;
+        req->outsize = nOutBufferSize;
+        req->insize = nInBufferSize;
+        req->timeout = nDefaultTimeOut;
+
+        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
+        SetLastError(0);
+        SERVER_CALL_ERR();
+        ret = req->handle;
+    }
+    SERVER_END_VAR_REQ;
+    TRACE("Returned %d\n",ret);
+    return ret;
 }
 
 
@@ -528,12 +552,34 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
                                 DWORD nOutBufferSize, DWORD nInBufferSize,
                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
 {
-    FIXME("(Name=%s, OpenMode=%#08lx, dwPipeMode=%#08lx, MaxInst=%ld, OutBSize=%ld, InBuffSize=%ld, DefTimeOut=%ld, SecAttr=%p): stub\n",
+    HANDLE ret;
+    DWORD len = name ? strlenW(name) : 0;
+
+    TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
           debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
           nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
 
-    SetLastError (ERROR_UNKNOWN);
-    return INVALID_HANDLE_VALUE;
+    if (len >= MAX_PATH)
+    {
+        SetLastError( ERROR_FILENAME_EXCED_RANGE );
+        return 0;
+    }
+    SERVER_START_VAR_REQ( create_named_pipe, len * sizeof(WCHAR) )
+    {
+        req->openmode = dwOpenMode;
+        req->pipemode = dwPipeMode;
+        req->maxinstances = nMaxInstances;
+        req->outsize = nOutBufferSize;
+        req->insize = nInBufferSize;
+        req->timeout = nDefaultTimeOut;
+
+        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
+        SetLastError(0);
+        SERVER_CALL_ERR();
+        ret = req->handle;
+    }
+    SERVER_END_VAR_REQ;
+    return ret;
 }
 
 
@@ -570,3 +616,56 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR lpNamedPipeName, DWORD nTimeOut)
     SetLastError(ERROR_PIPE_NOT_CONNECTED);
     return FALSE;
 }
+
+/***********************************************************************
+ *           ConnectNamedPipe   (KERNEL32.@)
+ */
+BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
+{
+    BOOL ret;
+    HANDLE event;
+
+    TRACE("(%d,%p):stub\n",hPipe, overlapped);
+
+    if(overlapped)
+    {
+        FIXME("overlapped operation not supported\n");
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return FALSE;
+    }
+
+    event = CreateEventA(NULL,0,0,NULL);
+    if(event==INVALID_HANDLE_VALUE)
+    {
+        ERR("create event failed!\n");
+        return FALSE;
+    }
+
+    SERVER_START_REQ( connect_named_pipe )
+    {
+        req->handle = hPipe;
+        req->event = event;
+        ret = SERVER_CALL_ERR();
+    }
+    SERVER_END_REQ;
+
+    if(ret) {
+        ERR("server returned status %08lx\n",GetLastError());
+        return FALSE;
+    }
+
+    WaitForSingleObject(event,INFINITE);
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *           DisconnectNamedPipe   (KERNEL32.@)
+ */
+BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
+{
+    FIXME("(%d):stub\n",hPipe);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
diff --git a/files/file.c b/files/file.c
index fecfce3a203..e976bf3a478 100644
--- a/files/file.c
+++ b/files/file.c
@@ -339,6 +339,31 @@ HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa
     return ret;
 }
 
+static HANDLE FILE_OpenPipe(LPCSTR name, DWORD access)
+{
+    HANDLE ret;
+    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
+
+    TRACE("name %s access %lx\n",name,access);
+
+    if (len >= MAX_PATH)
+    {
+        SetLastError( ERROR_FILENAME_EXCED_RANGE );
+        return 0;
+    }
+    SERVER_START_VAR_REQ( open_named_pipe, len * sizeof(WCHAR) )
+    {
+        req->access = access;
+
+        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
+        SetLastError(0);
+        SERVER_CALL_ERR();
+        ret = req->handle;
+    }
+    SERVER_END_VAR_REQ;
+    TRACE("Returned %d\n",ret);
+    return ret;
+}
 
 /*************************************************************************
  * CreateFileA [KERNEL32.@]  Creates or opens a file or other object
@@ -365,7 +390,7 @@ HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa
  *
  * BUGS
  *
- * Doesn't support character devices, pipes, template files, or a
+ * Doesn't support character devices, template files, or a
  * lot of the 'attributes' flags yet.
  */
 HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
@@ -406,7 +431,12 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
     }
 
     if (!strncmp(filename, "\\\\.\\", 4)) {
-        if (!DOSFS_GetDevice( filename ))
+        if(!strncasecmp(&filename[4],"pipe\\",5))
+        {
+            TRACE("Opening a pipe: %s\n",filename);
+            return FILE_OpenPipe(filename,access);
+        }
+        else if (!DOSFS_GetDevice( filename ))
         {
             ret = DEVICE_Open( filename+4, access, sa );
             goto done;
diff --git a/include/server.h b/include/server.h
index 6c2907e58b6..6882959cc52 100644
--- a/include/server.h
+++ b/include/server.h
@@ -1489,6 +1489,33 @@ struct create_async_request
 #define ASYNC_TYPE_WRITE 0x02
 #define ASYNC_TYPE_WAIT  0x03
 
+struct create_named_pipe_request
+{
+    REQUEST_HEADER;                 /* request header */
+    IN unsigned int     openmode;
+    IN unsigned int     pipemode;
+    IN unsigned int     maxinstances;
+    IN unsigned int     outsize;
+    IN unsigned int     insize;
+    IN unsigned int     timeout;
+    OUT handle_t        handle;     /* handle to the pipe */
+    IN  VARARG(filename,string);    /* pipe name */
+};
+
+struct open_named_pipe_request
+{
+    REQUEST_HEADER;                 /* request header */
+    IN unsigned int     access;
+    OUT handle_t        handle;     /* handle to the pipe */
+    IN  VARARG(filename,string);    /* pipe name */
+};
+
+struct connect_named_pipe_request
+{
+    REQUEST_HEADER;
+    IN handle_t         handle;
+    IN handle_t         event;      /* set this event when it's ready */
+};
 
 /* Everything below this line is generated automatically by tools/make_requests */
 /* ### make_requests begin ### */
@@ -1613,6 +1640,9 @@ enum request
     REQ_get_serial_info,
     REQ_set_serial_info,
     REQ_create_async,
+    REQ_create_named_pipe,
+    REQ_open_named_pipe,
+    REQ_connect_named_pipe,
     REQ_NB_REQUESTS
 };
 
@@ -1738,9 +1768,12 @@ union generic_request
     struct get_serial_info_request get_serial_info;
     struct set_serial_info_request set_serial_info;
     struct create_async_request create_async;
+    struct create_named_pipe_request create_named_pipe;
+    struct open_named_pipe_request open_named_pipe;
+    struct connect_named_pipe_request connect_named_pipe;
 };
 
-#define SERVER_PROTOCOL_VERSION 47
+#define SERVER_PROTOCOL_VERSION 48
 
 /* ### make_requests end ### */
 /* Everything above this line is generated automatically by tools/make_requests */
diff --git a/include/winbase.h b/include/winbase.h
index 67f0670ce1b..4b107e7748d 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -793,6 +793,20 @@ typedef struct
   int nFileIndexLow;
 } BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION ;
 
+#define PIPE_ACCESS_INBOUND  1
+#define PIPE_ACCESS_OUTBOUND 2
+#define PIPE_ACCESS_DUPLEX   3
+
+#define PIPE_TYPE_BYTE    0
+#define PIPE_TYPE_MESSAGE 4
+
+#define PIPE_READMODE_BYTE    0
+#define PIPE_READMODE_MESSAGE 2
+
+#define PIPE_WAIT   0
+#define PIPE_NOWAIT 1
+
+#define PIPE_UNLIMITED_INSTANCES 255
 
 typedef struct _SYSTEM_POWER_STATUS
 {
diff --git a/server/Makefile.in b/server/Makefile.in
index e0bb99ee082..bb82aa775fb 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -20,6 +20,7 @@ C_SRCS = \
 	main.c \
 	mapping.c \
 	mutex.c \
+	named_pipe.c \
 	object.c \
 	pipe.c \
 	process.c \
diff --git a/server/named_pipe.c b/server/named_pipe.c
new file mode 100644
index 00000000000..60777e7a383
--- /dev/null
+++ b/server/named_pipe.c
@@ -0,0 +1,299 @@
+/*
+ * Server-side pipe management
+ *
+ * Copyright (C) 1998 Alexandre Julliard
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "winbase.h"
+
+#include "handle.h"
+#include "thread.h"
+#include "request.h"
+
+struct named_pipe;
+
+struct pipe_user
+{
+    struct object       obj;
+    int                 other_fd;
+    struct named_pipe  *pipe;
+    struct pipe_user   *next;
+    struct pipe_user   *prev;
+    struct event       *event;
+};
+
+struct named_pipe
+{
+    struct object       obj;         /* object header */
+    unsigned int        pipemode;
+    unsigned int        maxinstances;
+    unsigned int        outsize;
+    unsigned int        insize;
+    unsigned int        timeout;
+    struct pipe_user   *users;
+};
+
+static void named_pipe_dump( struct object *obj, int verbose );
+static void named_pipe_destroy( struct object *obj);
+
+static const struct object_ops named_pipe_ops =
+{
+    sizeof(struct named_pipe),    /* size */
+    named_pipe_dump,              /* dump */
+    no_add_queue,                 /* add_queue */
+    NULL,                         /* remove_queue */
+    NULL,                         /* signaled */
+    NULL,                         /* satisfied */
+    NULL,                         /* get_poll_events */
+    NULL,                         /* poll_event */
+    no_get_fd,                    /* get_fd */
+    no_flush,                     /* flush */
+    no_get_file_info,             /* get_file_info */
+    named_pipe_destroy            /* destroy */
+};
+
+static void pipe_user_dump( struct object *obj, int verbose );
+static void pipe_user_destroy( struct object *obj);
+static int pipe_user_get_fd( struct object *obj );
+
+static const struct object_ops pipe_user_ops =
+{
+    sizeof(struct pipe_user),     /* size */
+    pipe_user_dump,               /* dump */
+    default_poll_add_queue,       /* add_queue */
+    default_poll_remove_queue,    /* remove_queue */
+    default_poll_signaled,        /* signaled */
+    no_satisfied,                 /* satisfied */
+    NULL,                         /* get_poll_events */
+    default_poll_event,           /* poll_event */
+    pipe_user_get_fd,             /* get_fd */
+    no_flush,                     /* flush */
+    no_get_file_info,             /* get_file_info */
+    pipe_user_destroy             /* destroy */
+};
+
+static void named_pipe_dump( struct object *obj, int verbose )
+{
+    struct named_pipe *pipe = (struct named_pipe *)obj;
+    assert( obj->ops == &named_pipe_ops );
+    fprintf( stderr, "named pipe %p\n" ,pipe);
+}
+
+static void pipe_user_dump( struct object *obj, int verbose )
+{
+    struct pipe_user *user = (struct pipe_user *)obj;
+    assert( obj->ops == &pipe_user_ops );
+    fprintf( stderr, "named pipe user %p (%s)\n", user,
+             (user->other_fd != -1) ? "server" : "client" );
+}
+
+static void named_pipe_destroy( struct object *obj)
+{
+    struct named_pipe *pipe = (struct named_pipe *)obj;
+    assert( !pipe->users );
+}
+
+static void pipe_user_destroy( struct object *obj)
+{
+    struct pipe_user *user = (struct pipe_user *)obj;
+
+    assert( obj->ops == &pipe_user_ops );
+
+    if(user->event)
+    {
+        /* FIXME: signal waiter of failure */
+        release_object(user->event);
+        user->event = NULL;
+    }
+
+    /* remove user from pipe's user list */
+    if (user->next) user->next->prev = user->prev;
+    if (user->prev) user->prev->next = user->next;
+    else user->pipe->users = user->next;
+    release_object(user->pipe);
+}
+
+static int pipe_user_get_fd( struct object *obj )
+{
+    struct pipe_user *user = (struct pipe_user *)obj;
+    assert( obj->ops == &pipe_user_ops );
+    return user->obj.fd;
+}
+
+static struct named_pipe *create_named_pipe( const WCHAR *name, size_t len )
+{
+    struct named_pipe *pipe;
+
+    if ((pipe = create_named_object( &named_pipe_ops, name, len )))
+    {
+        if (get_error() != STATUS_OBJECT_NAME_COLLISION)
+        {
+            /* initialize it if it didn't already exist */
+            pipe->users = 0;
+        }
+    }
+    return pipe;
+}
+
+static struct pipe_user *get_pipe_user_obj( struct process *process, handle_t handle,
+                                            unsigned int access )
+{
+    return (struct pipe_user *)get_handle_obj( process, handle, access, &pipe_user_ops );
+}
+
+static struct pipe_user *create_pipe_user( struct named_pipe *pipe, int fd )
+{
+    struct pipe_user *user;
+    int fds[2];
+
+    if(fd == -1)
+    {
+        /* FIXME: what about messages? */
+
+        if(0>socketpair(PF_UNIX, SOCK_STREAM, 0, fds)) goto error;
+    }
+    else
+    {
+        if ((fds[0] = dup(fd)) == -1) goto error;
+        fds[1] = -1;
+    }
+    user = alloc_object( &pipe_user_ops, fds[0] );
+    if(!user)
+    {
+        if (fds[1] != -1) close( fds[1] );
+        return NULL;
+    }
+
+    user->pipe = pipe;
+    user->other_fd = fds[1];
+    user->event = NULL;   /* thread wait on this pipe */
+
+    /* add to list of pipe users */
+    if ((user->next = pipe->users)) user->next->prev = user;
+    user->prev = NULL;
+    pipe->users = user;
+
+    grab_object(pipe);
+
+    return user;
+
+ error:
+    file_set_error();
+    return NULL;
+}
+
+static struct pipe_user *find_partner(struct named_pipe *pipe)
+{
+    struct pipe_user *x;
+
+    for(x = pipe->users; x; x=x->next)
+    {
+        /* only pair threads that are waiting */
+        if(!x->event)
+            continue;
+
+        /* only pair with pipes that haven't been connected */
+        if(x->other_fd == -1)
+            continue;
+
+        break;
+    }
+
+    return (struct pipe_user *)grab_object( x );
+}
+
+DECL_HANDLER(create_named_pipe)
+{
+    struct named_pipe *pipe;
+    struct pipe_user *user;
+
+    req->handle = 0;
+    pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
+    if(!pipe)
+        return;
+
+    user = create_pipe_user (pipe, -1);
+
+    if(user)
+    {
+        req->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
+        release_object( user );
+    }
+
+    release_object( pipe );
+}
+
+DECL_HANDLER(open_named_pipe)
+{
+    struct named_pipe *pipe;
+    struct pipe_user *user,*partner;
+
+    req->handle = 0;
+    pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
+    if(!pipe)
+        return;
+
+    if (get_error() == STATUS_OBJECT_NAME_COLLISION)
+    {
+        if ((partner = find_partner(pipe)))
+        {
+            user = create_pipe_user (pipe, partner->other_fd);
+            if(user)
+            {
+                set_event(partner->event);
+                release_object(partner->event);
+                partner->event = NULL;
+                close( partner->other_fd );
+                partner->other_fd = -1;
+                req->handle = alloc_handle( current->process, user, req->access, 0 );
+                release_object(user);
+            }
+            release_object( partner );
+        }
+        else {
+            set_error(STATUS_NO_SUCH_FILE);
+        }
+    }
+    else {
+        set_error(STATUS_NO_SUCH_FILE);
+    }
+
+    release_object(pipe);
+}
+
+DECL_HANDLER(connect_named_pipe)
+{
+    struct pipe_user *user;
+    struct event *event;
+
+    user = get_pipe_user_obj(current->process, req->handle, 0);
+    if(!user)
+        return;
+
+    if( user->event || user->other_fd == -1)
+    {
+        /* fprintf(stderr,"fd = %x  event = %p\n",user->obj.fd,user->event);*/
+        set_error(STATUS_PORT_ALREADY_SET);
+    }
+    else
+    {
+        event = get_event_obj(current->process, req->event, 0);
+        if(event)
+            user->event = event;
+    }
+
+    release_object(user);
+}
diff --git a/server/request.h b/server/request.h
index 6a5bc406f53..8afa8dae577 100644
--- a/server/request.h
+++ b/server/request.h
@@ -186,6 +186,9 @@ DECL_HANDLER(create_serial);
 DECL_HANDLER(get_serial_info);
 DECL_HANDLER(set_serial_info);
 DECL_HANDLER(create_async);
+DECL_HANDLER(create_named_pipe);
+DECL_HANDLER(open_named_pipe);
+DECL_HANDLER(connect_named_pipe);
 
 #ifdef WANT_REQUEST_HANDLERS
 
@@ -310,6 +313,9 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_get_serial_info,
     (req_handler)req_set_serial_info,
     (req_handler)req_create_async,
+    (req_handler)req_create_named_pipe,
+    (req_handler)req_open_named_pipe,
+    (req_handler)req_connect_named_pipe,
 };
 #endif  /* WANT_REQUEST_HANDLERS */
 
diff --git a/server/trace.c b/server/trace.c
index 250ffd93fe7..438121c4fd6 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1593,6 +1593,41 @@ static void dump_create_async_reply( const struct create_async_request *req )
     fprintf( stderr, " timeout=%d", req->timeout );
 }
 
+static void dump_create_named_pipe_request( const struct create_named_pipe_request *req )
+{
+    fprintf( stderr, " openmode=%08x,", req->openmode );
+    fprintf( stderr, " pipemode=%08x,", req->pipemode );
+    fprintf( stderr, " maxinstances=%08x,", req->maxinstances );
+    fprintf( stderr, " outsize=%08x,", req->outsize );
+    fprintf( stderr, " insize=%08x,", req->insize );
+    fprintf( stderr, " timeout=%08x,", req->timeout );
+    fprintf( stderr, " filename=" );
+    cur_pos += dump_varargs_string( req );
+}
+
+static void dump_create_named_pipe_reply( const struct create_named_pipe_request *req )
+{
+    fprintf( stderr, " handle=%d", req->handle );
+}
+
+static void dump_open_named_pipe_request( const struct open_named_pipe_request *req )
+{
+    fprintf( stderr, " access=%08x,", req->access );
+    fprintf( stderr, " filename=" );
+    cur_pos += dump_varargs_string( req );
+}
+
+static void dump_open_named_pipe_reply( const struct open_named_pipe_request *req )
+{
+    fprintf( stderr, " handle=%d", req->handle );
+}
+
+static void dump_connect_named_pipe_request( const struct connect_named_pipe_request *req )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " event=%d", req->event );
+}
+
 static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_new_process_request,
     (dump_func)dump_get_new_process_info_request,
@@ -1712,6 +1747,9 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_get_serial_info_request,
     (dump_func)dump_set_serial_info_request,
     (dump_func)dump_create_async_request,
+    (dump_func)dump_create_named_pipe_request,
+    (dump_func)dump_open_named_pipe_request,
+    (dump_func)dump_connect_named_pipe_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -1833,6 +1871,9 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_get_serial_info_reply,
     (dump_func)0,
     (dump_func)dump_create_async_reply,
+    (dump_func)dump_create_named_pipe_reply,
+    (dump_func)dump_open_named_pipe_reply,
+    (dump_func)0,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -1954,6 +1995,9 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "get_serial_info",
     "set_serial_info",
     "create_async",
+    "create_named_pipe",
+    "open_named_pipe",
+    "connect_named_pipe",
 };
 
 /* ### make_requests end ### */
-- 
GitLab