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