[Wine-patches] [eter-1.0.12] Set file locks without wineserver (eterbug #5798).

Alexander Morozov amorozov на etersoft.ru
Пт Май 13 19:55:06 MSD 2011


----------- следующая часть -----------
From d1fa973ee9474e23ff0a39aa73deb0164e5564cd Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Fri, 13 May 2011 18:33:28 +0400
Subject: [eter-1.0.12] Set file locks without wineserver (eterbug #5798).

---
 dlls/ntdll/file.c       |   48 +++++++++++++++++++++++++++++++++++++---------
 dlls/ntdll/server.c     |   26 ++++++++++++++++++++++--
 include/wine/etersoft.h |   18 +++++++++++++++++
 server/fd.c             |    7 +++++-
 4 files changed, 85 insertions(+), 14 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index dc7af39..8eba2ac 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -82,6 +82,8 @@
 #include "winternl.h"
 #include "winioctl.h"
 #include "ddk/ntddser.h"
+
+#define ETERSOFT_FUNC_LOCK
 #include "wine/etersoft.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -226,6 +228,8 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
 
     if (io->u.Status == STATUS_SUCCESS)
     {
+        int fd, needs_close;
+
         if (created) io->Information = FILE_CREATED;
         else switch(disposition)
         {
@@ -244,6 +248,10 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
             io->Information = FILE_OVERWRITTEN;
             break;
         }
+        /* add to cache */
+        if (!server_get_unix_fd( *handle, access, &fd, &needs_close, NULL, NULL )
+            && needs_close)
+            close( fd );
     }
 
     return io->u.Status;
@@ -2470,20 +2478,31 @@ NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
         warn = FALSE;
     }
 
+    LOADETER_FUNC( etersoft_lock_file );
     for (;;)
     {
-        SERVER_START_REQ( lock_file )
+        if (etersoft_lock_file && etersoft_lock_file( hFile, offset->QuadPart,
+                count->QuadPart, dont_wait, exclusive, &ret ))
         {
-            req->handle      = wine_server_obj_handle( hFile );
-            req->offset      = offset->QuadPart;
-            req->count       = count->QuadPart;
-            req->shared      = !exclusive;
-            req->wait        = !dont_wait;
-            ret = wine_server_call( req );
-            handle = wine_server_ptr_handle( reply->handle );
-            async  = reply->overlapped;
+            if (ret == STATUS_UNSUCCESSFUL)
+                ret = FILE_GetNtStatus();
+            /* ret != STATUS_PENDING */
+        }
+        else
+        {
+            SERVER_START_REQ( lock_file )
+            {
+                req->handle      = wine_server_obj_handle( hFile );
+                req->offset      = offset->QuadPart;
+                req->count       = count->QuadPart;
+                req->shared      = !exclusive;
+                req->wait        = !dont_wait;
+                ret = wine_server_call( req );
+                handle = wine_server_ptr_handle( reply->handle );
+                async  = reply->overlapped;
+            }
+            SERVER_END_REQ;
         }
-        SERVER_END_REQ;
         if (ret != STATUS_PENDING)
         {
             if (!ret && lock_granted_event) NtSetEvent(lock_granted_event, NULL);
@@ -2534,6 +2553,15 @@ NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
         return STATUS_NOT_IMPLEMENTED;
     }
 
+    LOADETER_FUNC( etersoft_unlock_file );
+    if (etersoft_unlock_file && etersoft_unlock_file( hFile, offset->QuadPart,
+            count->QuadPart, &status ))
+    {
+        if (status == STATUS_UNSUCCESSFUL)
+            status = FILE_GetNtStatus();
+        return status;
+    }
+
     SERVER_START_REQ( unlock_file )
     {
         req->handle = wine_server_obj_handle( hFile );
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index f1e2eb9..734a50e 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -69,6 +69,9 @@
 #include "wine/debug.h"
 #include "ntdll_misc.h"
 
+#define ETERSOFT_FUNC_FD
+#include "wine/etersoft.h"
+
 /* mcache */
 extern BOOL mcache_check_msg( const struct __server_request_info* req, 
 								struct __server_request_info* rep );
@@ -456,9 +459,14 @@ static inline unsigned int handle_to_index( HANDLE handle, unsigned int *entry )
 static int add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
                             unsigned int access, unsigned int options )
 {
-    unsigned int entry, idx = handle_to_index( handle, &entry );
+    unsigned int entry, idx;
     int prev_fd;
 
+    LOADETER_FUNC( etersoft_save_fd );
+    if (etersoft_save_fd && etersoft_save_fd( handle, fd, type, access, options ))
+        return 1;
+
+    idx = handle_to_index( handle, &entry );
     if (entry >= FD_CACHE_ENTRIES)
     {
         FIXME( "too many allocated handles, not caching %p\n", handle );
@@ -494,9 +502,16 @@ static int add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
 static inline int get_cached_fd( HANDLE handle, enum server_fd_type *type,
                                  unsigned int *access, unsigned int *options )
 {
-    unsigned int entry, idx = handle_to_index( handle, &entry );
+    unsigned int entry, idx;
     int fd = -1;
 
+    LOADETER_FUNC( etersoft_get_fd );
+    if (etersoft_get_fd)
+        fd = etersoft_get_fd( handle, type, access, options );
+    if (fd >= 0)
+        return fd;
+
+    idx = handle_to_index( handle, &entry );
     if (entry < FD_CACHE_ENTRIES && fd_cache[entry])
     {
         fd = fd_cache[entry][idx].fd - 1;
@@ -513,9 +528,14 @@ static inline int get_cached_fd( HANDLE handle, enum server_fd_type *type,
  */
 int server_remove_fd_from_cache( HANDLE handle )
 {
-    unsigned int entry, idx = handle_to_index( handle, &entry );
+    unsigned int entry, idx;
     int fd = -1;
 
+    LOADETER_FUNC( etersoft_remove_fd );
+    if (etersoft_remove_fd && etersoft_remove_fd( handle ))
+        return -1;
+
+    idx = handle_to_index( handle, &entry );
     if (entry < FD_CACHE_ENTRIES && fd_cache[entry])
         fd = interlocked_xchg( &fd_cache[entry][idx].fd, 0 ) - 1;
 
diff --git a/include/wine/etersoft.h b/include/wine/etersoft.h
index 706a6b4..3723285 100644
--- a/include/wine/etersoft.h
+++ b/include/wine/etersoft.h
@@ -200,4 +200,22 @@ static int (*etersoft_ioctl_pre)(unsigned long code, void *in_buff,
 static void (*etersoft_ioctl_post)(void *process, void *saved_ptr, char *data);
 #endif
 
+#ifdef ETERSOFT_FUNC_FD
+static int (*etersoft_save_fd)(void *handle, int fd, unsigned int type,
+        unsigned int access, unsigned int options);
+
+static int (*etersoft_get_fd)(void *handle, unsigned int *type,
+        unsigned int *access, unsigned int *options);
+
+static int (*etersoft_remove_fd)(void *handle);
+#endif
+
+#ifdef ETERSOFT_FUNC_LOCK
+static int (*etersoft_lock_file)(void *handle, unsigned long long offset,
+        unsigned long long count, int dont_wait, int exclusive, int *status);
+
+static int (*etersoft_unlock_file)(void *handle, unsigned long long offset,
+        unsigned long long count, int *status);
+#endif
+
 #endif
diff --git a/server/fd.c b/server/fd.c
index a208136..12149e0 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2221,7 +2221,12 @@ DECL_HANDLER(get_handle_fd)
 
     if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
     {
-        int unix_fd = get_unix_fd( fd );
+        int unix_fd = -1;
+
+        if (fd->inode)
+            unix_fd = inode_get_lock_fd( fd->inode );
+        if (unix_fd == -1)
+            unix_fd = get_unix_fd( fd );
         if (unix_fd != -1)
         {
             reply->type = fd->fd_ops->get_fd_type( fd );
-- 
1.7.4.5



Подробная информация о списке рассылки Wine-patches