1/* 2 * Copyright (c) 1998-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include "DiskArbitration.h" 25 26#include "DiskArbitrationPrivate.h" 27#include "DAInternal.h" 28#include "DAServer.h" 29 30#include <pthread.h> 31#include <unistd.h> 32#include <IOKit/storage/IOStorageProtocolCharacteristics.h> 33#include <Security/Authorization.h> 34 35CFDictionaryRef kDADiskDescriptionMatchMediaUnformatted = NULL; 36CFDictionaryRef kDADiskDescriptionMatchMediaWhole = NULL; 37CFDictionaryRef kDADiskDescriptionMatchVolumeMountable = NULL; 38CFDictionaryRef kDADiskDescriptionMatchVolumeUnrecognized = NULL; 39 40CFArrayRef kDADiskDescriptionWatchVolumeName = NULL; 41CFArrayRef kDADiskDescriptionWatchVolumePath = NULL; 42 43__private_extern__ char * _DADiskGetID( DADiskRef disk ); 44__private_extern__ mach_port_t _DADiskGetSessionID( DADiskRef disk ); 45__private_extern__ void _DADiskInitialize( void ); 46__private_extern__ void _DADiskSetDescription( DADiskRef disk, CFDictionaryRef description ); 47 48__private_extern__ AuthorizationRef _DASessionGetAuthorization( DASessionRef session ); 49__private_extern__ mach_port_t _DASessionGetID( DASessionRef session ); 50__private_extern__ void _DASessionInitialize( void ); 51 52static void __DAInitialize( void ) 53{ 54 CFMutableDictionaryRef match; 55 CFMutableArrayRef watch; 56 57 /* 58 * Initialize classes. 59 */ 60 61 _DADiskInitialize( ); 62 63 _DASessionInitialize( ); 64 65 /* 66 * Create the disk match description for unformatted media. 67 */ 68 69 match = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); 70 71 assert( match ); 72 73 ___CFDictionarySetIntegerValue( match, kDADiskDescriptionMediaSizeKey, 0 ); 74 75 kDADiskDescriptionMatchMediaUnformatted = match; 76 77 /* 78 * Create the disk match description for whole media. 79 */ 80 81 match = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); 82 83 assert( match ); 84 85 CFDictionarySetValue( match, kDADiskDescriptionMediaWholeKey, kCFBooleanTrue ); 86 87 kDADiskDescriptionMatchMediaWhole = match; 88 89 /* 90 * Create the disk match description for mountable volumes. 91 */ 92 93 match = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); 94 95 assert( match ); 96 97 CFDictionarySetValue( match, kDADiskDescriptionVolumeMountableKey, kCFBooleanTrue ); 98 99 kDADiskDescriptionMatchVolumeMountable = match; 100 101 /* 102 * Create the disk match description for unrecognized volumes. 103 */ 104 105 match = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); 106 107 assert( match ); 108 109 CFDictionarySetValue( match, kDADiskDescriptionVolumeMountableKey, kCFBooleanFalse ); 110 111 kDADiskDescriptionMatchVolumeUnrecognized = match; 112 113 /* 114 * Create the disk watch description for volume name changes. 115 */ 116 117 watch = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); 118 119 assert( watch ); 120 121 CFArrayAppendValue( watch, kDADiskDescriptionVolumeNameKey ); 122 123 kDADiskDescriptionWatchVolumeName = watch; 124 125 /* 126 * Create the disk watch description for volume path changes. 127 */ 128 129 watch = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); 130 131 assert( watch ); 132 133 CFArrayAppendValue( watch, kDADiskDescriptionVolumePathKey ); 134 135 kDADiskDescriptionWatchVolumePath = watch; 136} 137 138static DAReturn __DAQueueRequest( DASessionRef session, 139 _DARequestKind kind, 140 DADiskRef argument0, 141 CFIndex argument1, 142 CFTypeRef argument2, 143 CFTypeRef argument3, 144 void * address, 145 void * context ) 146{ 147 DAReturn status; 148 149 status = kDAReturnBadArgument; 150 151 if ( session ) 152 { 153 CFDataRef _argument2 = NULL; 154 CFDataRef _argument3 = NULL; 155 156 if ( argument2 ) _argument2 = _DASerialize( kCFAllocatorDefault, argument2 ); 157 if ( argument3 ) _argument3 = _DASerialize( kCFAllocatorDefault, argument3 ); 158 159 status = _DAServerSessionQueueRequest( _DASessionGetID( session ), 160 ( int32_t ) kind, 161 ( caddr_t ) _DADiskGetID( argument0 ), 162 ( int32_t ) argument1, 163 ( vm_address_t ) ( _argument2 ? CFDataGetBytePtr( _argument2 ) : 0 ), 164 ( mach_msg_type_number_t ) ( _argument2 ? CFDataGetLength( _argument2 ) : 0 ), 165 ( vm_address_t ) ( _argument3 ? CFDataGetBytePtr( _argument3 ) : 0 ), 166 ( mach_msg_type_number_t ) ( _argument3 ? CFDataGetLength( _argument3 ) : 0 ), 167 ( uintptr_t ) address, 168 ( uintptr_t ) context ); 169 170 if ( _argument2 ) CFRelease( _argument2 ); 171 if ( _argument3 ) CFRelease( _argument3 ); 172 } 173 174 return status; 175} 176 177static void __DAQueueResponse( DASessionRef session, 178 void * address, 179 void * context, 180 _DACallbackKind kind, 181 DADiskRef disk, 182 CFTypeRef response, 183 SInt32 responseID ) 184{ 185 CFDataRef _response = NULL; 186 187 if ( response ) _response = _DASerialize( kCFAllocatorDefault, response ); 188 189 _DAServerSessionQueueResponse( _DASessionGetID( session ), 190 ( uintptr_t ) address, 191 ( uintptr_t ) context, 192 ( int32_t ) kind, 193 ( caddr_t ) _DADiskGetID( disk ), 194 ( vm_address_t ) ( _response ? CFDataGetBytePtr( _response ) : 0 ), 195 ( mach_msg_type_number_t ) ( _response ? CFDataGetLength( _response ) : 0 ), 196 ( int32_t ) responseID ); 197 198 if ( _response ) CFRelease( _response ); 199} 200 201__private_extern__ DAReturn _DAAuthorize( DASessionRef session, _DAAuthorizeOptions options, DADiskRef disk, const char * right ) 202{ 203 DAReturn status; 204 205 status = kDAReturnNotPrivileged; 206 207 if ( status ) 208 { 209 if ( ( options & _kDAAuthorizeOptionIsOwner ) ) 210 { 211 uid_t diskUID; 212 213 status = _DAServerDiskGetUserUID( _DADiskGetSessionID( disk ), _DADiskGetID( disk ), &diskUID ); 214 215 if ( status ) 216 { 217 return status; 218 } 219 220 status = kDAReturnNotPrivileged; 221 222 if ( diskUID == geteuid( ) ) 223 { 224 status = kDAReturnSuccess; 225 } 226 } 227 } 228 229 if ( status ) 230 { 231 AuthorizationRef authorization; 232 233 authorization = _DASessionGetAuthorization( session ); 234 235 if ( authorization ) 236 { 237 CFDictionaryRef description; 238 239 description = DADiskCopyDescription( disk ); 240 241 if ( description ) 242 { 243 AuthorizationFlags flags; 244 AuthorizationItem item; 245 char * name; 246 AuthorizationRights rights; 247 248 flags = kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize; 249 250 if ( CFDictionaryGetValue( description, kDADiskDescriptionVolumeNetworkKey ) == kCFBooleanTrue ) 251 { 252 asprintf( &name, "system.volume.network.%s", right ); 253 } 254 else 255 { 256 CFTypeRef object; 257 258 object = CFDictionaryGetValue( description, kDADiskDescriptionDeviceProtocolKey ); 259 260 if ( object && CFEqual( object, CFSTR( kIOPropertyPhysicalInterconnectTypeVirtual ) ) ) 261 { 262 asprintf( &name, "system.volume.virtual.%s", right ); 263 } 264 else 265 { 266 if ( CFDictionaryGetValue( description, kDADiskDescriptionMediaRemovableKey ) == kCFBooleanTrue ) 267 { 268 if ( CFDictionaryGetValue( description, kDADiskDescriptionMediaTypeKey ) ) 269 { 270 asprintf( &name, "system.volume.optical.%s", right ); 271 } 272 else 273 { 274 asprintf( &name, "system.volume.removable.%s", right ); 275 } 276 } 277 else 278 { 279 if ( CFDictionaryGetValue( description, kDADiskDescriptionDeviceInternalKey ) == kCFBooleanTrue ) 280 { 281 asprintf( &name, "system.volume.internal.%s", right ); 282 } 283 else 284 { 285 asprintf( &name, "system.volume.external.%s", right ); 286 } 287 } 288 } 289 } 290 291 if ( name ) 292 { 293 item.flags = 0; 294 item.name = name; 295 item.value = NULL; 296 item.valueLength = 0; 297 298 rights.count = 1; 299 rights.items = &item; 300 301 status = AuthorizationCopyRights( authorization, &rights, NULL, flags, NULL ); 302 303 if ( status ) 304 { 305 status = kDAReturnNotPrivileged; 306 } 307 308 free( name ); 309 } 310 311 CFRelease( description ); 312 } 313 } 314 } 315 316 return status; 317} 318 319__private_extern__ void _DADispatchCallback( DASessionRef session, 320 void * address, 321 void * context, 322 _DACallbackKind kind, 323 CFTypeRef argument0, 324 CFTypeRef argument1 ) 325{ 326 DADiskRef disk = NULL; 327 CFTypeRef response = NULL; 328 329 if ( argument0 ) 330 { 331 disk = _DADiskCreateFromSerialization( CFGetAllocator( session ), session, argument0 ); 332 } 333 334 switch ( kind ) 335 { 336 case _kDADiskAppearedCallback: 337 { 338 ( ( DADiskAppearedCallback ) address )( disk, context ); 339 340 break; 341 } 342 case _kDADiskClaimCallback: 343 { 344 ( ( DADiskClaimCallback ) address )( disk, argument1, context ); 345 346 break; 347 } 348 case _kDADiskClaimReleaseCallback: 349 { 350 response = ( ( DADiskClaimReleaseCallback ) address )( disk, context ); 351 352 response = response ? response : kCFNull; 353 354 break; 355 } 356 case _kDADiskDescriptionChangedCallback: 357 { 358 ( ( DADiskDescriptionChangedCallback ) address )( disk, argument1, context ); 359 360 break; 361 } 362 case _kDADiskDisappearedCallback: 363 { 364 ( ( DADiskDisappearedCallback ) address )( disk, context ); 365 366 break; 367 } 368 case _kDADiskEjectCallback: 369 { 370 ( ( DADiskEjectCallback ) address )( disk, argument1, context ); 371 372 break; 373 } 374 case _kDADiskEjectApprovalCallback: 375 { 376 response = ( ( DADiskEjectApprovalCallback ) address )( disk, context ); 377 378 response = response ? response : kCFNull; 379 380 break; 381 } 382 case _kDADiskMountCallback: 383 { 384 ( ( DADiskMountCallback ) address )( disk, argument1, context ); 385 386 break; 387 } 388 case _kDADiskMountApprovalCallback: 389 { 390 response = ( ( DADiskMountApprovalCallback ) address )( disk, context ); 391 392 response = response ? response : kCFNull; 393 394 break; 395 } 396 case _kDADiskPeekCallback: 397 { 398 ( ( DADiskPeekCallback ) address )( disk, context ); 399 400 response = kCFNull; 401 402 break; 403 } 404 case _kDADiskRenameCallback: 405 { 406 ( ( DADiskRenameCallback ) address )( disk, argument1, context ); 407 408 break; 409 } 410 case _kDADiskUnmountCallback: 411 { 412 ( ( DADiskUnmountCallback ) address )( disk, argument1, context ); 413 414 break; 415 } 416 case _kDADiskUnmountApprovalCallback: 417 { 418 response = ( ( DADiskUnmountApprovalCallback ) address )( disk, context ); 419 420 response = response ? response : kCFNull; 421 422 break; 423 } 424 case _kDAIdleCallback: 425 { 426 ( ( DAIdleCallback ) address )( context ); 427 428 break; 429 } 430 } 431 432 if ( response ) 433 { 434 SInt32 responseID; 435 436 responseID = ___CFNumberGetIntegerValue( argument1 ); 437 438 if ( response == kCFNull ) 439 { 440 response = NULL; 441 } 442 443 __DAQueueResponse( session, address, context, kind, disk, response, responseID ); 444 445 if ( response ) 446 { 447 CFRelease( response ); 448 } 449 } 450 451 if ( disk ) 452 { 453 _DADiskSetDescription( disk, NULL ); 454 455 CFRelease( disk ); 456 } 457} 458 459__private_extern__ void _DAInitialize( void ) 460{ 461 static pthread_once_t initialize = PTHREAD_ONCE_INIT; 462 463 pthread_once( &initialize, __DAInitialize ); 464} 465 466__private_extern__ void _DARegisterCallback( DASessionRef session, 467 void * address, 468 void * context, 469 _DACallbackKind kind, 470 CFIndex order, 471 CFDictionaryRef match, 472 CFArrayRef watch ) 473{ 474 if ( session ) 475 { 476 CFDataRef _match = NULL; 477 CFDataRef _watch = NULL; 478 479 if ( match ) _match = _DASerializeDiskDescription( kCFAllocatorDefault, match ); 480 if ( watch ) _watch = _DASerialize( kCFAllocatorDefault, watch ); 481 482 _DAServerSessionRegisterCallback( _DASessionGetID( session ), 483 ( uintptr_t ) address, 484 ( uintptr_t ) context, 485 ( int32_t ) kind, 486 ( int32_t ) order, 487 ( vm_address_t ) ( _match ? CFDataGetBytePtr( _match ) : 0 ), 488 ( mach_msg_type_number_t ) ( _match ? CFDataGetLength( _match ) : 0 ), 489 ( vm_address_t ) ( _watch ? CFDataGetBytePtr( _watch ) : 0 ), 490 ( mach_msg_type_number_t ) ( _watch ? CFDataGetLength( _watch ) : 0 ) ); 491 492 if ( _match ) CFRelease( _match ); 493 if ( _watch ) CFRelease( _watch ); 494 } 495} 496 497__private_extern__ void _DAUnregisterCallback( DASessionRef session, void * address, void * context ) 498{ 499 if ( session ) 500 { 501 _DAServerSessionUnregisterCallback( _DASessionGetID( session ), ( uintptr_t ) address, ( uintptr_t ) context ); 502 } 503} 504 505void DADiskClaim( DADiskRef disk, 506 DADiskClaimOptions options, 507 DADiskClaimReleaseCallback release, 508 void * releaseContext, 509 DADiskClaimCallback callback, 510 void * callbackContext ) 511{ 512 CFNumberRef _release; 513 CFNumberRef _releaseContext; 514 DAReturn status; 515 516 status = kDAReturnBadArgument; 517 518 if ( disk ) 519 { 520 _release = ___CFNumberCreateWithIntegerValue( kCFAllocatorDefault, ( uintptr_t ) release ); 521 _releaseContext = ___CFNumberCreateWithIntegerValue( kCFAllocatorDefault, ( uintptr_t ) releaseContext ); 522 523 status = __DAQueueRequest( _DADiskGetSession( disk ), _kDADiskClaim, disk, options, _release, _releaseContext, callback, callbackContext ); 524 525 if ( _release ) CFRelease( _release ); 526 if ( _releaseContext ) CFRelease( _releaseContext ); 527 } 528 529 if ( status ) 530 { 531 if ( callback ) 532 { 533 DADissenterRef dissenter; 534 535 dissenter = DADissenterCreate( kCFAllocatorDefault, status, NULL ); 536 537 ( callback )( disk, dissenter, callbackContext ); 538 539 CFRelease( dissenter ); 540 } 541 } 542} 543 544void DADiskEject( DADiskRef disk, DADiskEjectOptions options, DADiskEjectCallback callback, void * context ) 545{ 546 DAReturn status; 547 548 status = kDAReturnBadArgument; 549 550 if ( disk ) 551 { 552 status = _DAAuthorize( _DADiskGetSession( disk ), _kDAAuthorizeOptionIsOwner, disk, _kDAAuthorizeRightUnmount ); 553 554 if ( status == kDAReturnSuccess ) 555 { 556 status = __DAQueueRequest( _DADiskGetSession( disk ), _kDADiskEject, disk, options, NULL, NULL, callback, context ); 557 } 558 } 559 560 if ( status ) 561 { 562 if ( callback ) 563 { 564 DADissenterRef dissenter; 565 566 dissenter = DADissenterCreate( kCFAllocatorDefault, status, NULL ); 567 568 ( callback )( disk, dissenter, context ); 569 570 CFRelease( dissenter ); 571 } 572 } 573} 574 575DADiskOptions DADiskGetOptions( DADiskRef disk ) 576{ 577 int32_t options; 578 579 options = kDADiskOptionDefault; 580 581 if ( disk ) 582 { 583 _DAServerDiskGetOptions( _DADiskGetSessionID( disk ), _DADiskGetID( disk ), &options ); 584 } 585 586 return options; 587} 588 589Boolean DADiskIsClaimed( DADiskRef disk ) 590{ 591 boolean_t claimed; 592 593 claimed = FALSE; 594 595 if ( disk ) 596 { 597 _DAServerDiskIsClaimed( _DADiskGetSessionID( disk ), _DADiskGetID( disk ), &claimed ); 598 } 599 600 return claimed; 601} 602 603void DADiskMount( DADiskRef disk, CFURLRef path, DADiskMountOptions options, DADiskMountCallback callback, void * context ) 604{ 605 DADiskMountWithArguments( disk, path, options, callback, context, NULL ); 606} 607 608void DADiskMountWithArguments( DADiskRef disk, 609 CFURLRef path, 610 DADiskMountOptions options, 611 DADiskMountCallback callback, 612 void * context, 613 CFStringRef arguments[] ) 614{ 615 CFMutableStringRef argument; 616 DAReturn status; 617 618 argument = NULL; 619 620 if ( arguments ) 621 { 622 if ( arguments[0] ) 623 { 624 if ( arguments[1] ) 625 { 626 argument = CFStringCreateMutableCopy( kCFAllocatorDefault, 0, arguments[0] ); 627 628 if ( argument ) 629 { 630 CFIndex index; 631 632 for ( index = 1; arguments[index]; index++ ) 633 { 634 CFStringAppend( argument, CFSTR( "," ) ); 635 CFStringAppend( argument, arguments[index] ); 636 } 637 } 638 } 639 else 640 { 641 argument = ( void * ) CFRetain( arguments[0] ); 642 } 643 } 644 } 645 646 if ( path ) 647 { 648 char * _path; 649 650 _path = ___CFURLCopyFileSystemRepresentation( path ); 651 652 if ( _path ) 653 { 654 char name[MAXPATHLEN]; 655 656 if ( realpath( _path, name ) ) 657 { 658 path = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault, ( void * ) name, strlen( name ), TRUE ); 659 } 660 else 661 { 662 CFRetain( path ); 663 } 664 665 free( _path ); 666 } 667 else 668 { 669 CFRetain( path ); 670 } 671 } 672 673 status = kDAReturnBadArgument; 674 675 if ( disk ) 676 { 677 status = _DAAuthorize( _DADiskGetSession( disk ), _kDAAuthorizeOptionIsOwner, disk, _kDAAuthorizeRightMount ); 678 679 if ( status == kDAReturnSuccess ) 680 { 681 status = __DAQueueRequest( _DADiskGetSession( disk ), _kDADiskMount, disk, options, path ? CFURLGetString( path ) : NULL, argument, callback, context ); 682 } 683 } 684 685 if ( argument ) 686 { 687 CFRelease( argument ); 688 } 689 690 if ( path ) 691 { 692 CFRelease( path ); 693 } 694 695 if ( status ) 696 { 697 if ( callback ) 698 { 699 DADissenterRef dissenter; 700 701 dissenter = DADissenterCreate( kCFAllocatorDefault, status, NULL ); 702 703 ( callback )( disk, dissenter, context ); 704 705 CFRelease( dissenter ); 706 } 707 } 708} 709 710void DADiskRename( DADiskRef disk, CFStringRef name, DADiskRenameOptions options, DADiskRenameCallback callback, void * context ) 711{ 712 DAReturn status; 713 714 status = kDAReturnBadArgument; 715 716 if ( disk ) 717 { 718 if ( name ) 719 { 720 if ( CFGetTypeID( name ) == CFStringGetTypeID( ) ) 721 { 722 status = _DAAuthorize( _DADiskGetSession( disk ), _kDAAuthorizeOptionIsOwner, disk, _kDAAuthorizeRightRename ); 723 724 if ( status == kDAReturnSuccess ) 725 { 726 status = __DAQueueRequest( _DADiskGetSession( disk ), _kDADiskRename, disk, options, name, NULL, callback, context ); 727 } 728 } 729 } 730 } 731 732 if ( status ) 733 { 734 if ( callback ) 735 { 736 DADissenterRef dissenter; 737 738 dissenter = DADissenterCreate( kCFAllocatorDefault, status, NULL ); 739 740 ( callback )( disk, dissenter, context ); 741 742 CFRelease( dissenter ); 743 } 744 } 745} 746 747DAReturn DADiskSetOptions( DADiskRef disk, DADiskOptions options, Boolean value ) 748{ 749 DAReturn status; 750 751 status = kDAReturnBadArgument; 752 753 if ( disk ) 754 { 755 status = _DAServerDiskSetOptions( _DADiskGetSessionID( disk ), _DADiskGetID( disk ), options, value ); 756 } 757 758 return status; 759} 760 761void DADiskUnmount( DADiskRef disk, DADiskUnmountOptions options, DADiskUnmountCallback callback, void * context ) 762{ 763 DAReturn status; 764 765 status = kDAReturnBadArgument; 766 767 if ( disk ) 768 { 769 status = _DAAuthorize( _DADiskGetSession( disk ), _kDAAuthorizeOptionIsOwner, disk, _kDAAuthorizeRightUnmount ); 770 771 if ( status == kDAReturnSuccess ) 772 { 773 status = __DAQueueRequest( _DADiskGetSession( disk ), _kDADiskUnmount, disk, options, NULL, NULL, callback, context ); 774 } 775 } 776 777 if ( status ) 778 { 779 if ( callback ) 780 { 781 DADissenterRef dissenter; 782 783 dissenter = DADissenterCreate( kCFAllocatorDefault, status, NULL ); 784 785 ( callback )( disk, dissenter, context ); 786 787 CFRelease( dissenter ); 788 } 789 } 790} 791 792void DARegisterDiskAppearedCallback( DASessionRef session, 793 CFDictionaryRef match, 794 DADiskAppearedCallback callback, 795 void * context ) 796{ 797 _DARegisterCallback( session, callback, context, _kDADiskAppearedCallback, 0, match, NULL ); 798} 799 800void DARegisterDiskDescriptionChangedCallback( DASessionRef session, 801 CFDictionaryRef match, 802 CFArrayRef watch, 803 DADiskDescriptionChangedCallback callback, 804 void * context ) 805{ 806 _DARegisterCallback( session, callback, context, _kDADiskDescriptionChangedCallback, 0, match, watch ); 807} 808 809void DARegisterDiskDisappearedCallback( DASessionRef session, 810 CFDictionaryRef match, 811 DADiskDisappearedCallback callback, 812 void * context ) 813{ 814 _DARegisterCallback( session, callback, context, _kDADiskDisappearedCallback, 0, match, NULL ); 815} 816 817void DARegisterDiskEjectApprovalCallback( DASessionRef session, 818 CFDictionaryRef match, 819 DADiskEjectApprovalCallback callback, 820 void * context ) 821{ 822 _DARegisterCallback( session, callback, context, _kDADiskEjectApprovalCallback, 0, match, NULL ); 823} 824 825void DARegisterDiskPeekCallback( DASessionRef session, 826 CFDictionaryRef match, 827 CFIndex order, 828 DADiskPeekCallback callback, 829 void * context ) 830{ 831 _DARegisterCallback( session, callback, context, _kDADiskPeekCallback, order, match, NULL ); 832} 833 834void DARegisterDiskMountApprovalCallback( DASessionRef session, 835 CFDictionaryRef match, 836 DADiskMountApprovalCallback callback, 837 void * context ) 838{ 839 _DARegisterCallback( session, callback, context, _kDADiskMountApprovalCallback, 0, match, NULL ); 840} 841 842void DARegisterDiskUnmountApprovalCallback( DASessionRef session, 843 CFDictionaryRef match, 844 DADiskUnmountApprovalCallback callback, 845 void * context ) 846{ 847 _DARegisterCallback( session, callback, context, _kDADiskUnmountApprovalCallback, 0, match, NULL ); 848} 849 850void DADiskUnclaim( DADiskRef disk ) 851{ 852 if ( disk ) 853 { 854 _DAServerDiskUnclaim( _DADiskGetSessionID( disk ), _DADiskGetID( disk ) ); 855 } 856} 857 858void DAUnregisterCallback( DASessionRef session, void * callback, void * context ) 859{ 860 _DAUnregisterCallback( session, callback, context ); 861} 862 863void DAUnregisterApprovalCallback( DASessionRef session, void * callback, void * context ) 864{ 865 _DAUnregisterCallback( session, callback, context ); 866} 867