- moved named pipe creation to ntdll
- server now handles the named pipe flags as the NTDLL values (not the KERNEL32 ones) - named pipes in server now use the async IO mechanism for connect/wait ops
This commit is contained in:
parent
267f85b0ac
commit
5a2591d96d
|
@ -41,6 +41,9 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
|
||||
#include "ntstatus.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -1051,15 +1054,20 @@ HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
|
|||
HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
|
||||
DWORD dwPipeMode, DWORD nMaxInstances,
|
||||
DWORD nOutBufferSize, DWORD nInBufferSize,
|
||||
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
|
||||
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES sa )
|
||||
{
|
||||
HANDLE ret;
|
||||
HANDLE handle;
|
||||
UNICODE_STRING nt_name;
|
||||
static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
DWORD options;
|
||||
BOOLEAN pipe_type, read_mode, non_block;
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
LARGE_INTEGER timeout;
|
||||
|
||||
TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
|
||||
debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
|
||||
nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
|
||||
nOutBufferSize, nInBufferSize, nDefaultTimeOut, sa );
|
||||
|
||||
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
|
||||
{
|
||||
|
@ -1072,30 +1080,42 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
|
|||
RtlFreeUnicodeString( &nt_name );
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (nt_name.Length < sizeof(leadin) ||
|
||||
strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
|
||||
{
|
||||
SetLastError( ERROR_INVALID_NAME );
|
||||
RtlFreeUnicodeString( &nt_name );
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
SERVER_START_REQ( create_named_pipe )
|
||||
{
|
||||
req->openmode = dwOpenMode;
|
||||
req->pipemode = dwPipeMode;
|
||||
req->maxinstances = nMaxInstances;
|
||||
req->outsize = nOutBufferSize;
|
||||
req->insize = nInBufferSize;
|
||||
req->timeout = nDefaultTimeOut;
|
||||
req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
|
||||
wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &nt_name;
|
||||
attr.Attributes = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
|
||||
attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
options = 0;
|
||||
if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) options |= FILE_WRITE_THROUGH;
|
||||
if (!(dwOpenMode & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_ALERT;
|
||||
if ((dwOpenMode & PIPE_ACCESS_DUPLEX) == PIPE_ACCESS_DUPLEX)
|
||||
options |= FILE_PIPE_FULL_DUPLEX;
|
||||
else if (dwOpenMode & PIPE_ACCESS_INBOUND) options |= FILE_PIPE_INBOUND;
|
||||
else if (dwOpenMode & PIPE_ACCESS_OUTBOUND) options |= FILE_PIPE_OUTBOUND;
|
||||
pipe_type = (dwPipeMode & PIPE_TYPE_MESSAGE) ? TRUE : FALSE;
|
||||
read_mode = (dwPipeMode & PIPE_READMODE_MESSAGE) ? TRUE : FALSE;
|
||||
non_block = (dwPipeMode & PIPE_NOWAIT) ? TRUE : FALSE;
|
||||
if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES) nMaxInstances = ULONG_MAX;
|
||||
|
||||
timeout.QuadPart = (ULONGLONG)nDefaultTimeOut * -10000;
|
||||
|
||||
SetLastError(0);
|
||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
||||
else ret = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
status = NtCreateNamedPipeFile(&handle, 0, &attr, &iosb, 0, FILE_OVERWRITE_IF,
|
||||
options, pipe_type, read_mode, non_block,
|
||||
nMaxInstances, nInBufferSize, nOutBufferSize,
|
||||
&timeout);
|
||||
|
||||
RtlFreeUnicodeString( &nt_name );
|
||||
return ret;
|
||||
if (status)
|
||||
{
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
SetLastError( RtlNtStatusToDosError(status) );
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1177,17 +1197,21 @@ BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SYNC_CompletePipeOverlapped (Internal)
|
||||
* PIPE_CompletionWait (Internal)
|
||||
*/
|
||||
static void CALLBACK SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
|
||||
static void CALLBACK PIPE_CompletionWait(void *user, PIO_STATUS_BLOCK iosb, ULONG status)
|
||||
{
|
||||
TRACE("for %p result %08lx\n",overlapped,result);
|
||||
if(!overlapped)
|
||||
return;
|
||||
overlapped->Internal = result;
|
||||
SetEvent(overlapped->hEvent);
|
||||
}
|
||||
LPOVERLAPPED ovlp = (LPOVERLAPPED)user;
|
||||
|
||||
TRACE("for %p/%p, status=%08lx\n", ovlp, iosb, status);
|
||||
|
||||
if (ovlp)
|
||||
{
|
||||
ovlp->Internal = status;
|
||||
SetEvent(ovlp->hEvent);
|
||||
}
|
||||
TRACE("done\n");
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WaitNamedPipeA (KERNEL32.@)
|
||||
|
@ -1243,7 +1267,7 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
|
|||
{
|
||||
req->timeout = nTimeOut;
|
||||
req->overlapped = &ov;
|
||||
req->func = SYNC_CompletePipeOverlapped;
|
||||
req->func = PIPE_CompletionWait;
|
||||
wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
|
@ -1264,63 +1288,50 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* 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 = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ConnectNamedPipe (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
|
||||
{
|
||||
OVERLAPPED ov;
|
||||
BOOL ret;
|
||||
LPOVERLAPPED pov;
|
||||
OVERLAPPED ov;
|
||||
|
||||
TRACE("(%p,%p)\n",hPipe, overlapped);
|
||||
TRACE("(%p,%p)\n", hPipe, overlapped);
|
||||
|
||||
if(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;
|
||||
|
||||
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;
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if (overlapped)
|
||||
{
|
||||
if(SYNC_ConnectNamedPipe(hPipe,overlapped))
|
||||
SetLastError( ERROR_IO_PENDING );
|
||||
return FALSE;
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
memset(&ov,0,sizeof(ov));
|
||||
ov.hEvent = CreateEventW(NULL,0,0,NULL);
|
||||
if (!ov.hEvent)
|
||||
return FALSE;
|
||||
|
||||
ret=SYNC_ConnectNamedPipe(hPipe, &ov);
|
||||
if(ret)
|
||||
else
|
||||
{
|
||||
if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
|
||||
{
|
||||
SetLastError(RtlNtStatusToDosError(ov.Internal));
|
||||
ret = (ov.Internal==STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
ret = GetOverlappedResult(hPipe, &ov, NULL, TRUE);
|
||||
CloseHandle(ov.hEvent);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1391,10 +1402,19 @@ BOOL WINAPI GetNamedPipeInfo(
|
|||
{
|
||||
req->handle = hNamedPipe;
|
||||
ret = !wine_server_call_err( req );
|
||||
if(lpFlags) *lpFlags = reply->flags;
|
||||
if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
|
||||
if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
|
||||
if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
|
||||
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;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
|
|
@ -1735,19 +1735,49 @@ NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
|
|||
*
|
||||
*
|
||||
*/
|
||||
NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE FileHandle, ULONG DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock,
|
||||
ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions,
|
||||
ULONG NamedPipeType, ULONG ReadMode, ULONG CompletionMode,
|
||||
ULONG MaximumInstances, ULONG InboundQuota, ULONG OutboundQuota,
|
||||
PLARGE_INTEGER DefaultTimeout)
|
||||
NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
|
||||
POBJECT_ATTRIBUTES oa, PIO_STATUS_BLOCK iosb,
|
||||
ULONG sharing, ULONG dispo, ULONG options,
|
||||
ULONG pipe_type, ULONG read_mode,
|
||||
ULONG completion_mode, ULONG max_inst,
|
||||
ULONG inbound_quota, ULONG outbound_quota,
|
||||
PLARGE_INTEGER timeout)
|
||||
{
|
||||
FIXME("(%p %lx %p %p %lx %ld %lx %ld %ld %ld %ld %ld %ld %p): stub\n",
|
||||
FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock,
|
||||
ShareAccess, CreateDisposition, CreateOptions, NamedPipeType,
|
||||
ReadMode, CompletionMode, MaximumInstances, InboundQuota,
|
||||
OutboundQuota, DefaultTimeout);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS status;
|
||||
static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
|
||||
|
||||
TRACE("(%p %lx %p %p %lx %ld %lx %ld %ld %ld %ld %ld %ld %p): stub\n",
|
||||
handle, access, oa, iosb, sharing, dispo, options, pipe_type,
|
||||
read_mode, completion_mode, max_inst, inbound_quota, outbound_quota,
|
||||
timeout);
|
||||
|
||||
if (oa->ObjectName->Length < sizeof(leadin) ||
|
||||
strncmpiW( oa->ObjectName->Buffer,
|
||||
leadin, sizeof(leadin)/sizeof(leadin[0]) ))
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
/* assume we only get relative timeout, and storable in a DWORD as ms */
|
||||
if (timeout->QuadPart > 0 || (timeout->QuadPart / -10000) >> 32)
|
||||
FIXME("Wrong time %s\n", wine_dbgstr_longlong(timeout->QuadPart));
|
||||
|
||||
SERVER_START_REQ( create_named_pipe )
|
||||
{
|
||||
req->options = options; /* FIXME not used in server yet !!!! */
|
||||
req->flags =
|
||||
(pipe_type) ? NAMED_PIPE_MESSAGE_STREAM_WRITE : 0 |
|
||||
(read_mode) ? NAMED_PIPE_MESSAGE_STREAM_READ : 0 |
|
||||
(completion_mode) ? NAMED_PIPE_NONBLOCKING_MODE : 0;
|
||||
req->maxinstances = max_inst;
|
||||
req->outsize = outbound_quota;
|
||||
req->insize = inbound_quota;
|
||||
req->timeout = timeout->QuadPart / -10000;
|
||||
req->inherit = (oa->Attributes & OBJ_INHERIT) != 0;
|
||||
wine_server_add_data( req, oa->ObjectName->Buffer + 4,
|
||||
oa->ObjectName->Length - 4 * sizeof(WCHAR) );
|
||||
status = wine_server_call( req );
|
||||
if (!status) *handle = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
|
@ -2328,8 +2328,8 @@ struct cancel_async_reply
|
|||
struct create_named_pipe_request
|
||||
{
|
||||
struct request_header __header;
|
||||
unsigned int openmode;
|
||||
unsigned int pipemode;
|
||||
unsigned int options;
|
||||
unsigned int flags;
|
||||
unsigned int maxinstances;
|
||||
unsigned int outsize;
|
||||
unsigned int insize;
|
||||
|
@ -2344,6 +2344,11 @@ struct create_named_pipe_reply
|
|||
};
|
||||
|
||||
|
||||
#define NAMED_PIPE_MESSAGE_STREAM_WRITE 0x0001
|
||||
#define NAMED_PIPE_MESSAGE_STREAM_READ 0x0002
|
||||
#define NAMED_PIPE_NONBLOCKING_MODE 0x0004
|
||||
|
||||
|
||||
|
||||
struct open_named_pipe_request
|
||||
{
|
||||
|
@ -3877,6 +3882,6 @@ union generic_reply
|
|||
struct set_mailslot_info_reply set_mailslot_info_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 166
|
||||
#define SERVER_PROTOCOL_VERSION 167
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -1295,6 +1295,11 @@ typedef struct _RTL_HANDLE_TABLE
|
|||
#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
|
||||
#define FILE_DEVICE_SECURE_OPEN 0x00000100
|
||||
|
||||
/* options for NtCreateNamedPipeFile */
|
||||
#define FILE_PIPE_INBOUND 0x00000000
|
||||
#define FILE_PIPE_OUTBOUND 0x00000001
|
||||
#define FILE_PIPE_FULL_DUPLEX 0x00000002
|
||||
|
||||
#if (_WIN32_WINNT >= 0x0501)
|
||||
#define INTERNAL_TS_ACTIVE_CONSOLE_ID ( *((volatile ULONG*)(0x7ffe02d8)) )
|
||||
#endif /* (_WIN32_WINNT >= 0x0501) */
|
||||
|
|
|
@ -60,13 +60,6 @@ enum pipe_state
|
|||
ps_wait_connect
|
||||
};
|
||||
|
||||
struct wait_info
|
||||
{
|
||||
struct thread *thread;
|
||||
void *func;
|
||||
void *overlapped;
|
||||
};
|
||||
|
||||
struct named_pipe;
|
||||
|
||||
struct pipe_server
|
||||
|
@ -79,7 +72,7 @@ struct pipe_server
|
|||
struct named_pipe *pipe;
|
||||
struct timeout_user *flush_poll;
|
||||
struct event *event;
|
||||
struct wait_info wait;
|
||||
struct list wait_q; /* only a single one can be queued */
|
||||
};
|
||||
|
||||
struct pipe_client
|
||||
|
@ -87,20 +80,12 @@ struct pipe_client
|
|||
struct object obj; /* object header */
|
||||
struct fd *fd; /* pipe file descriptor */
|
||||
struct pipe_server *server; /* server that this client is connected to */
|
||||
struct wait_info wait;
|
||||
};
|
||||
|
||||
struct connect_wait
|
||||
{
|
||||
struct list entry; /* entry in named pipe wait list */
|
||||
struct wait_info wait;
|
||||
struct timeout_user *timeout_user;
|
||||
};
|
||||
|
||||
struct named_pipe
|
||||
{
|
||||
struct object obj; /* object header */
|
||||
unsigned int pipemode;
|
||||
unsigned int flags;
|
||||
unsigned int maxinstances;
|
||||
unsigned int outsize;
|
||||
unsigned int insize;
|
||||
|
@ -208,83 +193,13 @@ static void pipe_client_dump( struct object *obj, int verbose )
|
|||
fprintf( stderr, "Named pipe client server=%p\n", client->server );
|
||||
}
|
||||
|
||||
static void notify_waiter( struct wait_info *wait, unsigned int status )
|
||||
{
|
||||
if( wait->thread && wait->func && wait->overlapped )
|
||||
{
|
||||
/* queue a system APC, to notify a waiting thread */
|
||||
thread_queue_apc( wait->thread, NULL, wait->func, APC_ASYNC,
|
||||
1, wait->overlapped, (void *)status, NULL );
|
||||
}
|
||||
if( wait->thread ) release_object( wait->thread );
|
||||
wait->thread = NULL;
|
||||
}
|
||||
|
||||
static void set_waiter( struct wait_info *wait, void *func, void *ov )
|
||||
{
|
||||
wait->thread = (struct thread *) grab_object( current );
|
||||
wait->func = func;
|
||||
wait->overlapped = ov;
|
||||
}
|
||||
|
||||
static void notify_connect_waiter( struct connect_wait *waiter, unsigned int status )
|
||||
{
|
||||
notify_waiter( &waiter->wait, status );
|
||||
list_remove( &waiter->entry );
|
||||
free( waiter );
|
||||
}
|
||||
|
||||
static void notify_all_connect_waiters( struct named_pipe *pipe, unsigned int status )
|
||||
{
|
||||
struct list *ptr;
|
||||
|
||||
while ((ptr = list_head( &pipe->waiters )) != NULL)
|
||||
{
|
||||
struct connect_wait *waiter = LIST_ENTRY( ptr, struct connect_wait, entry );
|
||||
if (waiter->timeout_user) remove_timeout_user( waiter->timeout_user );
|
||||
notify_connect_waiter( waiter, status );
|
||||
}
|
||||
}
|
||||
|
||||
/* pipe connect wait timeout */
|
||||
static void connect_timeout( void *ptr )
|
||||
{
|
||||
struct connect_wait *waiter = (struct connect_wait *)ptr;
|
||||
notify_connect_waiter( waiter, STATUS_TIMEOUT );
|
||||
}
|
||||
|
||||
static void named_pipe_destroy( struct object *obj)
|
||||
{
|
||||
struct named_pipe *pipe = (struct named_pipe *) obj;
|
||||
|
||||
assert( list_empty( &pipe->servers ) );
|
||||
assert( !pipe->instances );
|
||||
notify_all_connect_waiters( pipe, STATUS_HANDLES_CLOSED );
|
||||
}
|
||||
|
||||
static void queue_connect_waiter( struct named_pipe *pipe, void *func,
|
||||
void *overlapped, unsigned int *timeout )
|
||||
{
|
||||
struct connect_wait *waiter;
|
||||
|
||||
waiter = mem_alloc( sizeof(*waiter) );
|
||||
if( waiter )
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
set_waiter( &waiter->wait, func, overlapped );
|
||||
list_add_tail( &pipe->waiters, &waiter->entry );
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
gettimeofday( &tv, 0 );
|
||||
add_timeout( &tv, *timeout );
|
||||
waiter->timeout_user = add_timeout_user( &tv, connect_timeout,
|
||||
waiter );
|
||||
}
|
||||
else
|
||||
waiter->timeout_user = NULL;
|
||||
}
|
||||
async_terminate_queue( &pipe->waiters, STATUS_HANDLES_CLOSED );
|
||||
}
|
||||
|
||||
static struct fd *pipe_client_get_fd( struct object *obj )
|
||||
|
@ -367,7 +282,7 @@ static void pipe_server_destroy( struct object *obj)
|
|||
server->client = NULL;
|
||||
}
|
||||
|
||||
notify_waiter( &server->wait, STATUS_HANDLES_CLOSED );
|
||||
async_terminate_head( &server->wait_q, STATUS_HANDLES_CLOSED );
|
||||
|
||||
assert( server->pipe->instances );
|
||||
server->pipe->instances--;
|
||||
|
@ -383,8 +298,6 @@ static void pipe_client_destroy( struct object *obj)
|
|||
|
||||
assert( obj->ops == &pipe_client_ops );
|
||||
|
||||
notify_waiter( &client->wait, STATUS_HANDLES_CLOSED );
|
||||
|
||||
if( server )
|
||||
{
|
||||
notify_empty( server );
|
||||
|
@ -560,7 +473,7 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe )
|
|||
server->state = ps_idle_server;
|
||||
server->client = NULL;
|
||||
server->flush_poll = NULL;
|
||||
server->wait.thread = NULL;
|
||||
list_init( &server->wait_q );
|
||||
|
||||
list_add_head( &pipe->servers, &server->entry );
|
||||
grab_object( pipe );
|
||||
|
@ -578,7 +491,6 @@ static struct pipe_client *create_pipe_client( struct pipe_server *server )
|
|||
|
||||
client->fd = NULL;
|
||||
client->server = server;
|
||||
client->wait.thread = NULL;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
@ -623,7 +535,7 @@ DECL_HANDLER(create_named_pipe)
|
|||
pipe->outsize = req->outsize;
|
||||
pipe->maxinstances = req->maxinstances;
|
||||
pipe->timeout = req->timeout;
|
||||
pipe->pipemode = req->pipemode;
|
||||
pipe->flags = req->flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -636,7 +548,7 @@ DECL_HANDLER(create_named_pipe)
|
|||
}
|
||||
if( ( pipe->maxinstances != req->maxinstances ) ||
|
||||
( pipe->timeout != req->timeout ) ||
|
||||
( pipe->pipemode != req->pipemode ) )
|
||||
( pipe->flags != req->flags ) )
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
release_object( pipe );
|
||||
|
@ -693,8 +605,8 @@ DECL_HANDLER(open_named_pipe)
|
|||
if (client->fd && server->fd)
|
||||
{
|
||||
if( server->state == ps_wait_open )
|
||||
notify_waiter( &server->wait, STATUS_SUCCESS );
|
||||
assert( !server->wait.thread );
|
||||
async_terminate_head( &server->wait_q, STATUS_SUCCESS );
|
||||
assert( list_empty( &server->wait_q ) );
|
||||
server->state = ps_connected_server;
|
||||
server->client = client;
|
||||
client->server = server;
|
||||
|
@ -724,8 +636,9 @@ DECL_HANDLER(connect_named_pipe)
|
|||
case ps_wait_connect:
|
||||
assert( !server->fd );
|
||||
server->state = ps_wait_open;
|
||||
set_waiter( &server->wait, req->func, req->overlapped );
|
||||
notify_all_connect_waiters( server->pipe, STATUS_SUCCESS );
|
||||
create_async( current, NULL, &server->wait_q,
|
||||
req->func, req->overlapped, NULL );
|
||||
async_terminate_queue( &server->pipe->waiters, STATUS_SUCCESS );
|
||||
break;
|
||||
case ps_connected_server:
|
||||
assert( server->fd );
|
||||
|
@ -759,9 +672,8 @@ DECL_HANDLER(wait_named_pipe)
|
|||
if( server )
|
||||
{
|
||||
/* there's already a server waiting for a client to connect */
|
||||
struct wait_info wait;
|
||||
set_waiter( &wait, req->func, req->overlapped );
|
||||
notify_waiter( &wait, STATUS_SUCCESS );
|
||||
thread_queue_apc( current, NULL, req->func, APC_ASYNC_IO,
|
||||
1, req->overlapped, NULL, (void *)STATUS_SUCCESS );
|
||||
release_object( server );
|
||||
}
|
||||
else
|
||||
|
@ -773,9 +685,11 @@ DECL_HANDLER(wait_named_pipe)
|
|||
timeout = req->timeout;
|
||||
|
||||
if (req->timeout == NMPWAIT_WAIT_FOREVER)
|
||||
queue_connect_waiter( pipe, req->func, req->overlapped, NULL );
|
||||
create_async( current, NULL, &pipe->waiters,
|
||||
req->func, req->overlapped, NULL );
|
||||
else
|
||||
queue_connect_waiter( pipe, req->func, req->overlapped, &timeout );
|
||||
create_async( current, &timeout, &pipe->waiters,
|
||||
req->func, req->overlapped, NULL );
|
||||
}
|
||||
|
||||
release_object( pipe );
|
||||
|
@ -797,7 +711,6 @@ DECL_HANDLER(disconnect_named_pipe)
|
|||
assert( server->client->fd );
|
||||
|
||||
notify_empty( server );
|
||||
notify_waiter( &server->client->wait, STATUS_PIPE_DISCONNECTED );
|
||||
|
||||
/* Dump the client and server fds, but keep the pointers
|
||||
around - client loses all waiting data */
|
||||
|
@ -832,7 +745,7 @@ DECL_HANDLER(get_named_pipe_info)
|
|||
if(!server)
|
||||
return;
|
||||
|
||||
reply->flags = server->pipe->pipemode;
|
||||
reply->flags = server->pipe->flags;
|
||||
reply->maxinstances = server->pipe->maxinstances;
|
||||
reply->insize = server->pipe->insize;
|
||||
reply->outsize = server->pipe->outsize;
|
||||
|
|
|
@ -1647,8 +1647,8 @@ enum message_type
|
|||
|
||||
/* Create a named pipe */
|
||||
@REQ(create_named_pipe)
|
||||
unsigned int openmode;
|
||||
unsigned int pipemode;
|
||||
unsigned int options;
|
||||
unsigned int flags;
|
||||
unsigned int maxinstances;
|
||||
unsigned int outsize;
|
||||
unsigned int insize;
|
||||
|
@ -1659,6 +1659,11 @@ enum message_type
|
|||
obj_handle_t handle; /* handle to the pipe */
|
||||
@END
|
||||
|
||||
/* flags in create_named_pipe and get_named_pipe_info */
|
||||
#define NAMED_PIPE_MESSAGE_STREAM_WRITE 0x0001
|
||||
#define NAMED_PIPE_MESSAGE_STREAM_READ 0x0002
|
||||
#define NAMED_PIPE_NONBLOCKING_MODE 0x0004
|
||||
|
||||
|
||||
/* Open an existing named pipe */
|
||||
@REQ(open_named_pipe)
|
||||
|
|
|
@ -1986,8 +1986,8 @@ static void dump_cancel_async_request( const struct cancel_async_request *req )
|
|||
|
||||
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, " options=%08x,", req->options );
|
||||
fprintf( stderr, " flags=%08x,", req->flags );
|
||||
fprintf( stderr, " maxinstances=%08x,", req->maxinstances );
|
||||
fprintf( stderr, " outsize=%08x,", req->outsize );
|
||||
fprintf( stderr, " insize=%08x,", req->insize );
|
||||
|
|
Loading…
Reference in New Issue