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 );
}