Make ConnectNamedPipe work in overlapped mode.

diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c
index 833b781..5fe788a 100644
--- a/dlls/kernel/sync.c
+++ b/dlls/kernel/sync.c
@@ -601,38 +601,72 @@
     return FALSE;
 }
 
+/***********************************************************************
+ *           SYNC_CompletePipeOverlapped   (Internal)
+ */
+static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
+{
+    TRACE("for %p result %08lx\n",overlapped,result);
+    if(!overlapped)
+        return;
+    overlapped->Internal = result;
+    SetEvent(overlapped->hEvent);
+}
 
 /***********************************************************************
  *           WaitNamedPipeA   (KERNEL32.@)
  */
-BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
+static BOOL SYNC_WaitNamedPipeA (LPCSTR name, DWORD nTimeOut, LPOVERLAPPED overlapped)
 {
     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    HANDLE event;
     BOOL ret;
 
-    TRACE("%s 0x%08lx\n",debugstr_a(name),nTimeOut);
-
     if (len >= MAX_PATH)
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return FALSE;
     }
 
-    if (!(event = CreateEventA( NULL, 0, 0, NULL ))) return FALSE;
-
     SERVER_START_VAR_REQ( wait_named_pipe, len * sizeof(WCHAR) )
     {
         req->timeout = nTimeOut;
-        req->event = event;
+        req->overlapped = overlapped;
+        req->func = SYNC_CompletePipeOverlapped;
         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
         ret = !SERVER_CALL_ERR();
     }
     SERVER_END_REQ;
 
-    if (ret) WaitForSingleObject(event,INFINITE);
+    return ret;
+}
 
-    CloseHandle(event);
+/***********************************************************************
+ *           WaitNamedPipeA   (KERNEL32.@)
+ */
+BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
+{
+    BOOL ret;
+    OVERLAPPED ov;
+
+    TRACE("%s 0x%08lx\n",debugstr_a(name),nTimeOut);
+
+    memset(&ov,0,sizeof ov);
+    ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
+    if (!ov.hEvent)
+        return FALSE;
+
+    /* expect to fail with STATUS_PENDING */
+    ret = SYNC_WaitNamedPipeA(name, nTimeOut, &ov);
+    if(ret)
+    {
+        if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
+        {
+            SetLastError(ov.Internal);
+            ret = (ov.Internal==STATUS_SUCCESS);
+        }
+    }
+
+    CloseHandle(ov.hEvent);
     return ret;
 }
 
@@ -640,68 +674,115 @@
 /***********************************************************************
  *           WaitNamedPipeW   (KERNEL32.@)
  */
-BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
+static BOOL SYNC_WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut, LPOVERLAPPED overlapped)
 {
     DWORD len = name ? strlenW(name) : 0;
-    HANDLE event;
     BOOL ret;
 
-    TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
-
     if (len >= MAX_PATH)
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return FALSE;
     }
 
-    if (!(event = CreateEventA( NULL, 0, 0, NULL ))) return FALSE;
-
     SERVER_START_VAR_REQ( wait_named_pipe, len * sizeof(WCHAR) )
     {
         req->timeout = nTimeOut;
-        req->event = event;
+        req->overlapped = overlapped;
+        req->func = SYNC_CompletePipeOverlapped;
         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
         ret = !SERVER_CALL_ERR();
     }
     SERVER_END_REQ;
 
-    if (ret) WaitForSingleObject(event,INFINITE);
-
-    CloseHandle(event);
     return ret;
 }
 
+/***********************************************************************
+ *           WaitNamedPipeW   (KERNEL32.@)
+ */
+BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
+{
+    BOOL ret;
+    OVERLAPPED ov;
+
+    TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
+
+    memset(&ov,0,sizeof ov);
+    ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
+    if (!ov.hEvent)
+        return FALSE;
+
+    ret = SYNC_WaitNamedPipeW(name, nTimeOut, &ov);
+    if(ret)
+    {
+        if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
+        {
+            SetLastError(ov.Internal);
+            ret = (ov.Internal==STATUS_SUCCESS);
+        }
+    }
+
+    CloseHandle(ov.hEvent);
+
+    return ret;
+}
+
+
+/***********************************************************************
+ *           SYNC_ConnectNamedPipe   (Internal)
+ */
+static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
+{
+    BOOL ret;
+
+    if(!overlapped)
+        return FALSE;
+
+    overlapped->Internal = STATUS_PENDING;
+
+    SERVER_START_REQ( connect_named_pipe )
+    {
+        req->handle = hPipe;
+        req->overlapped = overlapped;
+        req->func = SYNC_CompletePipeOverlapped;
+        ret = !SERVER_CALL_ERR();
+    }
+    SERVER_END_REQ;
+
+    return ret;
+}
 
 /***********************************************************************
  *           ConnectNamedPipe   (KERNEL32.@)
  */
 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
 {
+    OVERLAPPED ov;
     BOOL ret;
-    HANDLE event;
 
     TRACE("(%d,%p)\n",hPipe, overlapped);
 
     if(overlapped)
-    {
-        FIXME("overlapped operation not supported\n");
-        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return SYNC_ConnectNamedPipe(hPipe,overlapped);
+
+    memset(&ov,0,sizeof ov);
+    ov.hEvent = CreateEventA(NULL,0,0,NULL);
+    if (!ov.hEvent)
         return FALSE;
-    }
 
-    if (!(event = CreateEventA(NULL,0,0,NULL))) return FALSE;
-
-    SERVER_START_REQ( connect_named_pipe )
+    ret=SYNC_ConnectNamedPipe(hPipe, &ov);
+    if(ret)
     {
-        req->handle = hPipe;
-        req->event = event;
-        ret = !SERVER_CALL_ERR();
+        if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
+        {
+            SetLastError(ov.Internal);
+            ret = (ov.Internal==STATUS_SUCCESS);
+        }
     }
-    SERVER_END_REQ;
 
-    if (ret) WaitForSingleObject(event,INFINITE);
+    CloseHandle(ov.hEvent);
 
-    CloseHandle(event);
     return ret;
 }
 
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index fe437e9..41dba2e 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1552,7 +1552,8 @@
 {
     struct request_header __header;
     handle_t       handle;
-    handle_t       event;
+    void*          overlapped;
+    void*          func;
 };
 
 
@@ -1561,7 +1562,8 @@
 {
     struct request_header __header;
     unsigned int   timeout;
-    handle_t       event;
+    void*          overlapped;
+    void*          func;
     /* VARARG(filename,string); */
 };
 
@@ -2056,6 +2058,6 @@
     struct get_window_properties_request get_window_properties;
 };
 
-#define SERVER_PROTOCOL_VERSION 62
+#define SERVER_PROTOCOL_VERSION 63
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/scheduler/synchro.c b/scheduler/synchro.c
index 77907a4..5bb83ff 100644
--- a/scheduler/synchro.c
+++ b/scheduler/synchro.c
@@ -243,6 +243,7 @@
         case APC_NONE:
             return;  /* no more APCs */
         case APC_ASYNC:
+            proc( args[0], args[1]);
             break;
         case APC_USER:
             proc( args[0] );
diff --git a/server/named_pipe.c b/server/named_pipe.c
index edc92e8..57013d9 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -48,7 +48,9 @@
     struct named_pipe  *pipe;
     struct pipe_user   *next;
     struct pipe_user   *prev;
-    struct event       *event;
+    void               *thread;
+    void               *func;
+    void               *overlapped;
 };
 
 struct named_pipe
@@ -122,18 +124,28 @@
     assert( !pipe->users );
 }
 
+static void notify_waiter( struct pipe_user *user, unsigned int status)
+{
+    if(user->thread && user->func && user->overlapped)
+    {
+        /* queue a system APC, to notify a waiting thread */
+        thread_queue_apc(user->thread,NULL,user->func,
+            APC_ASYNC,1,2,user->overlapped,status);
+    }
+    user->thread = NULL;
+    user->func = NULL;
+    user->overlapped=NULL;
+}
+
 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;
-    }
+    if(user->overlapped)
+        notify_waiter(user,STATUS_HANDLES_CLOSED);
+
     if(user->other)
     {
         close(user->other->obj.fd);
@@ -217,8 +229,10 @@
 
     user->pipe = pipe;
     user->state = ps_none;
-    user->event = NULL;   /* thread wait on this pipe */
     user->other = NULL;
+    user->thread = NULL;
+    user->func = NULL;
+    user->overlapped = NULL;
 
     /* add to list of pipe users */
     if ((user->next = pipe->users)) user->next->prev = user;
@@ -301,9 +315,7 @@
                 if( (user = create_pipe_user (pipe, fds[1])) )
                 {
                     partner->obj.fd = fds[0];
-                    set_event(partner->event);
-                    release_object(partner->event);
-                    partner->event = NULL;
+                    notify_waiter(partner,STATUS_SUCCESS);
                     partner->state = ps_connected_server;
                     partner->other = user;
                     user->state = ps_connected_client;
@@ -334,7 +346,6 @@
 DECL_HANDLER(connect_named_pipe)
 {
     struct pipe_user *user, *partner;
-    struct event *event;
 
     user = get_pipe_user_obj(current->process, req->handle, 0);
     if(!user)
@@ -347,16 +358,14 @@
     else
     {
         user->state = ps_wait_open;
-        event = get_event_obj(current->process, req->event, 0);
-        if(event)
-            user->event = event;
+        user->thread = current;
+        user->func = req->func;
+        user->overlapped = req->overlapped;
 
         /* notify all waiters that a pipe just became available */
         while( (partner = find_partner(user->pipe,ps_wait_connect)) )
         {
-            set_event(partner->event);
-            release_object(partner->event);
-            partner->event = NULL;
+            notify_waiter(partner,STATUS_SUCCESS);
             release_object(partner);
             release_object(partner);
         }
@@ -367,13 +376,8 @@
 
 DECL_HANDLER(wait_named_pipe)
 {
-    struct event *event;
     struct named_pipe *pipe;
 
-    event = get_event_obj(current->process, req->event, 0);
-    if(!event)
-        return;
-
     pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
     if( pipe )
     {
@@ -385,7 +389,10 @@
             set_error(STATUS_SUCCESS);
             if( (partner = find_partner(pipe,ps_wait_open)) )
             {
-                set_event(event);
+                /* this should use notify_waiter, 
+                   but no pipe_user object exists now... */
+                thread_queue_apc(current,NULL,req->func,
+                    APC_ASYNC,1,2,req->overlapped,STATUS_SUCCESS);
                 release_object(partner);
             }
             else
@@ -394,8 +401,10 @@
 
                 if( (user = create_pipe_user (pipe, -1)) )
                 {
-                    user->event = (struct event *)grab_object( event );
                     user->state = ps_wait_connect;
+                    user->thread = current;
+                    user->func = req->func;
+                    user->overlapped = req->overlapped;
                     /* don't release it */
                 }
             }
@@ -406,7 +415,6 @@
         }
         release_object(pipe);
     }
-    release_object(event);
 }
 
 DECL_HANDLER(disconnect_named_pipe)
diff --git a/server/protocol.def b/server/protocol.def
index 07c7f79..5e6c8a0 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1392,14 +1392,16 @@
 /* Connect to a named pipe */
 @REQ(connect_named_pipe)
     handle_t       handle;
-    handle_t       event;      /* set this event when it's ready */
+    void*          overlapped;
+    void*          func;
 @END
 
 
 /* Wait for a named pipe */
 @REQ(wait_named_pipe)
     unsigned int   timeout;
-    handle_t       event;       /* set this event when it's ready */
+    void*          overlapped;
+    void*          func;
     VARARG(filename,string);    /* pipe name */
 @END
 
diff --git a/server/trace.c b/server/trace.c
index ba98c0a..012286b 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1661,13 +1661,15 @@
 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 );
+    fprintf( stderr, " overlapped=%p,", req->overlapped );
+    fprintf( stderr, " func=%p", req->func );
 }
 
 static void dump_wait_named_pipe_request( const struct wait_named_pipe_request *req )
 {
     fprintf( stderr, " timeout=%08x,", req->timeout );
-    fprintf( stderr, " event=%d,", req->event );
+    fprintf( stderr, " overlapped=%p,", req->overlapped );
+    fprintf( stderr, " func=%p,", req->func );
     fprintf( stderr, " filename=" );
     cur_pos += dump_varargs_string( req );
 }