/* * 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 #include #include #include #include #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 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__ */