Alexandre Julliard : ntdll: Add a helper to lock the user output buffer during a server call.

Alexandre Julliard julliard at winehq.org
Fri Sep 22 15:49:06 CDT 2017


Module: wine
Branch: master
Commit: a20c4e11dfe4d89fc0f7184616386e56354995df
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a20c4e11dfe4d89fc0f7184616386e56354995df

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Sep 22 14:58:09 2017 +0200

ntdll: Add a helper to lock the user output buffer during a server call.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/virtual.c | 10 ++++------
 dlls/ntdll/file.c             |  6 +++---
 dlls/ntdll/ntdll_misc.h       |  2 ++
 dlls/ntdll/server.c           | 17 ++++++++++++++---
 dlls/ntdll/virtual.c          | 25 +++++++++++++++++++++++++
 5 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index 1d611cd..ec2489f 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -1840,7 +1840,7 @@ static DWORD CALLBACK read_pipe( void *arg )
         "%u: ConnectNamedPipe failed %u\n", args->index, GetLastError() );
 
     success = ReadFile( args->pipe, args->base, args->size, &num_bytes, NULL );
-    todo_wine
+    todo_wine_if (!args->index)
     {
     ok( success, "%u: ReadFile failed %u\n", args->index, GetLastError() );
     ok( num_bytes == sizeof(testdata), "%u: wrong number of bytes read %u\n", args->index, num_bytes );
@@ -2056,7 +2056,7 @@ static void test_write_watch(void)
 
         num_bytes = 0;
         success = GetOverlappedResult( readpipe, &overlapped, &num_bytes, TRUE );
-        todo_wine
+        todo_wine_if (!i)
         {
         ok( success, "%u: GetOverlappedResult failed %u\n", i, GetLastError() );
         ok( num_bytes == sizeof(testdata), "%u: wrong number of bytes read %u\n", i, num_bytes );
@@ -2067,7 +2067,7 @@ static void test_write_watch(void)
         memset( results, 0, sizeof(results) );
         ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
         ok( !ret, "%u: GetWriteWatch failed %u\n", i, GetLastError() );
-        todo_wine
+        todo_wine_if (!i)
         {
         ok( count == 1, "%u: wrong count %lu\n", i, count );
         ok( results[0] == base, "%u: wrong result %p\n", i, results[0] );
@@ -2076,7 +2076,6 @@ static void test_write_watch(void)
         CloseHandle( readpipe );
         CloseHandle( writepipe );
         CloseHandle( overlapped.hEvent );
-        if (!success) break;  /* don't try message mode if byte mode already doesn't work */
     }
 
     for (i = 0; i < 2; i++)
@@ -2121,7 +2120,7 @@ static void test_write_watch(void)
         memset( results, 0, sizeof(results) );
         ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
         ok( !ret, "%u: GetWriteWatch failed %u\n", i, GetLastError() );
-        todo_wine
+        todo_wine_if (!i)
         {
         ok( count == 1, "%u: wrong count %lu\n", i, count );
         ok( results[0] == base, "%u: wrong result %p\n", i, results[0] );
@@ -2130,7 +2129,6 @@ static void test_write_watch(void)
         CloseHandle( readpipe );
         CloseHandle( writepipe );
         CloseHandle( thread );
-        if (!count) break;  /* don't try message mode if byte mode already doesn't work */
     }
 
     GetTempPathA( MAX_PATH, path );
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 0381e55..f0f5361 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -438,7 +438,7 @@ static NTSTATUS irp_completion( void *user, IO_STATUS_BLOCK *io, NTSTATUS status
         {
             req->user_arg = wine_server_client_ptr( async );
             wine_server_set_reply( req, async->buffer, async->size );
-            status = wine_server_call( req );
+            status = virtual_locked_server_call( req );
             information = reply->size;
         }
         SERVER_END_REQ;
@@ -577,7 +577,7 @@ static NTSTATUS server_read_file( HANDLE handle, HANDLE event, PIO_APC_ROUTINE a
         req->async = server_async( handle, &async->io, event, apc, apc_context, io );
         req->pos   = offset ? offset->QuadPart : 0;
         wine_server_set_reply( req, buffer, size );
-        status = wine_server_call( req );
+        status = virtual_locked_server_call( req );
         wait_handle = wine_server_ptr_handle( reply->wait );
         options     = reply->options;
         if (wait_handle && status != STATUS_PENDING)
@@ -1540,7 +1540,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
         if ((code & 3) != METHOD_BUFFERED)
             wine_server_add_data( req, out_buffer, out_size );
         wine_server_set_reply( req, out_buffer, out_size );
-        status = wine_server_call( req );
+        status = virtual_locked_server_call( req );
         wait_handle = wine_server_ptr_handle( reply->wait );
         options     = reply->options;
         if (wait_handle && status != STATUS_PENDING)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 8dae676..aad4546 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -88,6 +88,7 @@ extern void DECLSPEC_NORETURN abort_thread( int status ) DECLSPEC_HIDDEN;
 extern void DECLSPEC_NORETURN terminate_thread( int status ) DECLSPEC_HIDDEN;
 extern void DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN;
 extern sigset_t server_block_set DECLSPEC_HIDDEN;
+extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
 extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
 extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
 extern unsigned int server_select( const select_op_t *select_op, data_size_t size,
@@ -169,6 +170,7 @@ extern void virtual_clear_thread_stack(void) DECLSPEC_HIDDEN;
 extern BOOL virtual_handle_stack_fault( void *addr ) DECLSPEC_HIDDEN;
 extern BOOL virtual_is_valid_code_address( const void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
 extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack ) DECLSPEC_HIDDEN;
+extern unsigned int virtual_locked_server_call( void *req_ptr ) DECLSPEC_HIDDEN;
 extern BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ) DECLSPEC_HIDDEN;
 extern BOOL virtual_check_buffer_for_write( void *ptr, SIZE_T size ) DECLSPEC_HIDDEN;
 extern SIZE_T virtual_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T size ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index c3b878e..1e84fbf 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -278,6 +278,19 @@ static inline unsigned int wait_reply( struct __server_request_info *req )
 
 
 /***********************************************************************
+ *           server_call_unlocked
+ */
+unsigned int server_call_unlocked( void *req_ptr )
+{
+    struct __server_request_info * const req = req_ptr;
+    unsigned int ret;
+
+    if ((ret = send_request( req ))) return ret;
+    return wait_reply( req );
+}
+
+
+/***********************************************************************
  *           wine_server_call (NTDLL.@)
  *
  * Perform a server call.
@@ -301,13 +314,11 @@ static inline unsigned int wait_reply( struct __server_request_info *req )
  */
 unsigned int wine_server_call( void *req_ptr )
 {
-    struct __server_request_info * const req = req_ptr;
     sigset_t old_set;
     unsigned int ret;
 
     pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
-    ret = send_request( req );
-    if (!ret) ret = wait_reply( req );
+    ret = server_call_unlocked( req_ptr );
     pthread_sigmask( SIG_SETMASK, &old_set, NULL );
     return ret;
 }
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index d36dd7d..68a61b5 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1838,6 +1838,31 @@ static NTSTATUS check_write_access( void *base, size_t size, BOOL *has_write_wat
 }
 
 
+/***********************************************************************
+ *           virtual_locked_server_call
+ */
+unsigned int virtual_locked_server_call( void *req_ptr )
+{
+    struct __server_request_info * const req = req_ptr;
+    sigset_t sigset;
+    void *addr = req->reply_data;
+    data_size_t size = req->u.req.request_header.reply_size;
+    BOOL has_write_watch = FALSE;
+    unsigned int ret = STATUS_ACCESS_VIOLATION;
+
+    if (!size) return wine_server_call( req_ptr );
+
+    server_enter_uninterrupted_section( &csVirtual, &sigset );
+    if (!(ret = check_write_access( addr, size, &has_write_watch )))
+    {
+        ret = server_call_unlocked( req );
+        if (has_write_watch) update_write_watches( addr, size, wine_server_reply_size( req ));
+    }
+    server_leave_uninterrupted_section( &csVirtual, &sigset );
+    return ret;
+}
+
+
 
 /***********************************************************************
  *           virtual_is_valid_code_address




More information about the wine-cvs mailing list