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:
parent
12b35c2dd8
commit
b05340a523
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue