Added FSCTL_PIPE_LISTEN support.

diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c
index fe785ec..9a37727 100644
--- a/dlls/kernel/sync.c
+++ b/dlls/kernel/sync.c
@@ -1310,50 +1310,34 @@
 
 /***********************************************************************
  *           ConnectNamedPipe   (KERNEL32.@)
+ *
+ *  Connects to a named pipe
+ *
+ *  Parameters
+ *  hPipe: A handle to a named pipe returned by CreateNamedPipe
+ *  overlapped: Optional OVERLAPPED struct
+ *
+ *  Return values
+ *  TRUE: Success
+ *  FALSE: Failure, GetLastError can be called for further details
  */
 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
 {
-    BOOL                ret;
-    LPOVERLAPPED        pov;
-    OVERLAPPED          ov;
+    NTSTATUS status;
+    IO_STATUS_BLOCK status_block;
 
     TRACE("(%p,%p)\n", hPipe, overlapped);
 
-    if (!overlapped)
-    {
-        memset(&ov, 0, sizeof(ov));
-        ov.hEvent = CreateEventW(NULL, 0, 0, NULL);
-        if (!ov.hEvent) return FALSE;
-        pov = &ov;
-    }
-    else pov = overlapped;
-        
-    pov->Internal = STATUS_PENDING;
+    if(overlapped)
+        overlapped->Internal = STATUS_PENDING;
 
-    SERVER_START_REQ( connect_named_pipe )
-    {
-        req->handle = hPipe;
-        req->overlapped = pov;
-        req->func = PIPE_CompletionWait;
-        ret = !wine_server_call_err( req );
-    }
-    SERVER_END_REQ;
+    status = NtFsControlFile(hPipe, overlapped ? overlapped->hEvent : NULL, NULL, NULL,
+                             overlapped ? (IO_STATUS_BLOCK *)overlapped : &status_block,
+                             FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
 
-    if (ret)
-    {
-        if (overlapped)
-        {
-            SetLastError( ERROR_IO_PENDING );
-            ret = FALSE;
-        }
-        else
-        {
-            ret = GetOverlappedResult(hPipe, &ov, NULL, TRUE);
-            CloseHandle(ov.hEvent);
-        }
-    }
-
-    return ret;
+    if (status == STATUS_SUCCESS) return TRUE;
+    SetLastError( RtlNtStatusToDosError(status) );
+    return FALSE;
 }
 
 /***********************************************************************
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 2e4d042..cfd2c21 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -862,24 +862,90 @@
     return IoStatusBlock->u.Status;
 }
 
-/******************************************************************************
- * NtFsControlFile [NTDLL.@]
- * ZwFsControlFile [NTDLL.@]
+/***********************************************************************
+ *           pipe_completion_wait   (Internal)
+ */
+static void CALLBACK pipe_completion_wait(HANDLE event, PIO_STATUS_BLOCK iosb, ULONG status)
+{
+    TRACE("for %p/%p, status=%08lx\n", event, iosb, status);
+
+    if (iosb)
+        iosb->u.Status = status;
+    NtSetEvent(event, NULL);
+    TRACE("done\n");
+}
+
+/**************************************************************************
+ *              NtFsControlFile                 [NTDLL.@]
+ *              ZwFsControlFile                 [NTDLL.@]
+ *
+ * Perform a file system control operation on an open file handle.
+ *
+ * PARAMS
+ *  DeviceHandle     [I] Handle returned from ZwOpenFile() or ZwCreateFile()
+ *  Event            [I] Event to signal upon completion (or NULL)
+ *  ApcRoutine       [I] Callback to call upon completion (or NULL)
+ *  ApcContext       [I] Context for ApcRoutine (or NULL)
+ *  IoStatusBlock    [O] Receives information about the operation on return
+ *  FsControlCode    [I] Control code for the operation to perform
+ *  InputBuffer      [I] Source for any input data required (or NULL)
+ *  InputBufferSize  [I] Size of InputBuffer
+ *  OutputBuffer     [O] Source for any output data returned (or NULL)
+ *  OutputBufferSize [I] Size of OutputBuffer
+ *
+ * RETURNS
+ *  Success: 0. IoStatusBlock is updated.
+ *  Failure: An NTSTATUS error code describing the error.
  */
 NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_APC_ROUTINE ApcRoutine,
-                                PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode,
+                                PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode,
                                 PVOID InputBuffer, ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize)
 {
     NTSTATUS ret;
 
     TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n",
-    DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode,
+    DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FsControlCode,
     InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize);
 
     if(!IoStatusBlock) return STATUS_INVALID_PARAMETER;
 
-    switch(IoControlCode)
+    switch(FsControlCode)
     {
+        case FSCTL_PIPE_LISTEN :
+        {
+            HANDLE internal_event;
+
+            if(!Event)
+            {
+                OBJECT_ATTRIBUTES obj;
+                InitializeObjectAttributes(&obj, NULL, 0, 0, NULL);
+                ret = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, &obj, FALSE, FALSE);
+                if(ret != STATUS_SUCCESS) return ret;
+            }
+
+            SERVER_START_REQ(connect_named_pipe)
+            {
+                req->handle = DeviceHandle;
+                req->event = Event ? Event : internal_event;
+                req->func = pipe_completion_wait;
+                ret = wine_server_call(req);
+            }
+            SERVER_END_REQ;
+
+            if(ret == STATUS_SUCCESS)
+            {
+                if(Event)
+                    ret = STATUS_PENDING;
+                else
+                {
+                    do
+                        ret = NtWaitForSingleObject(internal_event, TRUE, NULL);
+                    while(ret == STATUS_USER_APC);
+                    NtClose(internal_event);
+                }
+            }
+            break;
+        }
         case FSCTL_PIPE_DISCONNECT :
             SERVER_START_REQ(disconnect_named_pipe)
             {
@@ -888,11 +954,14 @@
                 if (!ret && reply->fd != -1) close(reply->fd);
             }
             SERVER_END_REQ;
-            return ret;
+            break;
         default :
-            FIXME("Unsupported IoControlCode %lx\n", IoControlCode);
-            return STATUS_NOT_SUPPORTED;
+            FIXME("Unsupported FsControlCode %lx\n", FsControlCode);
+            ret = STATUS_NOT_SUPPORTED;
+            break;
     }
+    IoStatusBlock->u.Status = ret;
+    return ret;
 }
 
 /******************************************************************************
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index e18d682..2f1ada88 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -2408,7 +2408,7 @@
 {
     struct request_header __header;
     obj_handle_t   handle;
-    void*          overlapped;
+    obj_handle_t   event;
     void*          func;
 };
 struct connect_named_pipe_reply
@@ -4206,6 +4206,6 @@
     struct set_mailslot_info_reply set_mailslot_info_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 191
+#define SERVER_PROTOCOL_VERSION 192
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index b22dfb1..55a8ee0 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -671,7 +671,7 @@
         assert( !server->fd );
         server->state = ps_wait_open;
         create_async( current, NULL, &server->wait_q,
-                      req->func, req->overlapped, NULL );
+                      req->func, req->event, NULL );
         async_terminate_queue( &server->pipe->waiters, STATUS_SUCCESS );
         break;
     case ps_connected_server:
diff --git a/server/protocol.def b/server/protocol.def
index 422aa00..9e93f53 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1712,7 +1712,7 @@
 /* Connect to a named pipe */
 @REQ(connect_named_pipe)
     obj_handle_t   handle;
-    void*          overlapped;
+    obj_handle_t   event;
     void*          func;
 @END
 
diff --git a/server/trace.c b/server/trace.c
index 538732f..2c00f2e 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2173,7 +2173,7 @@
 static void dump_connect_named_pipe_request( const struct connect_named_pipe_request *req )
 {
     fprintf( stderr, " handle=%p,", req->handle );
-    fprintf( stderr, " overlapped=%p,", req->overlapped );
+    fprintf( stderr, " event=%p,", req->event );
     fprintf( stderr, " func=%p", req->func );
 }