ntdll: Implement FSCTL_PIPE_WAIT NtFsControlFile ioctl.
Vitaliy Margolen
wine-patch at kievinfo.com
Mon Dec 12 18:03:03 CST 2005
ChangeLog:
ntdll: Implement FSCTL_PIPE_WAIT NtFsControlFile ioctl.
kernel: Modify WaitNamedPipeW to use NtFsControlFile.
server: Replace struct overlapped with even.
dlls/kernel/sync.c | 95 +++++++++++++++++++++++++---------------------
dlls/kernel/tests/pipe.c | 2 -
dlls/ntdll/file.c | 44 +++++++++++++++------
include/winioctl.h | 7 +++
server/named_pipe.c | 19 +++++----
server/protocol.def | 3 +
6 files changed, 104 insertions(+), 66 deletions(-)
-------------- next part --------------
af425629092a4fc4b72b918020f2eb29ef1a4bc3
diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c
index 1f93efe..70a190f 100644
--- a/dlls/kernel/sync.c
+++ b/dlls/kernel/sync.c
@@ -1269,23 +1269,6 @@ BOOL WINAPI PeekNamedPipe( HANDLE hPipe,
}
/***********************************************************************
- * 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.@)
*/
BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
@@ -1305,59 +1288,83 @@ BOOL WINAPI WaitNamedPipeA (LPCSTR name,
/***********************************************************************
* 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 = (WCHAR*)leadin;
+ 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 | SYNCHRONIZE, &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 != ERROR_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;
}
diff --git a/dlls/kernel/tests/pipe.c b/dlls/kernel/tests/pipe.c
index a4c15fe..5b0286f 100644
--- a/dlls/kernel/tests/pipe.c
+++ b/dlls/kernel/tests/pipe.c
@@ -91,7 +91,7 @@ static void test_CreateNamedPipe(int pip
/* 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());
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 17c4ba0..fab4228 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -931,7 +931,8 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE D
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 D
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 = (FILE_PIPE_WAIT_FOR_BUFFER*)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 D
break;
default :
FIXME("Unsupported FsControlCode %lx\n", FsControlCode);
- ret = STATUS_NOT_SUPPORTED;
break;
}
IoStatusBlock->u.Status = ret;
diff --git a/include/winioctl.h b/include/winioctl.h
index 8ae5b6f..5a9ff32 100644
--- a/include/winioctl.h
+++ b/include/winioctl.h
@@ -404,6 +404,13 @@ typedef struct _FILE_FS_ATTRIBUTE_INFORM
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
diff --git a/server/named_pipe.c b/server/named_pipe.c
index e451156..2587d98 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -437,9 +437,6 @@ static void named_pipe_device_destroy( s
if (device->pipes) free( device->pipes );
}
-/* 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 )
{
@@ -456,7 +453,6 @@ struct named_pipe_device *create_named_p
dev = NULL;
}
}
- named_pipe_device = dev;
return dev;
}
@@ -840,15 +836,21 @@ 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 | SYNCHRONIZE, &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 );
if (!pipe)
{
set_error( STATUS_PIPE_NOT_AVAILABLE );
+ release_object( device );
return;
}
server = find_server( pipe, ps_wait_open );
@@ -856,7 +858,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
@@ -869,13 +871,14 @@ 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 );
+ release_object( device );
}
DECL_HANDLER(disconnect_named_pipe)
diff --git a/server/protocol.def b/server/protocol.def
index e4f3662..d46e44e 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -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
More information about the wine-patches
mailing list