diff --git a/configure b/configure index f0cd81c248f2a183cfe1a7a4bd904224cdb1d743..c009a21e40d0dd5c9a7e918cf005e94096f99a10 100755 --- a/configure +++ b/configure @@ -743,6 +743,7 @@ DLLTOOL DLLWRAP COREFOUNDATIONLIB IOKITLIB +DISKARBITRATIONLIB LDEXECFLAGS COREAUDIO CROSSTEST @@ -15359,6 +15360,8 @@ fi IOKITLIB="-framework IOKit -framework CoreFoundation" + DISKARBITRATIONLIB="-framework DiskArbitration -framework CoreFoundation" + LDEXECFLAGS="-image_base 0x7bf00000 -Wl,-segaddr,WINE_DOS,0x00000000,-segaddr,WINE_SHARED_HEAP,0x7f000000" if test "$ac_cv_header_CoreAudio_CoreAudio_h" = "yes" -a "$ac_cv_header_AudioUnit_AudioUnit_h" = "yes" @@ -24840,6 +24843,7 @@ DLLTOOL!$DLLTOOL$ac_delim DLLWRAP!$DLLWRAP$ac_delim COREFOUNDATIONLIB!$COREFOUNDATIONLIB$ac_delim IOKITLIB!$IOKITLIB$ac_delim +DISKARBITRATIONLIB!$DISKARBITRATIONLIB$ac_delim LDEXECFLAGS!$LDEXECFLAGS$ac_delim COREAUDIO!$COREAUDIO$ac_delim CROSSTEST!$CROSSTEST$ac_delim @@ -24858,7 +24862,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 77; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 78; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/configure.ac b/configure.ac index a31cd9dbd7a119db63c2d553599c0c2a548e319a..53a312607343d559f54fdf430710161eaa276e14 100644 --- a/configure.ac +++ b/configure.ac @@ -1005,6 +1005,7 @@ case $host_os in dnl declare needed frameworks AC_SUBST(COREFOUNDATIONLIB,"-framework CoreFoundation") AC_SUBST(IOKITLIB,"-framework IOKit -framework CoreFoundation") + AC_SUBST(DISKARBITRATIONLIB,"-framework DiskArbitration -framework CoreFoundation") AC_SUBST(LDEXECFLAGS,["-image_base 0x7bf00000 -Wl,-segaddr,WINE_DOS,0x00000000,-segaddr,WINE_SHARED_HEAP,0x7f000000"]) if test "$ac_cv_header_CoreAudio_CoreAudio_h" = "yes" -a "$ac_cv_header_AudioUnit_AudioUnit_h" = "yes" then diff --git a/programs/explorer/Makefile.in b/programs/explorer/Makefile.in index d2630f45429c8db2449d3169f87d9635bca675c2..3ee51f8cd0697ddad95e1ff06507889ab79c42ad 100644 --- a/programs/explorer/Makefile.in +++ b/programs/explorer/Makefile.in @@ -7,10 +7,12 @@ APPMODE = -mwindows IMPORTS = user32 gdi32 advapi32 kernel32 ntdll DELAYIMPORTS = comctl32 EXTRADEFS = @HALINCL@ +EXTRALIBS = @DISKARBITRATIONLIB@ C_SRCS = \ desktop.c \ device.c \ + diskarb.c \ explorer.c \ hal.c \ systray.c diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c index bbbde03070fa3bedace58b904d58fe90e1a52c74..095f95b4eac7eb43af88268f2c44f5a197e60131 100644 --- a/programs/explorer/desktop.c +++ b/programs/explorer/desktop.c @@ -166,6 +166,7 @@ void manage_desktop( char *arg ) SetWindowTextW( hwnd, desktop_nameW ); SystemParametersInfoA( SPI_SETDESKPATTERN, -1, NULL, FALSE ); SetDeskWallPaper( (LPSTR)-1 ); + initialize_diskarbitration(); initialize_hal(); initialize_systray(); } diff --git a/programs/explorer/device.c b/programs/explorer/device.c index e3309fa5d95f71a8fafab674c360fc5c4c080785..922f4d055f529cfd764f39cfa1e05839542259e6 100644 --- a/programs/explorer/device.c +++ b/programs/explorer/device.c @@ -76,6 +76,16 @@ static void send_notify( int drive, int code ) SMTO_ABORTIFHUNG, 0, &result ); } +static inline int is_valid_device( struct stat *st ) +{ +#if defined(linux) || defined(__sun__) + return S_ISBLK( st->st_mode ); +#else + /* disks are char devices on *BSD */ + return S_ISCHR( st->st_mode ); +#endif +} + /* find or create a DOS drive for the corresponding device */ static int add_drive( const char *device, const char *type ) { @@ -84,7 +94,7 @@ static int add_drive( const char *device, const char *type ) struct stat dev_st, drive_st; int drive, first, last, avail = 0; - if (stat( device, &dev_st ) == -1 || !S_ISBLK( dev_st.st_mode )) return -1; + if (stat( device, &dev_st ) == -1 || !is_valid_device( &dev_st )) return -1; if (!(path = get_dosdevices_path())) return -1; p = path + strlen(path) - 3; @@ -123,7 +133,7 @@ static int add_drive( const char *device, const char *type ) else { in_use[drive] = 1; - if (!S_ISBLK( drive_st.st_mode )) continue; + if (!is_valid_device( &drive_st )) continue; if (dev_st.st_rdev == drive_st.st_rdev) goto done; } } diff --git a/programs/explorer/diskarb.c b/programs/explorer/diskarb.c new file mode 100644 index 0000000000000000000000000000000000000000..b3b653debe0cf63221f7d91981c36c2c819efb28 --- /dev/null +++ b/programs/explorer/diskarb.c @@ -0,0 +1,143 @@ +/* + * Devices support using the MacOS Disk Arbitration library. + * + * Copyright 2006 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include <assert.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <sys/time.h> + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" + +#include "wine/debug.h" +#include "explorer_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(explorer); + +#ifdef __APPLE__ + +#include <DiskArbitration/DiskArbitration.h> + +static void appeared_callback( DADiskRef disk, void *context ) +{ + CFDictionaryRef dict = DADiskCopyDescription( disk ); + const void *ref; + char device[64]; + char mount_point[PATH_MAX]; + const char *type = NULL; + + if (!dict) return; + + /* ignore non-removable devices */ + if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaRemovable") )) || + !CFBooleanGetValue( ref )) return; + + /* get device name */ + if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaBSDName") ))) return; + strcpy( device, "/dev/r" ); + CFStringGetCString( ref, device + 6, sizeof(device) - 6, kCFStringEncodingASCII ); + + if ((ref = CFDictionaryGetValue( dict, CFSTR("DAVolumePath") ))) + CFURLGetFileSystemRepresentation( ref, true, (UInt8 *)mount_point, sizeof(mount_point) ); + else + mount_point[0] = 0; + + if ((ref = CFDictionaryGetValue( dict, CFSTR("DAVolumeKind") ))) + { + if (!CFStringCompare( ref, CFSTR("cd9660"), 0 ) || + !CFStringCompare( ref, CFSTR("udf"), 0 )) + type = "cdrom"; + } + + WINE_TRACE( "got mount notification for '%s' on '%s'\n", device, mount_point ); + + add_dos_device( device, device, mount_point, type ); + CFRelease( dict ); +} + +static void changed_callback( DADiskRef disk, CFArrayRef keys, void *context ) +{ + appeared_callback( disk, context ); +} + +static void disappeared_callback( DADiskRef disk, void *context ) +{ + CFDictionaryRef dict = DADiskCopyDescription( disk ); + const void *ref; + char device[100]; + + if (!dict) return; + + /* ignore non-removable devices */ + if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaRemovable") )) || + !CFBooleanGetValue( ref )) return; + + /* get device name */ + if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaBSDName") ))) return; + strcpy( device, "/dev/r" ); + CFStringGetCString( ref, device + 6, sizeof(device) - 6, kCFStringEncodingASCII ); + + WINE_TRACE( "got unmount notification for '%s'\n", device ); + + remove_dos_device( device ); + CFRelease( dict ); +} + +static DWORD WINAPI runloop_thread( void *arg ) +{ + DASessionRef session = DASessionCreate( NULL ); + + if (!session) return 1; + + DASessionScheduleWithRunLoop( session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode ); + DARegisterDiskAppearedCallback( session, kDADiskDescriptionMatchVolumeMountable, + appeared_callback, NULL ); + DARegisterDiskDisappearedCallback( session, kDADiskDescriptionMatchVolumeMountable, + disappeared_callback, NULL ); + DARegisterDiskDescriptionChangedCallback( session, kDADiskDescriptionMatchVolumeMountable, + kDADiskDescriptionWatchVolumePath, changed_callback, NULL ); + CFRunLoopRun(); + DASessionUnscheduleFromRunLoop( session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode ); + CFRelease( session ); + return 0; +} + +void initialize_diskarbitration(void) +{ + HANDLE handle; + + if (!(handle = CreateThread( NULL, 0, runloop_thread, NULL, 0, NULL ))) return; + CloseHandle( handle ); +} + +#else /* __APPLE__ */ + +void initialize_diskarbitration(void) +{ + WINE_TRACE( "Skipping on non-Apple platform\n" ); +} + +#endif /* __APPLE__ */ diff --git a/programs/explorer/explorer_private.h b/programs/explorer/explorer_private.h index 806dd4c3dba0d1a7238d4f3e49995df39aa28a20..59667eb2c899f99caea5f5b8cbce2631db60c94a 100644 --- a/programs/explorer/explorer_private.h +++ b/programs/explorer/explorer_private.h @@ -26,6 +26,7 @@ extern BOOL add_dos_device( const char *udi, const char *device, extern BOOL remove_dos_device( const char *udi ); extern void manage_desktop( char *arg ); +extern void initialize_diskarbitration(void); extern void initialize_hal(void); extern void initialize_systray(void); diff --git a/programs/explorer/hal.c b/programs/explorer/hal.c index dc7f66f34c08dd06732dc3bd55fc2bc13bc0df1d..7cd1a1dbe455347b74bed00eb72683c233712a3c 100644 --- a/programs/explorer/hal.c +++ b/programs/explorer/hal.c @@ -240,7 +240,7 @@ void initialize_hal(void) void initialize_hal(void) { - WINE_WARN( "HAL support not compiled in\n" ); + WINE_TRACE( "Skipping, HAL support not compiled in\n" ); } #endif /* HAVE_LIBHAL */