[Wine-patches] [2/5] ntdll: Use mountmgr IOCTL handler for removable disks.
Alexander Morozov
=?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Ср Ноя 12 12:45:13 MSK 2008
Ветка eterhack, баг 2790
----------- следующая часть -----------
From 64c92b88bdd037d8b7a7c23cb8b533901cb3ce0f Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Wed, 12 Nov 2008 12:34:18 +0300
Subject: [PATCH] ntdll: Use mountmgr IOCTL handler for removable disks.
---
dlls/ntdll/Makefile.in | 1 +
dlls/ntdll/directory.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++-
dlls/ntdll/loader.c | 3 +
3 files changed, 213 insertions(+), 1 deletions(-)
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index d0055f3..71b6e0b 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -7,6 +7,7 @@ MODULE = ntdll.dll
IMPORTLIB = ntdll
EXTRALIBS = @IOKITLIB@
EXTRADLLFLAGS = -Wl,--image-base,0x7bc00000
+EXTRADEFS = @HALINCL@
C_SRCS = \
actctx.c \
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index dee0ce6..caccebe 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -75,6 +75,75 @@
WINE_DEFAULT_DEBUG_CHANNEL(file);
+#ifdef SONAME_LIBHAL
+
+#include <dbus/dbus.h>
+#include <hal/libhal.h>
+
+#define DBUS_FUNCS \
+ DO_FUNC(dbus_bus_get); \
+ DO_FUNC(dbus_error_init); \
+ DO_FUNC(dbus_error_free); \
+ DO_FUNC(dbus_error_is_set); \
+ DO_FUNC(dbus_connection_unref)
+
+#define HAL_FUNCS \
+ DO_FUNC(libhal_ctx_free); \
+ DO_FUNC(libhal_ctx_init); \
+ DO_FUNC(libhal_ctx_new); \
+ DO_FUNC(libhal_ctx_set_dbus_connection); \
+ DO_FUNC(libhal_ctx_shutdown); \
+ DO_FUNC(libhal_device_get_property_bool); \
+ DO_FUNC(libhal_device_get_property_string); \
+ DO_FUNC(libhal_free_string); \
+ DO_FUNC(libhal_free_string_array); \
+ DO_FUNC(libhal_get_all_devices)
+
+#define DO_FUNC(f) static typeof(f) * p_##f
+DBUS_FUNCS;
+HAL_FUNCS;
+#undef DO_FUNC
+
+static void *hal_handle = NULL;
+
+int load_hal_functions(void)
+{
+ char error[128];
+
+ if (hal_handle)
+ return 0;
+ if (!(hal_handle = wine_dlopen( SONAME_LIBHAL, RTLD_NOW|RTLD_GLOBAL,
+ error, sizeof(error) )))
+ goto failed;
+#define DO_FUNC(f) if (!(p_##f = wine_dlsym( RTLD_DEFAULT, #f, \
+ error, sizeof(error) ))) goto failed
+ DBUS_FUNCS;
+#undef DO_FUNC
+#define DO_FUNC(f) if (!(p_##f = wine_dlsym( hal_handle, #f, \
+ error, sizeof(error) ))) goto failed
+ HAL_FUNCS;
+#undef DO_FUNC
+ return 0;
+failed:
+ WARN( "failed to load HAL support: %s\n", error );
+ return 1;
+}
+
+void unload_hal_functions(void)
+{
+ if (hal_handle)
+ {
+ wine_dlclose( hal_handle, NULL, 0 );
+ hal_handle = NULL;
+#define DO_FUNC(f) p_##f = NULL
+ DBUS_FUNCS;
+ HAL_FUNCS;
+#undef DO_FUNC
+ }
+}
+
+#endif /* SONAME_LIBHAL */
+
/* just in case... */
#undef VFAT_IOCTL_READDIR_BOTH
#undef USE_GETDENTS
@@ -1865,6 +1934,137 @@ static inline int get_dos_prefix_len( const UNICODE_STRING *name )
/******************************************************************************
+ * is_removable_disk
+ *
+ * Check if the device is a disk and it is removable.
+ * This function returns 0 for cdrom and floppy.
+ */
+static int is_removable_disk( const ANSI_STRING *unix_name )
+{
+#ifdef SONAME_LIBHAL
+ char *buf, *unix_device;
+ ssize_t len;
+ DBusError error;
+ DBusConnection *dbc;
+ LibHalContext *ctx;
+ int i, num, ret = 0, found = 0;
+ char **list;
+
+ buf = RtlAllocateHeap( GetProcessHeap(), 0, 2 * PATH_MAX + 2 );
+ if (!buf) return 0;
+ unix_device = buf + PATH_MAX + 1;
+
+ lstrcpynA( unix_device, unix_name->Buffer, unix_name->Length + 1 );
+ unix_device[unix_name->Length] = 0;
+ for (;;)
+ {
+ len = readlink( unix_device, buf, PATH_MAX );
+ if (len == -1)
+ break;
+ buf[len] = 0;
+ if (*buf == '/')
+ {
+ lstrcpynA( unix_device, buf, PATH_MAX + 1 );
+ continue;
+ }
+ *(strrchr( unix_device, '/' ) + 1) = 0;
+ strcat( unix_device, buf );
+ }
+
+ if (load_hal_functions())
+ goto end;
+
+ p_dbus_error_init( &error );
+ if (!(dbc = p_dbus_bus_get( DBUS_BUS_SYSTEM, &error )))
+ {
+ WARN( "failed to get system dbus connection: %s\n", error.message );
+ p_dbus_error_free( &error );
+ goto end;
+ }
+
+ if (!(ctx = p_libhal_ctx_new())) {
+ WARN( "HAL context creation failed\n" );
+ goto end;
+ }
+
+ if (!p_libhal_ctx_set_dbus_connection( ctx, dbc ))
+ {
+ WARN( "failed to set dbus connection\n" );
+ goto end;
+ }
+
+ if (!p_libhal_ctx_init( ctx, &error ))
+ {
+ WARN( "HAL context init failed: %s\n", error.message );
+ p_dbus_error_free( &error );
+ goto end;
+ }
+
+ if (!(list = p_libhal_get_all_devices( ctx, &num, &error )))
+ p_dbus_error_free( &error );
+ else
+ {
+ for (i = 0; i < num && !found; i++)
+ {
+ char *device;
+
+ if (!(device = p_libhal_device_get_property_string( ctx, list[i],
+ "block.device", &error )))
+ {
+ p_dbus_error_free( &error );
+ continue;
+ }
+ if (!strcmp( unix_device, device ))
+ {
+ char *parent;
+
+ if (!(parent = p_libhal_device_get_property_string( ctx, list[i],
+ "info.parent", &error )))
+ p_dbus_error_free( &error );
+ else
+ {
+ if (!p_libhal_device_get_property_bool( ctx, parent,
+ "storage.removable", &error ))
+ p_dbus_error_free( &error );
+ else
+ {
+ char *type;
+
+ if (!(type = p_libhal_device_get_property_string( ctx,
+ parent, "storage.drive_type", &error )))
+ p_dbus_error_free( &error );
+ else
+ {
+ if (!strcmp( type, "disk" ))
+ ret = 1;
+ p_libhal_free_string( type );
+ }
+ }
+ p_libhal_free_string( parent );
+ }
+ found = 1;
+ }
+ p_libhal_free_string( device );
+ }
+ p_libhal_free_string_array( list );
+ }
+
+ p_libhal_ctx_shutdown( ctx, &error );
+ if (p_dbus_error_is_set( &error ))
+ p_dbus_error_free( &error );
+ p_libhal_ctx_free( ctx );
+ p_dbus_connection_unref( dbc );
+end:
+ RtlFreeHeap( GetProcessHeap(), 0, buf );
+ return ret;
+#else
+ WARN( "HAL support not compiled in\n" );
+ return 0;
+#endif
+}
+
+
+/******************************************************************************
* wine_nt_to_unix_file_name (NTDLL.@) Not a Windows API
*
* Convert a file name from NT namespace to Unix namespace.
@@ -1910,7 +2110,15 @@ NTSTATUS wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *un
return STATUS_OBJECT_NAME_INVALID;
if (pos == name_len) /* no subdir, plain DOS device */
- return get_dos_device( name, name_len, unix_name_ret );
+ {
+ status = get_dos_device( name, name_len, unix_name_ret );
+ /* return STATUS_BAD_DEVICE_TYPE for removable disk device
+ in order to mountmgr.sys can handle IOCTLs */
+ if (status != STATUS_BAD_DEVICE_TYPE && is_removable_disk( unix_name_ret ))
+ return STATUS_BAD_DEVICE_TYPE;
+ else
+ return status;
+ }
for (prefix_len = 0; prefix_len < pos; prefix_len++)
prefix[prefix_len] = tolowerW(name[prefix_len]);
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 3a88199..f65dd8b 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -2551,6 +2551,9 @@ NTSTATUS WINAPI NtUnloadDriver( const UNICODE_STRING *DriverServiceName )
BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
{
if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst );
+#ifdef SONAME_LIBHAL
+ if (reason == DLL_PROCESS_DETACH) unload_hal_functions();
+#endif
return TRUE;
}
--
1.5.6.5.GIT
Подробная информация о списке рассылки Wine-patches