[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