| /* | |
| * 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 HAVE_DISKARBITRATION_DISKARBITRATION_H | |
| #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 )) goto done; | |
| /* get device name */ | |
| if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaBSDName") ))) goto done; | |
| 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 ); | |
| done: | |
| 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 )) goto done; | |
| /* get device name */ | |
| if (!(ref = CFDictionaryGetValue( dict, CFSTR("DAMediaBSDName") ))) goto done; | |
| 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 ); | |
| done: | |
| 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 /* HAVE_DISKARBITRATION_DISKARBITRATION_H */ | |
| void initialize_diskarbitration(void) | |
| { | |
| WINE_TRACE( "Skipping, Disk Arbitration support not compiled in\n" ); | |
| } | |
| #endif /* HAVE_DISKARBITRATION_DISKARBITRATION_H */ |