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

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


----------- следующая часть -----------
From edfaad3ad690c684f6769a5aec7b06716f693f8b Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Wed, 11 May 2011 16:43:33 +0400
Subject: [eterhack] Set file locks without wineserver (eterbug #5798).

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

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 8380ecf..da2bf4b 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -187,6 +187,8 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
 
     if (io->u.Status == STATUS_SUCCESS)
     {
+        int fd, needs_close;
+
         if (created) io->Information = FILE_CREATED;
         else switch(disposition)
         {
@@ -205,6 +207,10 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
             io->Information = FILE_OVERWRITTEN;
             break;
         }
+        /* add to cache */
+        if (!server_get_unix_fd( *handle, access, &fd, &needs_close, NULL, NULL )
+            && needs_close)
+            close( fd );
     }
     else if (io->u.Status == STATUS_TOO_MANY_OPENED_FILES)
     {
@@ -2696,6 +2702,7 @@ NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
                             PLARGE_INTEGER count, ULONG* key, BOOLEAN dont_wait,
                             BOOLEAN exclusive )
 {
+    DEFETER_FUNC( etersoft_lock_file );
     NTSTATUS    ret;
     HANDLE      handle;
     BOOLEAN     async;
@@ -2713,20 +2720,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);
@@ -2766,6 +2784,7 @@ NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
                               PLARGE_INTEGER offset, PLARGE_INTEGER count,
                               PULONG key )
 {
+    DEFETER_FUNC( etersoft_unlock_file );
     NTSTATUS status;
 
     TRACE( "%p %x%08x %x%08x\n",
@@ -2777,6 +2796,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 5eb87ba..4a8b25a 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -72,6 +72,8 @@
 #include "wine/debug.h"
 #include "ntdll_misc.h"
 
+#include "wine/etersoft.h"
+
 /* mcache */
 extern BOOL mcache_check_msg( const struct __server_request_info* req, 
 								struct __server_request_info* rep );
@@ -478,9 +480,15 @@ 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 );
+    DEFETER_FUNC( etersoft_save_fd );
+    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 );
@@ -516,9 +524,17 @@ 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 );
+    DEFETER_FUNC( etersoft_get_fd );
+    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;
@@ -535,9 +551,15 @@ 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 );
+    DEFETER_FUNC( etersoft_remove_fd );
+    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 42898ba..ac74c3f 100644
--- a/include/wine/etersoft.h
+++ b/include/wine/etersoft.h
@@ -174,4 +174,18 @@ typedef int (*t_etersoft_ioctl_pre)(unsigned long code, void *in_buff,
 
 typedef void (*t_etersoft_ioctl_post)(void *process, void *saved_ptr, char *data);
 
+typedef int (*t_etersoft_save_fd)(void *handle, int fd, unsigned int type,
+        unsigned int access, unsigned int options);
+
+typedef int (*t_etersoft_get_fd)(void *handle, unsigned int *type,
+        unsigned int *access, unsigned int *options);
+
+typedef int (*t_etersoft_remove_fd)(void *handle);
+
+typedef int (*t_etersoft_lock_file)(void *handle, unsigned long long offset,
+        unsigned long long count, int dont_wait, int exclusive, int *status);
+
+typedef int (*t_etersoft_unlock_file)(void *handle, unsigned long long offset,
+        unsigned long long count, int *status);
+
 #endif
diff --git a/server/fd.c b/server/fd.c
index 8ac5c7b..337f9c9 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2479,7 +2479,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