- 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 <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
|
#define NONAMELESSSTRUCT
|
||||||
|
|
||||||
#include "ntstatus.h"
|
#include "ntstatus.h"
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
@ -1051,15 +1054,20 @@ HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
|
||||||
HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
|
HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
|
||||||
DWORD dwPipeMode, DWORD nMaxInstances,
|
DWORD dwPipeMode, DWORD nMaxInstances,
|
||||||
DWORD nOutBufferSize, DWORD nInBufferSize,
|
DWORD nOutBufferSize, DWORD nInBufferSize,
|
||||||
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
|
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES sa )
|
||||||
{
|
{
|
||||||
HANDLE ret;
|
HANDLE handle;
|
||||||
UNICODE_STRING nt_name;
|
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",
|
TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
|
||||||
debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
|
debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
|
||||||
nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
|
nOutBufferSize, nInBufferSize, nDefaultTimeOut, sa );
|
||||||
|
|
||||||
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
|
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
|
||||||
{
|
{
|
||||||
|
@ -1072,30 +1080,42 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
|
||||||
RtlFreeUnicodeString( &nt_name );
|
RtlFreeUnicodeString( &nt_name );
|
||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
if (nt_name.Length < sizeof(leadin) ||
|
|
||||||
strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
|
attr.Length = sizeof(attr);
|
||||||
{
|
attr.RootDirectory = 0;
|
||||||
SetLastError( ERROR_INVALID_NAME );
|
attr.ObjectName = &nt_name;
|
||||||
RtlFreeUnicodeString( &nt_name );
|
attr.Attributes = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
|
||||||
return INVALID_HANDLE_VALUE;
|
attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
|
||||||
}
|
attr.SecurityQualityOfService = NULL;
|
||||||
SERVER_START_REQ( create_named_pipe )
|
|
||||||
{
|
options = 0;
|
||||||
req->openmode = dwOpenMode;
|
if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) options |= FILE_WRITE_THROUGH;
|
||||||
req->pipemode = dwPipeMode;
|
if (!(dwOpenMode & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_ALERT;
|
||||||
req->maxinstances = nMaxInstances;
|
if ((dwOpenMode & PIPE_ACCESS_DUPLEX) == PIPE_ACCESS_DUPLEX)
|
||||||
req->outsize = nOutBufferSize;
|
options |= FILE_PIPE_FULL_DUPLEX;
|
||||||
req->insize = nInBufferSize;
|
else if (dwOpenMode & PIPE_ACCESS_INBOUND) options |= FILE_PIPE_INBOUND;
|
||||||
req->timeout = nDefaultTimeOut;
|
else if (dwOpenMode & PIPE_ACCESS_OUTBOUND) options |= FILE_PIPE_OUTBOUND;
|
||||||
req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
|
pipe_type = (dwPipeMode & PIPE_TYPE_MESSAGE) ? TRUE : FALSE;
|
||||||
wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
|
read_mode = (dwPipeMode & PIPE_READMODE_MESSAGE) ? TRUE : FALSE;
|
||||||
SetLastError(0);
|
non_block = (dwPipeMode & PIPE_NOWAIT) ? TRUE : FALSE;
|
||||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES) nMaxInstances = ULONG_MAX;
|
||||||
else ret = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
timeout.QuadPart = (ULONGLONG)nDefaultTimeOut * -10000;
|
||||||
SERVER_END_REQ;
|
|
||||||
|
SetLastError(0);
|
||||||
|
|
||||||
|
status = NtCreateNamedPipeFile(&handle, 0, &attr, &iosb, 0, FILE_OVERWRITE_IF,
|
||||||
|
options, pipe_type, read_mode, non_block,
|
||||||
|
nMaxInstances, nInBufferSize, nOutBufferSize,
|
||||||
|
&timeout);
|
||||||
|
|
||||||
RtlFreeUnicodeString( &nt_name );
|
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);
|
LPOVERLAPPED ovlp = (LPOVERLAPPED)user;
|
||||||
if(!overlapped)
|
|
||||||
return;
|
|
||||||
overlapped->Internal = result;
|
|
||||||
SetEvent(overlapped->hEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
TRACE("for %p/%p, status=%08lx\n", ovlp, iosb, status);
|
||||||
|
|
||||||
|
if (ovlp)
|
||||||
|
{
|
||||||
|
ovlp->Internal = status;
|
||||||
|
SetEvent(ovlp->hEvent);
|
||||||
|
}
|
||||||
|
TRACE("done\n");
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* WaitNamedPipeA (KERNEL32.@)
|
* WaitNamedPipeA (KERNEL32.@)
|
||||||
|
@ -1243,7 +1267,7 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
|
||||||
{
|
{
|
||||||
req->timeout = nTimeOut;
|
req->timeout = nTimeOut;
|
||||||
req->overlapped = &ov;
|
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) );
|
wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
|
||||||
ret = !wine_server_call_err( req );
|
ret = !wine_server_call_err( req );
|
||||||
}
|
}
|
||||||
|
@ -1264,64 +1288,51 @@ 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.@)
|
* ConnectNamedPipe (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
|
BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
|
||||||
{
|
{
|
||||||
OVERLAPPED ov;
|
BOOL ret;
|
||||||
BOOL ret;
|
LPOVERLAPPED pov;
|
||||||
|
OVERLAPPED ov;
|
||||||
|
|
||||||
TRACE("(%p,%p)\n",hPipe, overlapped);
|
TRACE("(%p,%p)\n", hPipe, overlapped);
|
||||||
|
|
||||||
if(overlapped)
|
if (!overlapped)
|
||||||
{
|
{
|
||||||
if(SYNC_ConnectNamedPipe(hPipe,overlapped))
|
memset(&ov, 0, sizeof(ov));
|
||||||
SetLastError( ERROR_IO_PENDING );
|
ov.hEvent = CreateEventW(NULL, 0, 0, NULL);
|
||||||
return FALSE;
|
if (!ov.hEvent) return FALSE;
|
||||||
|
pov = &ov;
|
||||||
}
|
}
|
||||||
|
else pov = overlapped;
|
||||||
|
|
||||||
|
pov->Internal = STATUS_PENDING;
|
||||||
|
|
||||||
memset(&ov,0,sizeof(ov));
|
SERVER_START_REQ( connect_named_pipe )
|
||||||
ov.hEvent = CreateEventW(NULL,0,0,NULL);
|
|
||||||
if (!ov.hEvent)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
ret=SYNC_ConnectNamedPipe(hPipe, &ov);
|
|
||||||
if(ret)
|
|
||||||
{
|
{
|
||||||
if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
|
req->handle = hPipe;
|
||||||
|
req->overlapped = pov;
|
||||||
|
req->func = PIPE_CompletionWait;
|
||||||
|
ret = !wine_server_call_err( req );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
if (overlapped)
|
||||||
{
|
{
|
||||||
SetLastError(RtlNtStatusToDosError(ov.Internal));
|
SetLastError( ERROR_IO_PENDING );
|
||||||
ret = (ov.Internal==STATUS_SUCCESS);
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = GetOverlappedResult(hPipe, &ov, NULL, TRUE);
|
||||||
|
CloseHandle(ov.hEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(ov.hEvent);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1391,10 +1402,19 @@ BOOL WINAPI GetNamedPipeInfo(
|
||||||
{
|
{
|
||||||
req->handle = hNamedPipe;
|
req->handle = hNamedPipe;
|
||||||
ret = !wine_server_call_err( req );
|
ret = !wine_server_call_err( req );
|
||||||
if(lpFlags) *lpFlags = reply->flags;
|
if (lpFlags)
|
||||||
if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
|
{
|
||||||
if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
|
*lpFlags = 0;
|
||||||
if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
|
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;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
|
|
@ -1735,19 +1735,49 @@ NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE FileHandle, ULONG DesiredAccess,
|
NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock,
|
POBJECT_ATTRIBUTES oa, PIO_STATUS_BLOCK iosb,
|
||||||
ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions,
|
ULONG sharing, ULONG dispo, ULONG options,
|
||||||
ULONG NamedPipeType, ULONG ReadMode, ULONG CompletionMode,
|
ULONG pipe_type, ULONG read_mode,
|
||||||
ULONG MaximumInstances, ULONG InboundQuota, ULONG OutboundQuota,
|
ULONG completion_mode, ULONG max_inst,
|
||||||
PLARGE_INTEGER DefaultTimeout)
|
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",
|
NTSTATUS status;
|
||||||
FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock,
|
static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
|
||||||
ShareAccess, CreateDisposition, CreateOptions, NamedPipeType,
|
|
||||||
ReadMode, CompletionMode, MaximumInstances, InboundQuota,
|
TRACE("(%p %lx %p %p %lx %ld %lx %ld %ld %ld %ld %ld %ld %p): stub\n",
|
||||||
OutboundQuota, DefaultTimeout);
|
handle, access, oa, iosb, sharing, dispo, options, pipe_type,
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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 create_named_pipe_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
unsigned int openmode;
|
unsigned int options;
|
||||||
unsigned int pipemode;
|
unsigned int flags;
|
||||||
unsigned int maxinstances;
|
unsigned int maxinstances;
|
||||||
unsigned int outsize;
|
unsigned int outsize;
|
||||||
unsigned int insize;
|
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
|
struct open_named_pipe_request
|
||||||
{
|
{
|
||||||
|
@ -3877,6 +3882,6 @@ union generic_reply
|
||||||
struct set_mailslot_info_reply set_mailslot_info_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 */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -1295,6 +1295,11 @@ typedef struct _RTL_HANDLE_TABLE
|
||||||
#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
|
#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
|
||||||
#define FILE_DEVICE_SECURE_OPEN 0x00000100
|
#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)
|
#if (_WIN32_WINNT >= 0x0501)
|
||||||
#define INTERNAL_TS_ACTIVE_CONSOLE_ID ( *((volatile ULONG*)(0x7ffe02d8)) )
|
#define INTERNAL_TS_ACTIVE_CONSOLE_ID ( *((volatile ULONG*)(0x7ffe02d8)) )
|
||||||
#endif /* (_WIN32_WINNT >= 0x0501) */
|
#endif /* (_WIN32_WINNT >= 0x0501) */
|
||||||
|
|
|
@ -60,13 +60,6 @@ enum pipe_state
|
||||||
ps_wait_connect
|
ps_wait_connect
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wait_info
|
|
||||||
{
|
|
||||||
struct thread *thread;
|
|
||||||
void *func;
|
|
||||||
void *overlapped;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct named_pipe;
|
struct named_pipe;
|
||||||
|
|
||||||
struct pipe_server
|
struct pipe_server
|
||||||
|
@ -79,7 +72,7 @@ struct pipe_server
|
||||||
struct named_pipe *pipe;
|
struct named_pipe *pipe;
|
||||||
struct timeout_user *flush_poll;
|
struct timeout_user *flush_poll;
|
||||||
struct event *event;
|
struct event *event;
|
||||||
struct wait_info wait;
|
struct list wait_q; /* only a single one can be queued */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pipe_client
|
struct pipe_client
|
||||||
|
@ -87,20 +80,12 @@ struct pipe_client
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
struct fd *fd; /* pipe file descriptor */
|
struct fd *fd; /* pipe file descriptor */
|
||||||
struct pipe_server *server; /* server that this client is connected to */
|
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 named_pipe
|
||||||
{
|
{
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
unsigned int pipemode;
|
unsigned int flags;
|
||||||
unsigned int maxinstances;
|
unsigned int maxinstances;
|
||||||
unsigned int outsize;
|
unsigned int outsize;
|
||||||
unsigned int insize;
|
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 );
|
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)
|
static void named_pipe_destroy( struct object *obj)
|
||||||
{
|
{
|
||||||
struct named_pipe *pipe = (struct named_pipe *) obj;
|
struct named_pipe *pipe = (struct named_pipe *) obj;
|
||||||
|
|
||||||
assert( list_empty( &pipe->servers ) );
|
assert( list_empty( &pipe->servers ) );
|
||||||
assert( !pipe->instances );
|
assert( !pipe->instances );
|
||||||
notify_all_connect_waiters( pipe, STATUS_HANDLES_CLOSED );
|
async_terminate_queue( &pipe->waiters, 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fd *pipe_client_get_fd( struct object *obj )
|
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;
|
server->client = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
notify_waiter( &server->wait, STATUS_HANDLES_CLOSED );
|
async_terminate_head( &server->wait_q, STATUS_HANDLES_CLOSED );
|
||||||
|
|
||||||
assert( server->pipe->instances );
|
assert( server->pipe->instances );
|
||||||
server->pipe->instances--;
|
server->pipe->instances--;
|
||||||
|
@ -383,8 +298,6 @@ static void pipe_client_destroy( struct object *obj)
|
||||||
|
|
||||||
assert( obj->ops == &pipe_client_ops );
|
assert( obj->ops == &pipe_client_ops );
|
||||||
|
|
||||||
notify_waiter( &client->wait, STATUS_HANDLES_CLOSED );
|
|
||||||
|
|
||||||
if( server )
|
if( server )
|
||||||
{
|
{
|
||||||
notify_empty( 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->state = ps_idle_server;
|
||||||
server->client = NULL;
|
server->client = NULL;
|
||||||
server->flush_poll = NULL;
|
server->flush_poll = NULL;
|
||||||
server->wait.thread = NULL;
|
list_init( &server->wait_q );
|
||||||
|
|
||||||
list_add_head( &pipe->servers, &server->entry );
|
list_add_head( &pipe->servers, &server->entry );
|
||||||
grab_object( pipe );
|
grab_object( pipe );
|
||||||
|
@ -578,7 +491,6 @@ static struct pipe_client *create_pipe_client( struct pipe_server *server )
|
||||||
|
|
||||||
client->fd = NULL;
|
client->fd = NULL;
|
||||||
client->server = server;
|
client->server = server;
|
||||||
client->wait.thread = NULL;
|
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +535,7 @@ DECL_HANDLER(create_named_pipe)
|
||||||
pipe->outsize = req->outsize;
|
pipe->outsize = req->outsize;
|
||||||
pipe->maxinstances = req->maxinstances;
|
pipe->maxinstances = req->maxinstances;
|
||||||
pipe->timeout = req->timeout;
|
pipe->timeout = req->timeout;
|
||||||
pipe->pipemode = req->pipemode;
|
pipe->flags = req->flags;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -636,7 +548,7 @@ DECL_HANDLER(create_named_pipe)
|
||||||
}
|
}
|
||||||
if( ( pipe->maxinstances != req->maxinstances ) ||
|
if( ( pipe->maxinstances != req->maxinstances ) ||
|
||||||
( pipe->timeout != req->timeout ) ||
|
( pipe->timeout != req->timeout ) ||
|
||||||
( pipe->pipemode != req->pipemode ) )
|
( pipe->flags != req->flags ) )
|
||||||
{
|
{
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
release_object( pipe );
|
release_object( pipe );
|
||||||
|
@ -693,8 +605,8 @@ DECL_HANDLER(open_named_pipe)
|
||||||
if (client->fd && server->fd)
|
if (client->fd && server->fd)
|
||||||
{
|
{
|
||||||
if( server->state == ps_wait_open )
|
if( server->state == ps_wait_open )
|
||||||
notify_waiter( &server->wait, STATUS_SUCCESS );
|
async_terminate_head( &server->wait_q, STATUS_SUCCESS );
|
||||||
assert( !server->wait.thread );
|
assert( list_empty( &server->wait_q ) );
|
||||||
server->state = ps_connected_server;
|
server->state = ps_connected_server;
|
||||||
server->client = client;
|
server->client = client;
|
||||||
client->server = server;
|
client->server = server;
|
||||||
|
@ -724,8 +636,9 @@ DECL_HANDLER(connect_named_pipe)
|
||||||
case ps_wait_connect:
|
case ps_wait_connect:
|
||||||
assert( !server->fd );
|
assert( !server->fd );
|
||||||
server->state = ps_wait_open;
|
server->state = ps_wait_open;
|
||||||
set_waiter( &server->wait, req->func, req->overlapped );
|
create_async( current, NULL, &server->wait_q,
|
||||||
notify_all_connect_waiters( server->pipe, STATUS_SUCCESS );
|
req->func, req->overlapped, NULL );
|
||||||
|
async_terminate_queue( &server->pipe->waiters, STATUS_SUCCESS );
|
||||||
break;
|
break;
|
||||||
case ps_connected_server:
|
case ps_connected_server:
|
||||||
assert( server->fd );
|
assert( server->fd );
|
||||||
|
@ -759,9 +672,8 @@ DECL_HANDLER(wait_named_pipe)
|
||||||
if( server )
|
if( server )
|
||||||
{
|
{
|
||||||
/* there's already a server waiting for a client to connect */
|
/* there's already a server waiting for a client to connect */
|
||||||
struct wait_info wait;
|
thread_queue_apc( current, NULL, req->func, APC_ASYNC_IO,
|
||||||
set_waiter( &wait, req->func, req->overlapped );
|
1, req->overlapped, NULL, (void *)STATUS_SUCCESS );
|
||||||
notify_waiter( &wait, STATUS_SUCCESS );
|
|
||||||
release_object( server );
|
release_object( server );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -773,9 +685,11 @@ DECL_HANDLER(wait_named_pipe)
|
||||||
timeout = req->timeout;
|
timeout = req->timeout;
|
||||||
|
|
||||||
if (req->timeout == NMPWAIT_WAIT_FOREVER)
|
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
|
else
|
||||||
queue_connect_waiter( pipe, req->func, req->overlapped, &timeout );
|
create_async( current, &timeout, &pipe->waiters,
|
||||||
|
req->func, req->overlapped, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
release_object( pipe );
|
release_object( pipe );
|
||||||
|
@ -797,7 +711,6 @@ DECL_HANDLER(disconnect_named_pipe)
|
||||||
assert( server->client->fd );
|
assert( server->client->fd );
|
||||||
|
|
||||||
notify_empty( server );
|
notify_empty( server );
|
||||||
notify_waiter( &server->client->wait, STATUS_PIPE_DISCONNECTED );
|
|
||||||
|
|
||||||
/* Dump the client and server fds, but keep the pointers
|
/* Dump the client and server fds, but keep the pointers
|
||||||
around - client loses all waiting data */
|
around - client loses all waiting data */
|
||||||
|
@ -832,7 +745,7 @@ DECL_HANDLER(get_named_pipe_info)
|
||||||
if(!server)
|
if(!server)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
reply->flags = server->pipe->pipemode;
|
reply->flags = server->pipe->flags;
|
||||||
reply->maxinstances = server->pipe->maxinstances;
|
reply->maxinstances = server->pipe->maxinstances;
|
||||||
reply->insize = server->pipe->insize;
|
reply->insize = server->pipe->insize;
|
||||||
reply->outsize = server->pipe->outsize;
|
reply->outsize = server->pipe->outsize;
|
||||||
|
|
|
@ -1647,8 +1647,8 @@ enum message_type
|
||||||
|
|
||||||
/* Create a named pipe */
|
/* Create a named pipe */
|
||||||
@REQ(create_named_pipe)
|
@REQ(create_named_pipe)
|
||||||
unsigned int openmode;
|
unsigned int options;
|
||||||
unsigned int pipemode;
|
unsigned int flags;
|
||||||
unsigned int maxinstances;
|
unsigned int maxinstances;
|
||||||
unsigned int outsize;
|
unsigned int outsize;
|
||||||
unsigned int insize;
|
unsigned int insize;
|
||||||
|
@ -1659,6 +1659,11 @@ enum message_type
|
||||||
obj_handle_t handle; /* handle to the pipe */
|
obj_handle_t handle; /* handle to the pipe */
|
||||||
@END
|
@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 */
|
/* Open an existing named pipe */
|
||||||
@REQ(open_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 )
|
static void dump_create_named_pipe_request( const struct create_named_pipe_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " openmode=%08x,", req->openmode );
|
fprintf( stderr, " options=%08x,", req->options );
|
||||||
fprintf( stderr, " pipemode=%08x,", req->pipemode );
|
fprintf( stderr, " flags=%08x,", req->flags );
|
||||||
fprintf( stderr, " maxinstances=%08x,", req->maxinstances );
|
fprintf( stderr, " maxinstances=%08x,", req->maxinstances );
|
||||||
fprintf( stderr, " outsize=%08x,", req->outsize );
|
fprintf( stderr, " outsize=%08x,", req->outsize );
|
||||||
fprintf( stderr, " insize=%08x,", req->insize );
|
fprintf( stderr, " insize=%08x,", req->insize );
|
||||||
|
|
Loading…
Reference in New Issue