Commit b05340a5 authored by Vitaliy Margolen's avatar Vitaliy Margolen Committed by Alexandre Julliard

ntdll: Implement FSCTL_PIPE_WAIT NtFsControlFile ioctl.

Implement FSCTL_PIPE_WAIT NtFsControlFile ioctl. Modify WaitNamedPipeW to use NtFsControlFile. Replace struct overlapped with event.
parent 12b35c2d
...@@ -1269,23 +1269,6 @@ BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer, ...@@ -1269,23 +1269,6 @@ BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
} }
/*********************************************************************** /***********************************************************************
* PIPE_CompletionWait (Internal)
*/
static void CALLBACK PIPE_CompletionWait(void *user, PIO_STATUS_BLOCK iosb, ULONG status)
{
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.@) * WaitNamedPipeA (KERNEL32.@)
*/ */
BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut) BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
...@@ -1305,59 +1288,83 @@ BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut) ...@@ -1305,59 +1288,83 @@ BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
/*********************************************************************** /***********************************************************************
* WaitNamedPipeW (KERNEL32.@) * WaitNamedPipeW (KERNEL32.@)
*
* Waits for a named pipe instance to become available
*
* PARAMS
* name [I] Pointer to a named pipe name to wait for
* nTimeOut [I] How long to wait in ms
*
* RETURNS
* TRUE: Success, named pipe can be opened with CreteFile
* FALSE: Failure, GetLastError can be called for further details
*/ */
BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut) BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
{ {
BOOL ret;
OVERLAPPED ov;
UNICODE_STRING nt_name;
static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'}; static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
NTSTATUS status;
UNICODE_STRING nt_name, pipe_dev_name;
FILE_PIPE_WAIT_FOR_BUFFER *pipe_wait;
IO_STATUS_BLOCK iosb;
OBJECT_ATTRIBUTES attr;
ULONG sz_pipe_wait;
HANDLE pipe_dev;
TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut); TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL )) if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
return FALSE; return FALSE;
if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) ) if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) ||
nt_name.Length < sizeof(leadin) ||
strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(WCHAR) != 0))
{ {
RtlFreeUnicodeString( &nt_name ); RtlFreeUnicodeString( &nt_name );
SetLastError( ERROR_PATH_NOT_FOUND );
return FALSE; return FALSE;
} }
if (nt_name.Length < sizeof(leadin) ||
strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0]))) sz_pipe_wait = sizeof(*pipe_wait) + nt_name.Length - sizeof(leadin) - sizeof(WCHAR);
if (!(pipe_wait = HeapAlloc( GetProcessHeap(), 0, sz_pipe_wait)))
{ {
RtlFreeUnicodeString( &nt_name ); RtlFreeUnicodeString( &nt_name );
SetLastError( ERROR_OUTOFMEMORY );
return FALSE; return FALSE;
} }
memset(&ov,0,sizeof(ov)); pipe_dev_name.Buffer = nt_name.Buffer;
ov.hEvent = CreateEventW( NULL, 0, 0, NULL ); pipe_dev_name.Length = sizeof(leadin);
if (!ov.hEvent) pipe_dev_name.MaximumLength = sizeof(leadin);
return FALSE; InitializeObjectAttributes(&attr,&pipe_dev_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile( &pipe_dev, FILE_READ_ATTRIBUTES, &attr,
SERVER_START_REQ( wait_named_pipe ) &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (status != ERROR_SUCCESS)
{ {
req->timeout = nTimeOut; SetLastError( ERROR_PATH_NOT_FOUND );
req->overlapped = &ov; return FALSE;
req->func = PIPE_CompletionWait;
wine_server_add_data( req, nt_name.Buffer + sizeof(leadin)/sizeof(WCHAR),
nt_name.Length - sizeof(leadin) );
ret = !wine_server_call_err( req );
} }
SERVER_END_REQ;
pipe_wait->TimeoutSpecified = !(nTimeOut == NMPWAIT_USE_DEFAULT_WAIT);
pipe_wait->Timeout.QuadPart = nTimeOut * -10000L;
pipe_wait->NameLength = nt_name.Length - sizeof(leadin);
memcpy(pipe_wait->Name, nt_name.Buffer + sizeof(leadin)/sizeof(WCHAR),
pipe_wait->NameLength);
RtlFreeUnicodeString( &nt_name ); RtlFreeUnicodeString( &nt_name );
if(ret) status = NtFsControlFile( pipe_dev, NULL, NULL, NULL, &iosb, FSCTL_PIPE_WAIT,
pipe_wait, sz_pipe_wait, NULL, 0 );
HeapFree( GetProcessHeap(), 0, pipe_wait );
NtClose( pipe_dev );
if(status != STATUS_SUCCESS)
{ {
if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE)) SetLastError(RtlNtStatusToDosError(status));
{ return FALSE;
SetLastError(RtlNtStatusToDosError(ov.Internal));
ret = (ov.Internal==STATUS_SUCCESS);
}
} }
CloseHandle(ov.hEvent); else
return ret; return TRUE;
} }
......
...@@ -91,7 +91,7 @@ static void test_CreateNamedPipe(int pipemode) ...@@ -91,7 +91,7 @@ static void test_CreateNamedPipe(int pipemode)
/* lpSecurityAttrib */ NULL); /* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n"); ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
todo_wine ok(WaitNamedPipeA(PIPENAME, 2000), "WaitNamedPipe failed (%08lx)\n", GetLastError()); ok(WaitNamedPipeA(PIPENAME, 2000), "WaitNamedPipe failed (%08lx)\n", GetLastError());
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%08lx)\n", GetLastError()); ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%08lx)\n", GetLastError());
......
...@@ -931,7 +931,8 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_ ...@@ -931,7 +931,8 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_
PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode,
PVOID InputBuffer, ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize) PVOID InputBuffer, ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize)
{ {
NTSTATUS ret; NTSTATUS ret = STATUS_NOT_SUPPORTED;
HANDLE internal_event;
TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n", TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n",
DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FsControlCode, DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FsControlCode,
...@@ -946,26 +947,46 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_ ...@@ -946,26 +947,46 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_
break; break;
case FSCTL_PIPE_LISTEN : case FSCTL_PIPE_LISTEN :
case FSCTL_PIPE_WAIT :
{ {
HANDLE internal_event; OBJECT_ATTRIBUTES obj;
if(!Event) if(!Event)
{ {
OBJECT_ATTRIBUTES obj;
InitializeObjectAttributes(&obj, NULL, 0, 0, NULL); InitializeObjectAttributes(&obj, NULL, 0, 0, NULL);
ret = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, &obj, FALSE, FALSE); ret = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, &obj, FALSE, FALSE);
if(ret != STATUS_SUCCESS) return ret; if(ret != STATUS_SUCCESS) return ret;
} }
switch(FsControlCode)
SERVER_START_REQ(connect_named_pipe)
{ {
req->handle = DeviceHandle; case FSCTL_PIPE_LISTEN :
req->event = Event ? Event : internal_event; SERVER_START_REQ(connect_named_pipe)
req->func = pipe_completion_wait; {
ret = wine_server_call(req); req->handle = DeviceHandle;
} req->event = Event ? Event : internal_event;
SERVER_END_REQ; req->func = pipe_completion_wait;
ret = wine_server_call(req);
}
SERVER_END_REQ;
break;
case FSCTL_PIPE_WAIT :
{
FILE_PIPE_WAIT_FOR_BUFFER *buff = InputBuffer;
SERVER_START_REQ(wait_named_pipe)
{
req->handle = DeviceHandle;
req->timeout = buff->TimeoutSpecified ? buff->Timeout.QuadPart / -10000L
: NMPWAIT_USE_DEFAULT_WAIT;
req->event = Event ? Event : internal_event;
req->func = pipe_completion_wait;
wine_server_add_data( req, buff->Name, buff->NameLength );
ret = wine_server_call( req );
}
SERVER_END_REQ;
break;
}
}
if(ret == STATUS_SUCCESS) if(ret == STATUS_SUCCESS)
{ {
if(Event) if(Event)
...@@ -991,7 +1012,6 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_ ...@@ -991,7 +1012,6 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_
break; break;
default : default :
FIXME("Unsupported FsControlCode %lx\n", FsControlCode); FIXME("Unsupported FsControlCode %lx\n", FsControlCode);
ret = STATUS_NOT_SUPPORTED;
break; break;
} }
IoStatusBlock->u.Status = ret; IoStatusBlock->u.Status = ret;
......
...@@ -2458,8 +2458,9 @@ struct connect_named_pipe_reply ...@@ -2458,8 +2458,9 @@ struct connect_named_pipe_reply
struct wait_named_pipe_request struct wait_named_pipe_request
{ {
struct request_header __header; struct request_header __header;
obj_handle_t handle;
unsigned int timeout; unsigned int timeout;
void* overlapped; obj_handle_t event;
void* func; void* func;
/* VARARG(name,unicode_str); */ /* VARARG(name,unicode_str); */
}; };
...@@ -4345,6 +4346,6 @@ union generic_reply ...@@ -4345,6 +4346,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply; struct query_symlink_reply query_symlink_reply;
}; };
#define SERVER_PROTOCOL_VERSION 216 #define SERVER_PROTOCOL_VERSION 217
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -404,6 +404,13 @@ typedef struct _FILE_FS_ATTRIBUTE_INFORMATION { ...@@ -404,6 +404,13 @@ typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
WCHAR FileSystemName[1]; WCHAR FileSystemName[1];
} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION; } FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
typedef struct _FILE_PIPE_WAIT_FOR_BUFFER {
LARGE_INTEGER Timeout;
ULONG NameLength;
BOOLEAN TimeoutSpecified;
WCHAR Name[1];
} FILE_PIPE_WAIT_FOR_BUFFER, *PFILE_PIPE_WAIT_FOR_BUFFER;
/* Device GUIDs */ /* Device GUIDs */
#ifdef DEFINE_GUID #ifdef DEFINE_GUID
......
...@@ -443,9 +443,6 @@ static int named_pipe_device_get_file_info( struct fd *fd ) ...@@ -443,9 +443,6 @@ static int named_pipe_device_get_file_info( struct fd *fd )
return 0; return 0;
} }
/* this will be deleted as soon an we fix wait_named_pipe */
static struct named_pipe_device *named_pipe_device;
struct named_pipe_device *create_named_pipe_device( struct directory *root, struct named_pipe_device *create_named_pipe_device( struct directory *root,
const struct unicode_str *name ) const struct unicode_str *name )
{ {
...@@ -462,7 +459,6 @@ struct named_pipe_device *create_named_pipe_device( struct directory *root, ...@@ -462,7 +459,6 @@ struct named_pipe_device *create_named_pipe_device( struct directory *root,
dev = NULL; dev = NULL;
} }
} }
named_pipe_device = dev;
return dev; return dev;
} }
...@@ -846,12 +842,18 @@ DECL_HANDLER(connect_named_pipe) ...@@ -846,12 +842,18 @@ DECL_HANDLER(connect_named_pipe)
DECL_HANDLER(wait_named_pipe) DECL_HANDLER(wait_named_pipe)
{ {
struct named_pipe_device *device;
struct named_pipe *pipe; struct named_pipe *pipe;
struct pipe_server *server; struct pipe_server *server;
struct unicode_str name; struct unicode_str name;
device = (struct named_pipe_device *)get_handle_obj( current->process, req->handle,
FILE_READ_ATTRIBUTES, &named_pipe_device_ops );
if (!device) return;
get_req_unicode_str( &name ); get_req_unicode_str( &name );
pipe = (struct named_pipe *)find_object( named_pipe_device->pipes, &name, OBJ_CASE_INSENSITIVE ); pipe = (struct named_pipe *)find_object( device->pipes, &name, OBJ_CASE_INSENSITIVE );
release_object( device );
if (!pipe) if (!pipe)
{ {
set_error( STATUS_PIPE_NOT_AVAILABLE ); set_error( STATUS_PIPE_NOT_AVAILABLE );
...@@ -862,7 +864,7 @@ DECL_HANDLER(wait_named_pipe) ...@@ -862,7 +864,7 @@ DECL_HANDLER(wait_named_pipe)
{ {
/* there's already a server waiting for a client to connect */ /* there's already a server waiting for a client to connect */
thread_queue_apc( current, NULL, req->func, APC_ASYNC_IO, thread_queue_apc( current, NULL, req->func, APC_ASYNC_IO,
1, req->overlapped, NULL, (void *)STATUS_SUCCESS ); 1, req->event, NULL, (void *)STATUS_SUCCESS );
release_object( server ); release_object( server );
} }
else else
...@@ -875,10 +877,10 @@ DECL_HANDLER(wait_named_pipe) ...@@ -875,10 +877,10 @@ DECL_HANDLER(wait_named_pipe)
if (req->timeout == NMPWAIT_WAIT_FOREVER) if (req->timeout == NMPWAIT_WAIT_FOREVER)
create_async( current, NULL, &pipe->waiters, create_async( current, NULL, &pipe->waiters,
req->func, req->overlapped, NULL ); req->func, req->event, NULL );
else else
create_async( current, &timeout, &pipe->waiters, create_async( current, &timeout, &pipe->waiters,
req->func, req->overlapped, NULL ); req->func, req->event, NULL );
} }
release_object( pipe ); release_object( pipe );
......
...@@ -1751,8 +1751,9 @@ enum message_type ...@@ -1751,8 +1751,9 @@ enum message_type
/* Wait for a named pipe */ /* Wait for a named pipe */
@REQ(wait_named_pipe) @REQ(wait_named_pipe)
obj_handle_t handle;
unsigned int timeout; unsigned int timeout;
void* overlapped; obj_handle_t event;
void* func; void* func;
VARARG(name,unicode_str); /* pipe name */ VARARG(name,unicode_str); /* pipe name */
@END @END
......
...@@ -2216,8 +2216,9 @@ static void dump_connect_named_pipe_request( const struct connect_named_pipe_req ...@@ -2216,8 +2216,9 @@ static void dump_connect_named_pipe_request( const struct connect_named_pipe_req
static void dump_wait_named_pipe_request( const struct wait_named_pipe_request *req ) static void dump_wait_named_pipe_request( const struct wait_named_pipe_request *req )
{ {
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " timeout=%08x,", req->timeout ); fprintf( stderr, " timeout=%08x,", req->timeout );
fprintf( stderr, " overlapped=%p,", req->overlapped ); fprintf( stderr, " event=%p,", req->event );
fprintf( stderr, " func=%p,", req->func ); fprintf( stderr, " func=%p,", req->func );
fprintf( stderr, " name=" ); fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size ); dump_varargs_unicode_str( cur_size );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment