ntdll: implement FSCTL_PIPE_WAIT and get WaitNamedPipe to use it
Vitaliy Margolen
wine-patch at kievinfo.com
Tue Sep 6 20:15:28 CDT 2005
Along the same lines as prior patch by Ivan Leo Puoti.
There is one problem however. Native opens a handle to "\\??\\PIPE\\" and use it
to call NtFsControlFile on. Wine currently has no means to acquire this handle.
Also, there is no use for it either since it doesn't go past the call to ntdll.
Vitaliy Margolen
changelog:
ntdll: implement FSCTL_PIPE_WAIT and get WaitNamedPipe to use it
-------------- next part --------------
Index: dlls/kernel/sync.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/sync.c,v
retrieving revision 1.85
diff -u -p -r1.85 sync.c
--- dlls/kernel/sync.c 6 Sep 2005 14:09:42 -0000 1.85
+++ dlls/kernel/sync.c 7 Sep 2005 01:03:31 -0000
@@ -1217,23 +1217,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)
@@ -1253,12 +1236,24 @@ BOOL WINAPI WaitNamedPipeA (LPCSTR name,
/***********************************************************************
* WaitNamedPipeW (KERNEL32.@)
+ *
+ * Waits for a named pipe instance to become available
+ *
+ * Parameters
+ * name: Pointer to a named pipe name to wait for
+ * nTimeOut: How long to wait in ms
+ *
+ * Return values
+ * 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;
+ NTSTATUS status;
UNICODE_STRING nt_name;
+ FILE_PIPE_WAIT_FOR_BUFFER *pipe_wait;
+ IO_STATUS_BLOCK iosb;
+ ULONG sz_pipe_wait;
static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
@@ -1266,45 +1261,43 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name
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;
+ 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 );
- SERVER_START_REQ( wait_named_pipe )
- {
- req->timeout = nTimeOut;
- req->overlapped = &ov;
- req->func = PIPE_CompletionWait;
- wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
- ret = !wine_server_call_err( req );
- }
- SERVER_END_REQ;
+ /* FIXME: we need to get a handle for "\\??\\PIPE\\" */
+ status = NtFsControlFile((HANDLE)1230, NULL, NULL, NULL, &iosb, FSCTL_PIPE_WAIT,
+ pipe_wait, sz_pipe_wait, NULL, 0);
- RtlFreeUnicodeString( &nt_name );
+ HeapFree( GetProcessHeap(), 0, pipe_wait );
- if(ret)
+ 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;
}
--- wine/dlls/ntdll/file.c 2005-09-06 17:43:35.000000000 -0600
+++ wine-new/dlls/ntdll/file.c 2005-09-06 18:27:00.000000000 -0600
@@ -902,6 +982,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE D
PVOID InputBuffer, ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize)
{
NTSTATUS ret;
+ HANDLE internal_event;
TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n",
DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FsControlCode,
@@ -912,26 +993,45 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE D
switch(FsControlCode)
{
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->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)
Index: include/winioctl.h
===================================================================
RCS file: /home/wine/wine/include/winioctl.h,v
retrieving revision 1.15
diff -u -p -r1.15 winioctl.h
--- include/winioctl.h 24 Jun 2005 11:54:15 -0000 1.15
+++ include/winioctl.h 7 Sep 2005 00:39:47 -0000
@@ -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
Index: server/named_pipe.c
===================================================================
RCS file: /home/wine/wine/server/named_pipe.c,v
retrieving revision 1.47
diff -u -p -r1.47 named_pipe.c
--- server/named_pipe.c 6 Sep 2005 14:10:53 -0000 1.47
+++ server/named_pipe.c 7 Sep 2005 00:52:47 -0000
@@ -707,7 +707,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
@@ -720,10 +720,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 );
Index: server/protocol.def
===================================================================
RCS file: /home/wine/wine/server/protocol.def,v
retrieving revision 1.155
diff -u -p -r1.155 protocol.def
--- server/protocol.def 6 Sep 2005 14:10:53 -0000 1.155
+++ server/protocol.def 7 Sep 2005 00:54:36 -0000
@@ -1720,7 +1720,7 @@ enum message_type
/* Wait for a named pipe */
@REQ(wait_named_pipe)
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