ntdll: Implement FSCTL_PIPE_WAIT NtFsControlFile ioctl.

Implement FSCTL_PIPE_WAIT NtFsControlFile ioctl.
Modify WaitNamedPipeW to use NtFsControlFile.
Replace struct overlapped with event.
This commit is contained in:
Vitaliy Margolen 2005-12-14 11:14:02 +01:00 committed by Alexandre Julliard
parent 12b35c2dd8
commit b05340a523
8 changed files with 108 additions and 69 deletions

View File

@ -1268,23 +1268,6 @@ BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
return FALSE;
}
/***********************************************************************
* 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.@)
*/
@ -1305,59 +1288,83 @@ BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
/***********************************************************************
* 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 ret;
OVERLAPPED ov;
UNICODE_STRING nt_name;
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);
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
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 );
SetLastError( ERROR_PATH_NOT_FOUND );
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 );
SetLastError( ERROR_OUTOFMEMORY );
return FALSE;
}
memset(&ov,0,sizeof(ov));
ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
if (!ov.hEvent)
return FALSE;
SERVER_START_REQ( wait_named_pipe )
pipe_dev_name.Buffer = nt_name.Buffer;
pipe_dev_name.Length = sizeof(leadin);
pipe_dev_name.MaximumLength = sizeof(leadin);
InitializeObjectAttributes(&attr,&pipe_dev_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile( &pipe_dev, FILE_READ_ATTRIBUTES, &attr,
&iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (status != ERROR_SUCCESS)
{
req->timeout = nTimeOut;
req->overlapped = &ov;
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 );
SetLastError( ERROR_PATH_NOT_FOUND );
return FALSE;
}
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 );
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(ov.Internal));
ret = (ov.Internal==STATUS_SUCCESS);
}
SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}
CloseHandle(ov.hEvent);
return ret;
else
return TRUE;
}

View File

@ -91,7 +91,7 @@ static void test_CreateNamedPipe(int pipemode)
/* lpSecurityAttrib */ NULL);
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);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%08lx)\n", GetLastError());

View File

@ -931,7 +931,8 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_
PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode,
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",
DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FsControlCode,
@ -946,26 +947,46 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_
break;
case FSCTL_PIPE_LISTEN :
case FSCTL_PIPE_WAIT :
{
HANDLE internal_event;
OBJECT_ATTRIBUTES obj;
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)
switch(FsControlCode)
{
req->handle = DeviceHandle;
req->event = Event ? Event : internal_event;
req->func = pipe_completion_wait;
ret = wine_server_call(req);
}
SERVER_END_REQ;
case FSCTL_PIPE_LISTEN :
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;
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(Event)
@ -991,7 +1012,6 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_
break;
default :
FIXME("Unsupported FsControlCode %lx\n", FsControlCode);
ret = STATUS_NOT_SUPPORTED;
break;
}
IoStatusBlock->u.Status = ret;

View File

@ -2458,8 +2458,9 @@ struct connect_named_pipe_reply
struct wait_named_pipe_request
{
struct request_header __header;
obj_handle_t handle;
unsigned int timeout;
void* overlapped;
obj_handle_t event;
void* func;
/* VARARG(name,unicode_str); */
};
@ -4345,6 +4346,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply;
};
#define SERVER_PROTOCOL_VERSION 216
#define SERVER_PROTOCOL_VERSION 217
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -404,6 +404,13 @@ typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
WCHAR FileSystemName[1];
} 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 */
#ifdef DEFINE_GUID

View File

@ -443,9 +443,6 @@ static int named_pipe_device_get_file_info( struct fd *fd )
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,
const struct unicode_str *name )
{
@ -462,7 +459,6 @@ struct named_pipe_device *create_named_pipe_device( struct directory *root,
dev = NULL;
}
}
named_pipe_device = dev;
return dev;
}
@ -846,12 +842,18 @@ DECL_HANDLER(connect_named_pipe)
DECL_HANDLER(wait_named_pipe)
{
struct named_pipe_device *device;
struct named_pipe *pipe;
struct pipe_server *server;
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 );
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)
{
set_error( STATUS_PIPE_NOT_AVAILABLE );
@ -862,7 +864,7 @@ DECL_HANDLER(wait_named_pipe)
{
/* there's already a server waiting for a client to connect */
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 );
}
else
@ -875,10 +877,10 @@ DECL_HANDLER(wait_named_pipe)
if (req->timeout == NMPWAIT_WAIT_FOREVER)
create_async( current, NULL, &pipe->waiters,
req->func, req->overlapped, NULL );
req->func, req->event, NULL );
else
create_async( current, &timeout, &pipe->waiters,
req->func, req->overlapped, NULL );
req->func, req->event, NULL );
}
release_object( pipe );

View File

@ -1751,8 +1751,9 @@ enum message_type
/* Wait for a named pipe */
@REQ(wait_named_pipe)
obj_handle_t handle;
unsigned int timeout;
void* overlapped;
obj_handle_t event;
void* func;
VARARG(name,unicode_str); /* pipe name */
@END

View File

@ -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 )
{
fprintf( stderr, " handle=%p,", req->handle );
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, " name=" );
dump_varargs_unicode_str( cur_size );