2  * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ 
   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.  The rights granted to you under the  
  10  * License may not be used to create, or enable the creation or  
  11  * redistribution of, unlawful or unlicensed copies of an Apple operating  
  12  * system, or to circumvent, violate, or enable the circumvention or  
  13  * violation of, any terms of an Apple operating system software license  
  16  * Please obtain a copy of the License at  
  17  * http://www.opensource.apple.com/apsl/ and read it before using this  
  20  * The Original Code and all software distributed under the License are  
  21  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER  
  22  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,  
  23  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,  
  24  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  
  25  * Please see the License for the specific language governing rights and  
  26  * limitations under the License. 
  28  * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ 
  32 #include <IOKit/IOKitServer.h> 
  33 #include <IOKit/IOUserClient.h> 
  34 #include <IOKit/IOService.h> 
  35 #include <IOKit/IOService.h> 
  36 #include <IOKit/IORegistryEntry.h> 
  37 #include <IOKit/IOCatalogue.h> 
  38 #include <IOKit/IOMemoryDescriptor.h> 
  39 #include <IOKit/IOLib.h> 
  41 #include <IOKit/assert.h> 
  43 #include "IOServicePrivate.h" 
  45 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  47 // definitions we should get from osfmk 
  49 //typedef struct ipc_port * ipc_port_t; 
  50 typedef natural_t ipc_kobject_type_t
; 
  52 #define IKOT_IOKIT_SPARE        27 
  53 #define IKOT_IOKIT_CONNECT      29 
  54 #define IKOT_IOKIT_OBJECT       30 
  58 extern ipc_port_t 
iokit_alloc_object_port( io_object_t obj
, 
  59                         ipc_kobject_type_t type 
); 
  61 extern kern_return_t 
iokit_destroy_object_port( ipc_port_t port 
); 
  63 extern mach_port_name_t 
iokit_make_send_right( task_t task
, 
  64                                 io_object_t obj
, ipc_kobject_type_t type 
); 
  66 extern kern_return_t 
iokit_mod_send_right( task_t task
, mach_port_name_t name
, mach_port_delta_t delta 
); 
  68 extern io_object_t 
iokit_lookup_connect_ref(io_object_t clientRef
, ipc_space_t task
); 
  70 extern io_object_t 
iokit_lookup_connect_ref_current_task(io_object_t clientRef
); 
  72 extern ipc_port_t master_device_port
; 
  74 extern void iokit_retain_port( ipc_port_t port 
); 
  75 extern void iokit_release_port( ipc_port_t port 
); 
  77 extern kern_return_t 
iokit_switch_object_port( ipc_port_t port
, io_object_t obj
, ipc_kobject_type_t type 
); 
  79 #include <mach/mach_traps.h> 
  80 #include <vm/vm_map.h> 
  85 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  87 // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject. 
  89 class IOMachPort 
: public OSObject
 
  91     OSDeclareDefaultStructors(IOMachPort
) 
  98     static IOMachPort 
* portForObject( OSObject 
* obj
, 
  99                                 ipc_kobject_type_t type 
); 
 100     static bool noMoreSendersForObject( OSObject 
* obj
, 
 101                                 ipc_kobject_type_t type
, mach_port_mscount_t 
* mscount 
); 
 102     static void releasePortForObject( OSObject 
* obj
, 
 103                                 ipc_kobject_type_t type 
); 
 104     static void setHoldDestroy( OSObject 
* obj
, ipc_kobject_type_t type 
); 
 106     static OSDictionary 
* dictForType( ipc_kobject_type_t type 
); 
 108     static mach_port_name_t 
makeSendRightForTask( task_t task
, 
 109                                 io_object_t obj
, ipc_kobject_type_t type 
); 
 114 #define super OSObject 
 115 OSDefineMetaClassAndStructors(IOMachPort
, OSObject
) 
 117 static IOLock 
*         gIOObjectPortLock
; 
 119 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 121 // not in dictForType() for debugging ease 
 122 static OSDictionary 
*   gIOObjectPorts
; 
 123 static OSDictionary 
*   gIOConnectPorts
; 
 125 OSDictionary 
* IOMachPort::dictForType( ipc_kobject_type_t type 
) 
 127     OSDictionary 
**             dict
; 
 129     if( IKOT_IOKIT_OBJECT 
== type 
) 
 130         dict 
= &gIOObjectPorts
; 
 131     else if( IKOT_IOKIT_CONNECT 
== type 
) 
 132         dict 
= &gIOConnectPorts
; 
 137         *dict 
= OSDictionary::withCapacity( 1 ); 
 142 IOMachPort 
* IOMachPort::portForObject ( OSObject 
* obj
, 
 143                                 ipc_kobject_type_t type 
) 
 145     IOMachPort 
*        inst 
= 0; 
 148     IOTakeLock( gIOObjectPortLock
); 
 152         dict 
= dictForType( type 
); 
 156         if( (inst 
= (IOMachPort 
*) 
 157                 dict
->getObject( (const OSSymbol 
*) obj 
))) { 
 163         inst 
= new IOMachPort
; 
 164         if( inst 
&& !inst
->init()) { 
 169         inst
->port 
= iokit_alloc_object_port( obj
, type 
); 
 172             dict
->setObject( (const OSSymbol 
*) obj
, inst 
); 
 182     IOUnlock( gIOObjectPortLock
); 
 187 bool IOMachPort::noMoreSendersForObject( OSObject 
* obj
, 
 188                                 ipc_kobject_type_t type
, mach_port_mscount_t 
* mscount 
) 
 191     IOMachPort 
*        machPort
; 
 192     bool                destroyed 
= true; 
 194     IOTakeLock( gIOObjectPortLock
); 
 196     if( (dict 
= dictForType( type 
))) { 
 199         machPort 
= (IOMachPort 
*) dict
->getObject( (const OSSymbol 
*) obj 
); 
 201             destroyed 
= (machPort
->mscount 
== *mscount
); 
 203                 dict
->removeObject( (const OSSymbol 
*) obj 
); 
 205                 *mscount 
= machPort
->mscount
; 
 210     IOUnlock( gIOObjectPortLock
); 
 215 void IOMachPort::releasePortForObject( OSObject 
* obj
, 
 216                                 ipc_kobject_type_t type 
) 
 219     IOMachPort 
*        machPort
; 
 221     IOTakeLock( gIOObjectPortLock
); 
 223     if( (dict 
= dictForType( type 
))) { 
 225         machPort 
= (IOMachPort 
*) dict
->getObject( (const OSSymbol 
*) obj 
); 
 226         if( machPort 
&& !machPort
->holdDestroy
) 
 227             dict
->removeObject( (const OSSymbol 
*) obj 
); 
 231     IOUnlock( gIOObjectPortLock
); 
 234 void IOMachPort::setHoldDestroy( OSObject 
* obj
, ipc_kobject_type_t type 
) 
 237     IOMachPort 
*        machPort
; 
 239     IOLockLock( gIOObjectPortLock 
); 
 241     if( (dict 
= dictForType( type 
))) { 
 242         machPort 
= (IOMachPort 
*) dict
->getObject( (const OSSymbol 
*) obj 
); 
 244             machPort
->holdDestroy 
= true; 
 247     IOLockUnlock( gIOObjectPortLock 
); 
 250 void IOUserClient::destroyUserReferences( OSObject 
* obj 
) 
 252     IOMachPort::releasePortForObject( obj
, IKOT_IOKIT_OBJECT 
); 
 255     // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT ); 
 259     IOTakeLock( gIOObjectPortLock
); 
 262     if( (dict 
= IOMachPort::dictForType( IKOT_IOKIT_CONNECT 
))) 
 265         port 
= (IOMachPort 
*) dict
->getObject( (const OSSymbol 
*) obj 
); 
 269             if ((uc 
= OSDynamicCast(IOUserClient
, obj
)) && uc
->mappings
) 
 271                 dict
->setObject((const OSSymbol 
*) uc
->mappings
, port
); 
 272                 iokit_switch_object_port(port
->port
, uc
->mappings
, IKOT_IOKIT_CONNECT
); 
 274                 uc
->mappings
->release(); 
 277             dict
->removeObject( (const OSSymbol 
*) obj 
); 
 281     IOUnlock( gIOObjectPortLock
); 
 284 mach_port_name_t 
IOMachPort::makeSendRightForTask( task_t task
, 
 285                                 io_object_t obj
, ipc_kobject_type_t type 
) 
 287     return( iokit_make_send_right( task
, obj
, type 
)); 
 290 void IOMachPort::free( void ) 
 293         iokit_destroy_object_port( port 
); 
 297 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 299 class IOUserNotification 
: public OSIterator
 
 301     OSDeclareDefaultStructors(IOUserNotification
) 
 303     IONotifier  
*       holdNotify
; 
 308     virtual bool init( void ); 
 311     virtual void setNotification( IONotifier 
* obj 
); 
 313     virtual void reset(); 
 314     virtual bool isValid(); 
 317 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 321 // functions called from osfmk/device/iokit_rpc.c 
 324 iokit_add_reference( io_object_t obj 
) 
 331 iokit_remove_reference( io_object_t obj 
) 
 338 iokit_port_for_object( io_object_t obj
, ipc_kobject_type_t type 
) 
 340     IOMachPort 
* machPort
; 
 343     if( (machPort 
= IOMachPort::portForObject( obj
, type 
))) { 
 345         port 
= machPort
->port
; 
 347             iokit_retain_port( port 
); 
 358 iokit_client_died( io_object_t obj
, ipc_port_t 
/* port */, 
 359                         ipc_kobject_type_t type
, mach_port_mscount_t 
* mscount 
) 
 361     IOUserClient 
*      client
; 
 363     IOUserNotification 
* notify
; 
 365     if( !IOMachPort::noMoreSendersForObject( obj
, type
, mscount 
)) 
 366         return( kIOReturnNotReady 
); 
 368     if( IKOT_IOKIT_CONNECT 
== type
) 
 370         if( (client 
= OSDynamicCast( IOUserClient
, obj 
))) 
 371             client
->clientDied(); 
 373     else if( IKOT_IOKIT_OBJECT 
== type
) 
 375         if( (map 
= OSDynamicCast( IOMemoryMap
, obj 
))) 
 377         else if( (notify 
= OSDynamicCast( IOUserNotification
, obj 
))) 
 378             notify
->setNotification( 0 ); 
 381     return( kIOReturnSuccess 
); 
 386 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 388 class IOServiceUserNotification 
: public IOUserNotification
 
 390     OSDeclareDefaultStructors(IOServiceUserNotification
) 
 393         mach_msg_header_t               msgHdr
; 
 394         OSNotificationHeader            notifyHeader
; 
 397     enum { kMaxOutstanding 
= 1024 }; 
 402     OSObject    
*       lastEntry
; 
 407     virtual bool init( mach_port_t port
, natural_t type
, 
 408                        OSAsyncReference reference 
); 
 411     static bool _handler( void * target
, 
 412                           void * ref
, IOService 
* newService 
); 
 413     virtual bool handler( void * ref
, IOService 
* newService 
); 
 415     virtual OSObject 
* getNextObject(); 
 418 class IOServiceMessageUserNotification 
: public IOUserNotification
 
 420     OSDeclareDefaultStructors(IOServiceMessageUserNotification
) 
 423         mach_msg_header_t               msgHdr
; 
 424         mach_msg_body_t                 msgBody
; 
 425         mach_msg_port_descriptor_t      ports
[1]; 
 426         OSNotificationHeader            notifyHeader
; 
 434     virtual bool init( mach_port_t port
, natural_t type
, 
 435                        OSAsyncReference reference
, vm_size_t extraSize 
); 
 438     static IOReturn 
_handler( void * target
, void * ref
, 
 439                               UInt32 messageType
, IOService 
* provider
, 
 440                               void * messageArgument
, vm_size_t argSize 
); 
 441     virtual IOReturn 
handler( void * ref
, 
 442                               UInt32 messageType
, IOService 
* provider
, 
 443                               void * messageArgument
, vm_size_t argSize 
); 
 445     virtual OSObject 
* getNextObject(); 
 448 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 451 #define super OSIterator 
 452 OSDefineMetaClass( IOUserNotification
, OSIterator 
) 
 453 OSDefineAbstractStructors( IOUserNotification
, OSIterator 
) 
 455 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 457 bool IOUserNotification::init( void ) 
 462     lock 
= IOLockAlloc(); 
 469 void IOUserNotification::free( void ) 
 472         holdNotify
->remove(); 
 473     // can't be in handler now 
 482 void IOUserNotification::setNotification( IONotifier 
* notify 
) 
 484     IONotifier 
* previousNotify
; 
 486     IOLockLock( gIOObjectPortLock
); 
 488     previousNotify 
= holdNotify
; 
 491     IOLockUnlock( gIOObjectPortLock
); 
 494         previousNotify
->remove(); 
 497 void IOUserNotification::reset() 
 502 bool IOUserNotification::isValid() 
 507 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 510 #define super IOUserNotification 
 511 OSDefineMetaClassAndStructors(IOServiceUserNotification
, IOUserNotification
) 
 513 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 515 bool IOServiceUserNotification::init( mach_port_t port
, natural_t type
, 
 516                                 OSAsyncReference reference 
) 
 518     newSet 
= OSArray::withCapacity( 1 ); 
 522     msgSize 
= sizeof( PingMsg
) + 0; 
 523     pingMsg 
= (PingMsg 
*) IOMalloc( msgSize
); 
 527     bzero( pingMsg
, msgSize
); 
 529     pingMsg
->msgHdr
.msgh_remote_port    
= port
; 
 530     pingMsg
->msgHdr
.msgh_bits           
= MACH_MSGH_BITS( 
 531                                             MACH_MSG_TYPE_COPY_SEND 
/*remote*/, 
 532                                             MACH_MSG_TYPE_MAKE_SEND 
/*local*/); 
 533     pingMsg
->msgHdr
.msgh_size           
= msgSize
; 
 534     pingMsg
->msgHdr
.msgh_id             
= kOSNotificationMessageID
; 
 536     pingMsg
->notifyHeader
.size 
= 0; 
 537     pingMsg
->notifyHeader
.type 
= type
; 
 538     bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) ); 
 540     return( super::init() ); 
 543 void IOServiceUserNotification::free( void ) 
 548     OSObject  
* _lastEntry
; 
 552     _lastEntry 
= lastEntry
; 
 557     if( _pingMsg 
&& _msgSize
) 
 558         IOFree( _pingMsg
, _msgSize
); 
 561         _lastEntry
->release(); 
 567 bool IOServiceUserNotification::_handler( void * target
, 
 568                                     void * ref
, IOService 
* newService 
) 
 570     return( ((IOServiceUserNotification 
*) target
)->handler( ref
, newService 
)); 
 573 bool IOServiceUserNotification::handler( void * ref
, 
 574                                 IOService 
* newService 
) 
 578     ipc_port_t          port 
= NULL
; 
 579     bool                sendPing 
= false; 
 583     count 
= newSet
->getCount(); 
 584     if( count 
< kMaxOutstanding
) { 
 586         newSet
->setObject( newService 
); 
 587         if( (sendPing 
= (armed 
&& (0 == count
)))) 
 593     if( kIOServiceTerminatedNotificationType 
== pingMsg
->notifyHeader
.type
) 
 594         IOMachPort::setHoldDestroy( newService
, IKOT_IOKIT_OBJECT 
); 
 597         if( (port 
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT 
) )) 
 598             pingMsg
->msgHdr
.msgh_local_port 
= port
; 
 600             pingMsg
->msgHdr
.msgh_local_port 
= NULL
; 
 602         kr 
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
, 
 603                                         pingMsg
->msgHdr
.msgh_size
); 
 605             iokit_release_port( port 
); 
 607         if( KERN_SUCCESS 
!= kr
) 
 608             IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr 
); 
 614 OSObject 
* IOServiceUserNotification::getNextObject() 
 622         lastEntry
->release(); 
 624     count 
= newSet
->getCount(); 
 626         result 
= newSet
->getObject( count 
- 1 ); 
 628         newSet
->removeObject( count 
- 1); 
 640 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 642 OSDefineMetaClassAndStructors(IOServiceMessageUserNotification
, IOUserNotification
) 
 644 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 646 bool IOServiceMessageUserNotification::init( mach_port_t port
, natural_t type
, 
 647                        OSAsyncReference reference
, vm_size_t extraSize 
) 
 650     extraSize 
+= sizeof(IOServiceInterestContent
); 
 651     msgSize 
= sizeof( PingMsg
) + extraSize
; 
 652     pingMsg 
= (PingMsg 
*) IOMalloc( msgSize
); 
 656     bzero( pingMsg
, msgSize
); 
 658     pingMsg
->msgHdr
.msgh_remote_port    
= port
; 
 659     pingMsg
->msgHdr
.msgh_bits           
= MACH_MSGH_BITS_COMPLEX
 
 661                                             MACH_MSG_TYPE_COPY_SEND 
/*remote*/, 
 662                                             MACH_MSG_TYPE_MAKE_SEND 
/*local*/); 
 663     pingMsg
->msgHdr
.msgh_size           
= msgSize
; 
 664     pingMsg
->msgHdr
.msgh_id             
= kOSNotificationMessageID
; 
 666     pingMsg
->msgBody
.msgh_descriptor_count 
= 1; 
 668     pingMsg
->ports
[0].name              
= 0; 
 669     pingMsg
->ports
[0].disposition       
= MACH_MSG_TYPE_MAKE_SEND
; 
 670     pingMsg
->ports
[0].type              
= MACH_MSG_PORT_DESCRIPTOR
; 
 672     pingMsg
->notifyHeader
.size          
= extraSize
; 
 673     pingMsg
->notifyHeader
.type          
= type
; 
 674     bcopy( reference
, pingMsg
->notifyHeader
.reference
, sizeof(OSAsyncReference
) ); 
 676     return( super::init() ); 
 679 void IOServiceMessageUserNotification::free( void ) 
 689     if( _pingMsg 
&& _msgSize
) 
 690         IOFree( _pingMsg
, _msgSize
); 
 693 IOReturn 
IOServiceMessageUserNotification::_handler( void * target
, void * ref
, 
 694                                             UInt32 messageType
, IOService 
* provider
, 
 695                                             void * argument
, vm_size_t argSize 
) 
 697     return( ((IOServiceMessageUserNotification 
*) target
)->handler( 
 698                                 ref
, messageType
, provider
, argument
, argSize
)); 
 701 IOReturn 
IOServiceMessageUserNotification::handler( void * ref
, 
 702                                     UInt32 messageType
, IOService 
* provider
, 
 703                                     void * messageArgument
, vm_size_t argSize 
) 
 706     ipc_port_t                  thisPort
, providerPort
; 
 707     IOServiceInterestContent 
*  data 
= (IOServiceInterestContent 
*) 
 708                                        pingMsg
->notifyHeader
.content
; 
 710     data
->messageType 
= messageType
; 
 712         argSize 
= sizeof( messageArgument
); 
 713         data
->messageArgument
[0] = messageArgument
; 
 715         if( argSize 
> kIOUserNotifyMaxMessageSize
) 
 716             argSize 
= kIOUserNotifyMaxMessageSize
; 
 717         bcopy( messageArgument
, data
->messageArgument
, argSize 
); 
 719     pingMsg
->msgHdr
.msgh_size 
= sizeof( PingMsg
) 
 720         + sizeof( IOServiceInterestContent 
) 
 721         - sizeof( data
->messageArgument
) 
 724     providerPort 
= iokit_port_for_object( provider
, IKOT_IOKIT_OBJECT 
); 
 725     pingMsg
->ports
[0].name 
= providerPort
; 
 726     thisPort 
= iokit_port_for_object( this, IKOT_IOKIT_OBJECT 
); 
 727     pingMsg
->msgHdr
.msgh_local_port 
= thisPort
; 
 728     kr 
= mach_msg_send_from_kernel( &pingMsg
->msgHdr
, 
 729                                     pingMsg
->msgHdr
.msgh_size
); 
 731         iokit_release_port( thisPort 
); 
 733         iokit_release_port( providerPort 
); 
 735     if( KERN_SUCCESS 
!= kr
) 
 736         IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr 
); 
 738     return( kIOReturnSuccess 
); 
 741 OSObject 
* IOServiceMessageUserNotification::getNextObject() 
 746 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 749 #define super IOService 
 750 OSDefineMetaClassAndAbstractStructors( IOUserClient
, IOService 
) 
 752 void IOUserClient::initialize( void ) 
 754     gIOObjectPortLock 
= IOLockAlloc(); 
 756     assert( gIOObjectPortLock 
); 
 759 void IOUserClient::setAsyncReference(OSAsyncReference asyncRef
, 
 760                                      mach_port_t wakePort
, 
 761                                      void *callback
, void *refcon
) 
 763     asyncRef
[kIOAsyncReservedIndex
] = (natural_t
) wakePort
; 
 764     asyncRef
[kIOAsyncCalloutFuncIndex
] = (natural_t
) callback
; 
 765     asyncRef
[kIOAsyncCalloutRefconIndex
] = (natural_t
) refcon
; 
 768 IOReturn 
IOUserClient::clientHasPrivilege( void * securityToken
, 
 769                                             const char * privilegeName 
) 
 772     security_token_t       token
; 
 773     mach_msg_type_number_t count
; 
 775     count 
= TASK_SECURITY_TOKEN_COUNT
; 
 776     kr 
= task_info( (task_t
) securityToken
, TASK_SECURITY_TOKEN
, 
 777                     (task_info_t
) &token
, &count 
); 
 779     if (KERN_SUCCESS 
!= kr
) 
 781     else if (!strcmp(privilegeName
, kIOClientPrivilegeAdministrator
)) 
 783         if (0 != token
.val
[0]) 
 784             kr 
= kIOReturnNotPrivileged
; 
 786     else if (!strcmp(privilegeName
, kIOClientPrivilegeLocalUser
)) 
 789         OSDictionary 
* user 
= 0; 
 791         if ((array 
= OSDynamicCast(OSArray
, 
 792             IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey
)))) 
 794             for (unsigned int idx 
= 0; 
 795                     (user 
= OSDynamicCast(OSDictionary
, array
->getObject(idx
))); 
 799                 if ((num 
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionUIDKey
))) 
 800                   && (token
.val
[0] == num
->unsigned32BitValue())) 
 806             kr 
= kIOReturnNotPrivileged
; 
 809         kr 
= kIOReturnUnsupported
; 
 814 bool IOUserClient::initWithTask(task_t owningTask
, 
 818     if( getPropertyTable()) 
 821         return super::init(); 
 824 bool IOUserClient::initWithTask(task_t owningTask
, 
 827                                 OSDictionary 
* properties 
) 
 831     ok 
= super::init( properties 
); 
 832     ok 
&= initWithTask( owningTask
, securityID
, type 
); 
 837 void IOUserClient::free() 
 845 IOReturn 
IOUserClient::clientDied( void ) 
 847     return( clientClose()); 
 850 IOReturn 
IOUserClient::clientClose( void ) 
 852     return( kIOReturnUnsupported 
); 
 855 IOService 
* IOUserClient::getService( void ) 
 860 IOReturn 
IOUserClient::registerNotificationPort( 
 861                 mach_port_t     
/* port */, 
 865     return( kIOReturnUnsupported
); 
 868 IOReturn 
IOUserClient::getNotificationSemaphore( UInt32 notification_type
, 
 869                                     semaphore_t 
* semaphore 
) 
 871     return( kIOReturnUnsupported
); 
 874 IOReturn 
IOUserClient::connectClient( IOUserClient 
* /* client */ ) 
 876     return( kIOReturnUnsupported
); 
 879 IOReturn 
IOUserClient::clientMemoryForType( UInt32 type
, 
 880                                 IOOptionBits 
* options
, 
 881                                 IOMemoryDescriptor 
** memory 
) 
 883     return( kIOReturnUnsupported
); 
 886 IOMemoryMap 
* IOUserClient::mapClientMemory(  
 889         IOOptionBits            mapFlags
, 
 890         IOVirtualAddress        atAddress 
) 
 893     IOOptionBits        options 
= 0; 
 894     IOMemoryDescriptor 
* memory
; 
 895     IOMemoryMap 
*       map 
= 0; 
 897     err 
= clientMemoryForType( (UInt32
) type
, &options
, &memory 
); 
 899     if( memory 
&& (kIOReturnSuccess 
== err
)) { 
 901         options 
= (options 
& ~kIOMapUserOptionsMask
) 
 902                 | (mapFlags 
& kIOMapUserOptionsMask
); 
 903         map 
= memory
->map( task
, atAddress
, options 
); 
 910 IOReturn 
IOUserClient::exportObjectToClient(task_t task
, 
 911                         OSObject 
*obj
, io_object_t 
*clientObj
) 
 913     mach_port_name_t    name
; 
 915     name 
= IOMachPort::makeSendRightForTask( task
, obj
, IKOT_IOKIT_OBJECT 
); 
 918     *(mach_port_name_t 
*)clientObj 
= name
; 
 919     return kIOReturnSuccess
; 
 922 IOExternalMethod 
* IOUserClient::getExternalMethodForIndex( UInt32 
/* index */) 
 927 IOExternalAsyncMethod 
* IOUserClient::getExternalAsyncMethodForIndex( UInt32 
/* index */) 
 932 IOExternalMethod 
* IOUserClient:: 
 933 getTargetAndMethodForIndex(IOService 
**targetP
, UInt32 index
) 
 935     IOExternalMethod 
*method 
= getExternalMethodForIndex(index
); 
 938         *targetP 
= (IOService 
*) method
->object
; 
 943 IOExternalAsyncMethod 
* IOUserClient:: 
 944 getAsyncTargetAndMethodForIndex(IOService 
** targetP
, UInt32 index
) 
 946     IOExternalAsyncMethod 
*method 
= getExternalAsyncMethodForIndex(index
); 
 949         *targetP 
= (IOService 
*) method
->object
; 
 954 IOExternalTrap 
* IOUserClient:: 
 955 getExternalTrapForIndex(UInt32 index
) 
 960 IOExternalTrap 
* IOUserClient:: 
 961 getTargetAndTrapForIndex(IOService 
** targetP
, UInt32 index
) 
 963       IOExternalTrap 
*trap 
= getExternalTrapForIndex(index
); 
 966               *targetP 
= trap
->object
; 
 972 IOReturn 
IOUserClient::sendAsyncResult(OSAsyncReference reference
, 
 973                                        IOReturn result
, void *args
[], UInt32 numArgs
) 
 976         mach_msg_header_t       msgHdr
; 
 977         OSNotificationHeader    notifyHdr
; 
 978         IOAsyncCompletionContent asyncContent
; 
 979         void *                  args
[kMaxAsyncArgs
]; 
 982     mach_port_t replyPort
; 
 985     // If no reply port, do nothing. 
 986     replyPort 
= (mach_port_t
) reference
[0]; 
 987     if(replyPort 
== MACH_PORT_NULL
) 
 988         return kIOReturnSuccess
; 
 990     if(numArgs 
> kMaxAsyncArgs
) 
 991         return kIOReturnMessageTooLarge
; 
 992     replyMsg
.msgHdr
.msgh_bits 
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND 
/*remote*/, 
 994     replyMsg
.msgHdr
.msgh_size 
= 
 995         sizeof(replyMsg
) - (kMaxAsyncArgs
-numArgs
)*sizeof(void *); 
 996     replyMsg
.msgHdr
.msgh_remote_port 
= replyPort
; 
 997     replyMsg
.msgHdr
.msgh_local_port 
= 0; 
 998     replyMsg
.msgHdr
.msgh_id 
= kOSNotificationMessageID
; 
1000     replyMsg
.notifyHdr
.size 
= sizeof(IOAsyncCompletionContent
) 
1001                             + numArgs
*sizeof(void *); 
1002     replyMsg
.notifyHdr
.type 
= kIOAsyncCompletionNotificationType
; 
1003     bcopy( reference
, replyMsg
.notifyHdr
.reference
, sizeof(OSAsyncReference
)); 
1005     replyMsg
.asyncContent
.result 
= result
; 
1007         bcopy(args
, replyMsg
.args
, sizeof(void *)*numArgs
); 
1008      kr 
= mach_msg_send_from_kernel( &replyMsg
.msgHdr
, 
1009             replyMsg
.msgHdr
.msgh_size
); 
1010     if( KERN_SUCCESS 
!= kr
) 
1011         IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__
, kr 
); 
1015 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1019 #define CHECK(cls,obj,out)                      \ 
1021         if( !(out = OSDynamicCast( cls, obj)))  \ 
1022             return( kIOReturnBadArgument ) 
1024 /* Routine io_object_get_class */ 
1025 kern_return_t 
is_io_object_get_class( 
1027         io_name_t className 
) 
1029         const OSMetaClass
* my_obj 
= NULL
; 
1032         return( kIOReturnBadArgument 
); 
1034         my_obj 
= object
->getMetaClass(); 
1036                 return (kIOReturnNotFound
); 
1039     strcpy( className
, my_obj
->getClassName()); 
1040     return( kIOReturnSuccess 
); 
1043 /* Routine io_object_get_superclass */ 
1044 kern_return_t 
is_io_object_get_superclass( 
1045         mach_port_t master_port
, 
1047         io_name_t class_name
) 
1049         const OSMetaClass
* my_obj 
= NULL
; 
1050         const OSMetaClass
* superclass 
= NULL
; 
1051         const OSSymbol 
*my_name 
= NULL
; 
1052         const char *my_cstr 
= NULL
; 
1054         if (!obj_name 
|| !class_name
)  
1055                 return (kIOReturnBadArgument
); 
1057     if( master_port 
!= master_device_port
) 
1058         return( kIOReturnNotPrivileged
); 
1060         my_name 
= OSSymbol::withCString(obj_name
); 
1063                 my_obj 
= OSMetaClass::getMetaClassWithName(my_name
); 
1067                 superclass 
= my_obj
->getSuperClass(); 
1071                 return( kIOReturnNotFound 
); 
1074         my_cstr 
= superclass
->getClassName(); 
1077                 strncpy(class_name
, my_cstr
, sizeof(io_name_t
)-1); 
1078                 return( kIOReturnSuccess 
); 
1080         return (kIOReturnNotFound
); 
1083 /* Routine io_object_get_bundle_identifier */ 
1084 kern_return_t 
is_io_object_get_bundle_identifier( 
1085         mach_port_t master_port
, 
1087         io_name_t bundle_name
) 
1089         const OSMetaClass
* my_obj 
= NULL
; 
1090         const OSSymbol 
*my_name 
= NULL
; 
1091         const OSSymbol 
*identifier 
= NULL
; 
1092         const char *my_cstr 
= NULL
; 
1094         if (!obj_name 
|| !bundle_name
)  
1095                 return (kIOReturnBadArgument
); 
1097     if( master_port 
!= master_device_port
) 
1098         return( kIOReturnNotPrivileged
); 
1100         my_name 
= OSSymbol::withCString(obj_name
);       
1103                 my_obj 
= OSMetaClass::getMetaClassWithName(my_name
); 
1108                 identifier 
= my_obj
->getKmodName(); 
1111                 return( kIOReturnNotFound 
); 
1114         my_cstr 
= identifier
->getCStringNoCopy(); 
1116                 strncpy(bundle_name
, identifier
->getCStringNoCopy(), sizeof(io_name_t
)-1); 
1117                 return( kIOReturnSuccess 
); 
1120         return (kIOReturnBadArgument
); 
1123 /* Routine io_object_conforms_to */ 
1124 kern_return_t 
is_io_object_conforms_to( 
1126         io_name_t className
, 
1127         boolean_t 
*conforms 
) 
1130         return( kIOReturnBadArgument 
); 
1132     *conforms 
= (0 != object
->metaCast( className 
)); 
1133     return( kIOReturnSuccess 
); 
1136 /* Routine io_object_get_retain_count */ 
1137 kern_return_t 
is_io_object_get_retain_count( 
1142         return( kIOReturnBadArgument 
); 
1144     *retainCount 
= object
->getRetainCount(); 
1145     return( kIOReturnSuccess 
); 
1148 /* Routine io_iterator_next */ 
1149 kern_return_t 
is_io_iterator_next( 
1150         io_object_t iterator
, 
1151         io_object_t 
*object 
) 
1155     CHECK( OSIterator
, iterator
, iter 
); 
1157     obj 
= iter
->getNextObject(); 
1161         return( kIOReturnSuccess 
); 
1163         return( kIOReturnNoDevice 
); 
1166 /* Routine io_iterator_reset */ 
1167 kern_return_t 
is_io_iterator_reset( 
1168         io_object_t iterator 
) 
1170     CHECK( OSIterator
, iterator
, iter 
); 
1174     return( kIOReturnSuccess 
); 
1177 /* Routine io_iterator_is_valid */ 
1178 kern_return_t 
is_io_iterator_is_valid( 
1179         io_object_t iterator
, 
1180         boolean_t 
*is_valid 
) 
1182     CHECK( OSIterator
, iterator
, iter 
); 
1184     *is_valid 
= iter
->isValid(); 
1186     return( kIOReturnSuccess 
); 
1189 /* Routine io_service_match_property_table */ 
1190 kern_return_t 
is_io_service_match_property_table( 
1191         io_service_t _service
, 
1192         io_string_t matching
, 
1193         boolean_t 
*matches 
) 
1195     CHECK( IOService
, _service
, service 
); 
1199     OSDictionary 
*      dict
; 
1201     obj 
= OSUnserializeXML( matching 
); 
1203     if( (dict 
= OSDynamicCast( OSDictionary
, obj
))) { 
1204         *matches 
= service
->passiveMatch( dict 
); 
1205         kr 
= kIOReturnSuccess
; 
1207         kr 
= kIOReturnBadArgument
; 
1215 /* Routine io_service_match_property_table_ool */ 
1216 kern_return_t 
is_io_service_match_property_table_ool( 
1217         io_object_t service
, 
1218         io_buf_ptr_t matching
, 
1219         mach_msg_type_number_t matchingCnt
, 
1221         boolean_t 
*matches 
) 
1225     vm_map_offset_t     map_data
; 
1227     kr 
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching 
); 
1228     data 
= CAST_DOWN(vm_offset_t
, map_data
); 
1230     if( KERN_SUCCESS 
== kr
) { 
1231         // must return success after vm_map_copyout() succeeds 
1232         *result 
= is_io_service_match_property_table( service
, 
1233                 (char *) data
, matches 
); 
1234         vm_deallocate( kernel_map
, data
, matchingCnt 
); 
1240 /* Routine io_service_get_matching_services */ 
1241 kern_return_t 
is_io_service_get_matching_services( 
1242         mach_port_t master_port
, 
1243         io_string_t matching
, 
1244         io_iterator_t 
*existing 
) 
1248     OSDictionary 
*      dict
; 
1250     if( master_port 
!= master_device_port
) 
1251         return( kIOReturnNotPrivileged
); 
1253     obj 
= OSUnserializeXML( matching 
); 
1255     if( (dict 
= OSDynamicCast( OSDictionary
, obj
))) { 
1256         *existing 
= IOService::getMatchingServices( dict 
); 
1257         kr 
= kIOReturnSuccess
; 
1259         kr 
= kIOReturnBadArgument
; 
1267 /* Routine io_service_get_matching_services_ool */ 
1268 kern_return_t 
is_io_service_get_matching_services_ool( 
1269         mach_port_t master_port
, 
1270         io_buf_ptr_t matching
, 
1271         mach_msg_type_number_t matchingCnt
, 
1273         io_object_t 
*existing 
) 
1277     vm_map_offset_t     map_data
; 
1279     kr 
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching 
); 
1280     data 
= CAST_DOWN(vm_offset_t
, map_data
); 
1282     if( KERN_SUCCESS 
== kr
) { 
1283         // must return success after vm_map_copyout() succeeds 
1284         *result 
= is_io_service_get_matching_services( master_port
, 
1285                         (char *) data
, existing 
); 
1286         vm_deallocate( kernel_map
, data
, matchingCnt 
); 
1292 /* Routine io_service_add_notification */ 
1293 kern_return_t 
is_io_service_add_notification( 
1294         mach_port_t master_port
, 
1295         io_name_t notification_type
, 
1296         io_string_t matching
, 
1298         io_async_ref_t reference
, 
1299         mach_msg_type_number_t referenceCnt
, 
1300         io_object_t 
* notification 
) 
1302     IOServiceUserNotification 
* userNotify 
= 0; 
1303     IONotifier 
*                notify 
= 0; 
1304     const OSSymbol 
*            sym
; 
1305     OSDictionary 
*              dict
; 
1307     unsigned long int           userMsgType
; 
1310     if( master_port 
!= master_device_port
) 
1311         return( kIOReturnNotPrivileged
); 
1314         err 
= kIOReturnNoResources
; 
1316         if( !(sym 
= OSSymbol::withCString( notification_type 
))) 
1317             err 
= kIOReturnNoResources
; 
1319         if( !(dict 
= OSDynamicCast( OSDictionary
, 
1320                     OSUnserializeXML( matching 
)))) { 
1321             err 
= kIOReturnBadArgument
; 
1325         if( (sym 
== gIOPublishNotification
) 
1326          || (sym 
== gIOFirstPublishNotification
)) 
1327             userMsgType 
= kIOServicePublishNotificationType
; 
1328         else if( (sym 
== gIOMatchedNotification
) 
1329               || (sym 
== gIOFirstMatchNotification
)) 
1330             userMsgType 
= kIOServiceMatchedNotificationType
; 
1331         else if( sym 
== gIOTerminatedNotification
) 
1332             userMsgType 
= kIOServiceTerminatedNotificationType
; 
1334             userMsgType 
= kLastIOKitNotificationType
; 
1336         userNotify 
= new IOServiceUserNotification
; 
1338         if( userNotify 
&& !userNotify
->init( port
, userMsgType
, 
1340             userNotify
->release(); 
1346         notify 
= IOService::addNotification( sym
, dict
, 
1347                                              &userNotify
->_handler
, userNotify 
); 
1350             *notification 
= userNotify
; 
1351             userNotify
->setNotification( notify 
); 
1352             err 
= kIOReturnSuccess
; 
1354             err 
= kIOReturnUnsupported
; 
1366 /* Routine io_service_add_notification_ool */ 
1367 kern_return_t 
is_io_service_add_notification_ool( 
1368         mach_port_t master_port
, 
1369         io_name_t notification_type
, 
1370         io_buf_ptr_t matching
, 
1371         mach_msg_type_number_t matchingCnt
, 
1372         mach_port_t wake_port
, 
1373         io_async_ref_t reference
, 
1374         mach_msg_type_number_t referenceCnt
, 
1376         io_object_t 
*notification 
) 
1380     vm_map_offset_t     map_data
; 
1382     kr 
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) matching 
); 
1383     data 
= CAST_DOWN(vm_offset_t
, map_data
); 
1385     if( KERN_SUCCESS 
== kr
) { 
1386         // must return success after vm_map_copyout() succeeds 
1387         *result 
= is_io_service_add_notification( master_port
, notification_type
, 
1388                         (char *) data
, wake_port
, reference
, referenceCnt
, notification 
); 
1389         vm_deallocate( kernel_map
, data
, matchingCnt 
); 
1396 /* Routine io_service_add_notification_old */ 
1397 kern_return_t 
is_io_service_add_notification_old( 
1398         mach_port_t master_port
, 
1399         io_name_t notification_type
, 
1400         io_string_t matching
, 
1403         io_object_t 
* notification 
) 
1405     return( is_io_service_add_notification( master_port
, notification_type
, 
1406             matching
, port
, &ref
, 1, notification 
)); 
1409 /* Routine io_service_add_message_notification */ 
1410 kern_return_t 
is_io_service_add_interest_notification( 
1411         io_object_t _service
, 
1412         io_name_t type_of_interest
, 
1414         io_async_ref_t reference
, 
1415         mach_msg_type_number_t referenceCnt
, 
1416         io_object_t 
* notification 
) 
1419     IOServiceMessageUserNotification 
*  userNotify 
= 0; 
1420     IONotifier 
*                        notify 
= 0; 
1421     const OSSymbol 
*                    sym
; 
1424     CHECK( IOService
, _service
, service 
); 
1426     err 
= kIOReturnNoResources
; 
1427     if( (sym 
= OSSymbol::withCString( type_of_interest 
))) do { 
1429         userNotify 
= new IOServiceMessageUserNotification
; 
1431         if( userNotify 
&& !userNotify
->init( port
, kIOServiceMessageNotificationType
, 
1432                                              reference
, kIOUserNotifyMaxMessageSize 
)) { 
1433             userNotify
->release(); 
1439         notify 
= service
->registerInterest( sym
, 
1440                                     &userNotify
->_handler
, userNotify 
); 
1442             *notification 
= userNotify
; 
1443             userNotify
->setNotification( notify 
); 
1444             err 
= kIOReturnSuccess
; 
1446             err 
= kIOReturnUnsupported
; 
1455 /* Routine io_service_acknowledge_notification */ 
1456 kern_return_t 
is_io_service_acknowledge_notification( 
1457         io_object_t _service
, 
1458         natural_t notify_ref
, 
1459         natural_t response 
) 
1461     CHECK( IOService
, _service
, service 
); 
1463     return( service
->acknowledgeNotification( (IONotificationRef
) notify_ref
, 
1464                                               (IOOptionBits
) response 
)); 
1468 /* Routine io_connect_get_semaphore */ 
1469 kern_return_t 
is_io_connect_get_notification_semaphore( 
1470         io_connect_t connection
, 
1471         natural_t notification_type
, 
1472         semaphore_t 
*semaphore 
) 
1474     CHECK( IOUserClient
, connection
, client 
); 
1476     return( client
->getNotificationSemaphore( (UInt32
) notification_type
, 
1480 /* Routine io_registry_get_root_entry */ 
1481 kern_return_t 
is_io_registry_get_root_entry( 
1482         mach_port_t master_port
, 
1485     IORegistryEntry 
*   entry
; 
1487     if( master_port 
!= master_device_port
) 
1488         return( kIOReturnNotPrivileged
); 
1490     entry 
= IORegistryEntry::getRegistryRoot(); 
1495     return( kIOReturnSuccess 
); 
1498 /* Routine io_registry_create_iterator */ 
1499 kern_return_t 
is_io_registry_create_iterator( 
1500         mach_port_t master_port
, 
1503         io_object_t 
*iterator 
) 
1505     if( master_port 
!= master_device_port
) 
1506         return( kIOReturnNotPrivileged
); 
1508     *iterator 
= IORegistryIterator::iterateOver( 
1509         IORegistryEntry::getPlane( plane 
), options 
); 
1511     return( *iterator 
? kIOReturnSuccess 
: kIOReturnBadArgument 
); 
1514 /* Routine io_registry_entry_create_iterator */ 
1515 kern_return_t 
is_io_registry_entry_create_iterator( 
1516         io_object_t registry_entry
, 
1519         io_object_t 
*iterator 
) 
1521     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1523     *iterator 
= IORegistryIterator::iterateOver( entry
, 
1524         IORegistryEntry::getPlane( plane 
), options 
); 
1526     return( *iterator 
? kIOReturnSuccess 
: kIOReturnBadArgument 
); 
1529 /* Routine io_registry_iterator_enter */ 
1530 kern_return_t 
is_io_registry_iterator_enter_entry( 
1531         io_object_t iterator 
) 
1533     CHECK( IORegistryIterator
, iterator
, iter 
); 
1537     return( kIOReturnSuccess 
); 
1540 /* Routine io_registry_iterator_exit */ 
1541 kern_return_t 
is_io_registry_iterator_exit_entry( 
1542         io_object_t iterator 
) 
1546     CHECK( IORegistryIterator
, iterator
, iter 
); 
1548     didIt 
= iter
->exitEntry(); 
1550     return( didIt 
? kIOReturnSuccess 
: kIOReturnNoDevice 
); 
1553 /* Routine io_registry_entry_from_path */ 
1554 kern_return_t 
is_io_registry_entry_from_path( 
1555         mach_port_t master_port
, 
1557         io_object_t 
*registry_entry 
) 
1559     IORegistryEntry 
*   entry
; 
1561     if( master_port 
!= master_device_port
) 
1562         return( kIOReturnNotPrivileged
); 
1564     entry 
= IORegistryEntry::fromPath( path 
); 
1566     *registry_entry 
= entry
; 
1568     return( kIOReturnSuccess 
); 
1571 /* Routine io_registry_entry_in_plane */ 
1572 kern_return_t 
is_io_registry_entry_in_plane( 
1573         io_object_t registry_entry
, 
1575         boolean_t 
*inPlane 
) 
1577     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1579     *inPlane 
= entry
->inPlane( IORegistryEntry::getPlane( plane 
)); 
1581     return( kIOReturnSuccess 
); 
1585 /* Routine io_registry_entry_get_path */ 
1586 kern_return_t 
is_io_registry_entry_get_path( 
1587         io_object_t registry_entry
, 
1592     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1594     length 
= sizeof( io_string_t
); 
1595     if( entry
->getPath( path
, &length
, IORegistryEntry::getPlane( plane 
))) 
1596         return( kIOReturnSuccess 
); 
1598         return( kIOReturnBadArgument 
); 
1602 /* Routine io_registry_entry_get_name */ 
1603 kern_return_t 
is_io_registry_entry_get_name( 
1604         io_object_t registry_entry
, 
1607     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1609     strncpy( name
, entry
->getName(), sizeof( io_name_t
)); 
1611     return( kIOReturnSuccess 
); 
1614 /* Routine io_registry_entry_get_name_in_plane */ 
1615 kern_return_t 
is_io_registry_entry_get_name_in_plane( 
1616         io_object_t registry_entry
, 
1617         io_name_t planeName
, 
1620     const IORegistryPlane 
* plane
; 
1621     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1624         plane 
= IORegistryEntry::getPlane( planeName 
); 
1628     strncpy( name
, entry
->getName( plane
), sizeof( io_name_t
)); 
1630     return( kIOReturnSuccess 
); 
1633 /* Routine io_registry_entry_get_location_in_plane */ 
1634 kern_return_t 
is_io_registry_entry_get_location_in_plane( 
1635         io_object_t registry_entry
, 
1636         io_name_t planeName
, 
1637         io_name_t location 
) 
1639     const IORegistryPlane 
* plane
; 
1640     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1643         plane 
= IORegistryEntry::getPlane( planeName 
); 
1647     const char * cstr 
= entry
->getLocation( plane 
); 
1650         strncpy( location
, cstr
, sizeof( io_name_t
)); 
1651         return( kIOReturnSuccess 
); 
1653         return( kIOReturnNotFound 
); 
1656 // Create a vm_map_copy_t or kalloc'ed data for memory 
1657 // to be copied out. ipc will free after the copyout. 
1659 static kern_return_t 
copyoutkdata( void * data
, vm_size_t len
, 
1660                                     io_buf_ptr_t 
* buf 
) 
1665     err 
= vm_map_copyin( kernel_map
, CAST_USER_ADDR_T(data
), len
, 
1666                     false /* src_destroy */, ©
); 
1668     assert( err 
== KERN_SUCCESS 
); 
1669     if( err 
== KERN_SUCCESS 
) 
1670         *buf 
= (char *) copy
; 
1675 /* Routine io_registry_entry_get_property */ 
1676 kern_return_t 
is_io_registry_entry_get_property_bytes( 
1677         io_object_t registry_entry
, 
1678         io_name_t property_name
, 
1679         io_scalar_inband_t buf
, 
1680         mach_msg_type_number_t 
*dataCnt 
) 
1688     unsigned int        len 
= 0; 
1689     const void *        bytes 
= 0; 
1690     IOReturn            ret 
= kIOReturnSuccess
; 
1692     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1694     obj 
= entry
->copyProperty(property_name
); 
1696         return( kIOReturnNoResources 
); 
1698     // One day OSData will be a common container base class 
1700     if( (data 
= OSDynamicCast( OSData
, obj 
))) { 
1701         len 
= data
->getLength(); 
1702         bytes 
= data
->getBytesNoCopy(); 
1704     } else if( (str 
= OSDynamicCast( OSString
, obj 
))) { 
1705         len 
= str
->getLength() + 1; 
1706         bytes 
= str
->getCStringNoCopy(); 
1708     } else if( (boo 
= OSDynamicCast( OSBoolean
, obj 
))) { 
1709         len 
= boo
->isTrue() ? sizeof("Yes") : sizeof("No"); 
1710         bytes 
= boo
->isTrue() ? "Yes" : "No"; 
1712     } else if( (off 
= OSDynamicCast( OSNumber
, obj 
))) { 
1713         offsetBytes 
= off
->unsigned64BitValue(); 
1714         len 
= off
->numberOfBytes(); 
1715         bytes 
= &offsetBytes
; 
1716 #ifdef __BIG_ENDIAN__ 
1717         bytes 
= (const void *) 
1718                 (((UInt32
) bytes
) + (sizeof( UInt64
) - len
)); 
1722         ret 
= kIOReturnBadArgument
; 
1726             ret 
= kIOReturnIPCError
; 
1729             bcopy( bytes
, buf
, len 
); 
1737 /* Routine io_registry_entry_get_property */ 
1738 kern_return_t 
is_io_registry_entry_get_property( 
1739         io_object_t registry_entry
, 
1740         io_name_t property_name
, 
1741         io_buf_ptr_t 
*properties
, 
1742         mach_msg_type_number_t 
*propertiesCnt 
) 
1748     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1750     obj 
= entry
->copyProperty(property_name
); 
1752         return( kIOReturnNotFound 
); 
1754     OSSerialize 
* s 
= OSSerialize::withCapacity(4096); 
1757         return( kIOReturnNoMemory 
); 
1761     if( obj
->serialize( s 
)) { 
1762         len 
= s
->getLength(); 
1763         *propertiesCnt 
= len
; 
1764         err 
= copyoutkdata( s
->text(), len
, properties 
); 
1767         err 
= kIOReturnUnsupported
; 
1775 /* Routine io_registry_entry_get_property_recursively */ 
1776 kern_return_t 
is_io_registry_entry_get_property_recursively( 
1777         io_object_t registry_entry
, 
1779         io_name_t property_name
, 
1781         io_buf_ptr_t 
*properties
, 
1782         mach_msg_type_number_t 
*propertiesCnt 
) 
1788     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1790     obj 
= entry
->copyProperty( property_name
, 
1791                                IORegistryEntry::getPlane( plane 
), options
); 
1793         return( kIOReturnNotFound 
); 
1795     OSSerialize 
* s 
= OSSerialize::withCapacity(4096); 
1798         return( kIOReturnNoMemory 
); 
1803     if( obj
->serialize( s 
)) { 
1804         len 
= s
->getLength(); 
1805         *propertiesCnt 
= len
; 
1806         err 
= copyoutkdata( s
->text(), len
, properties 
); 
1809         err 
= kIOReturnUnsupported
; 
1817 /* Routine io_registry_entry_get_properties */ 
1818 kern_return_t 
is_io_registry_entry_get_properties( 
1819         io_object_t registry_entry
, 
1820         io_buf_ptr_t 
*properties
, 
1821         mach_msg_type_number_t 
*propertiesCnt 
) 
1826     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1828     OSSerialize 
* s 
= OSSerialize::withCapacity(4096); 
1830         return( kIOReturnNoMemory 
); 
1834     if( entry
->serializeProperties( s 
)) { 
1835         len 
= s
->getLength(); 
1836         *propertiesCnt 
= len
; 
1837         err 
= copyoutkdata( s
->text(), len
, properties 
); 
1840         err 
= kIOReturnUnsupported
; 
1847 /* Routine io_registry_entry_set_properties */ 
1848 kern_return_t is_io_registry_entry_set_properties
 
1850         io_object_t registry_entry
, 
1851         io_buf_ptr_t properties
, 
1852         mach_msg_type_number_t propertiesCnt
, 
1859     vm_map_offset_t     map_data
; 
1861     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1863     err 
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
) properties 
); 
1864     data 
= CAST_DOWN(vm_offset_t
, map_data
); 
1866     if( KERN_SUCCESS 
== err
) { 
1868         // must return success after vm_map_copyout() succeeds 
1869         obj 
= OSUnserializeXML( (const char *) data 
); 
1870         vm_deallocate( kernel_map
, data
, propertiesCnt 
); 
1873             res 
= entry
->setProperties( obj 
); 
1876             res 
= kIOReturnBadArgument
; 
1884 /* Routine io_registry_entry_get_child_iterator */ 
1885 kern_return_t 
is_io_registry_entry_get_child_iterator( 
1886         io_object_t registry_entry
, 
1888         io_object_t 
*iterator 
) 
1890     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1892     *iterator 
= entry
->getChildIterator( 
1893         IORegistryEntry::getPlane( plane 
)); 
1895     return( kIOReturnSuccess 
); 
1898 /* Routine io_registry_entry_get_parent_iterator */ 
1899 kern_return_t 
is_io_registry_entry_get_parent_iterator( 
1900         io_object_t registry_entry
, 
1902         io_object_t 
*iterator
) 
1904     CHECK( IORegistryEntry
, registry_entry
, entry 
); 
1906     *iterator 
= entry
->getParentIterator( 
1907         IORegistryEntry::getPlane( plane 
)); 
1909     return( kIOReturnSuccess 
); 
1912 /* Routine io_service_get_busy_state */ 
1913 kern_return_t 
is_io_service_get_busy_state( 
1914         io_object_t _service
, 
1917     CHECK( IOService
, _service
, service 
); 
1919     *busyState 
= service
->getBusyState(); 
1921     return( kIOReturnSuccess 
); 
1924 /* Routine io_service_get_state */ 
1925 kern_return_t 
is_io_service_get_state( 
1926         io_object_t _service
, 
1929     CHECK( IOService
, _service
, service 
); 
1931     *state 
= service
->getState(); 
1933     return( kIOReturnSuccess 
); 
1936 /* Routine io_service_wait_quiet */ 
1937 kern_return_t 
is_io_service_wait_quiet( 
1938         io_object_t _service
, 
1939         mach_timespec_t wait_time 
) 
1941     CHECK( IOService
, _service
, service 
); 
1943     return( service
->waitQuiet( &wait_time 
)); 
1946 /* Routine io_service_request_probe */ 
1947 kern_return_t 
is_io_service_request_probe( 
1948         io_object_t _service
, 
1951     CHECK( IOService
, _service
, service 
); 
1953     return( service
->requestProbe( options 
)); 
1957 /* Routine io_service_open */ 
1958 kern_return_t 
is_io_service_open( 
1959         io_object_t _service
, 
1962         io_object_t 
*connection 
) 
1964     IOUserClient        
*       client
; 
1967     CHECK( IOService
, _service
, service 
); 
1969     err 
= service
->newUserClient( owningTask
, (void *) owningTask
, 
1970                 connect_type
, &client 
); 
1972     if( err 
== kIOReturnSuccess
) { 
1973         assert( OSDynamicCast(IOUserClient
, client
) ); 
1974         *connection 
= client
; 
1980 /* Routine io_service_close */ 
1981 kern_return_t 
is_io_service_close( 
1982         io_object_t connection 
) 
1985     if ((mappings 
= OSDynamicCast(OSSet
, connection
))) 
1986         return( kIOReturnSuccess 
); 
1988     CHECK( IOUserClient
, connection
, client 
); 
1990     client
->clientClose(); 
1992     return( kIOReturnSuccess 
); 
1995 /* Routine io_connect_get_service */ 
1996 kern_return_t 
is_io_connect_get_service( 
1997         io_object_t connection
, 
1998         io_object_t 
*service 
) 
2000     IOService 
* theService
; 
2002     CHECK( IOUserClient
, connection
, client 
); 
2004     theService 
= client
->getService(); 
2006         theService
->retain(); 
2008     *service 
= theService
; 
2010     return( theService 
? kIOReturnSuccess 
: kIOReturnUnsupported 
); 
2013 /* Routine io_connect_set_notification_port */ 
2014 kern_return_t 
is_io_connect_set_notification_port( 
2015         io_object_t connection
, 
2016         int notification_type
, 
2020     CHECK( IOUserClient
, connection
, client 
); 
2022     return( client
->registerNotificationPort( port
, notification_type
, 
2026 kern_return_t 
is_io_connect_map_memory( 
2027         io_object_t     connect
, 
2030         vm_address_t 
*  mapAddr
, 
2031         vm_size_t    
*  mapSize
, 
2037     CHECK( IOUserClient
, connect
, client 
); 
2039     map 
= client
->mapClientMemory( type
, task
, flags
, *mapAddr 
); 
2042         *mapAddr 
= map
->getVirtualAddress(); 
2044             *mapSize 
= map
->getLength(); 
2046         if( task 
!= current_task()) { 
2047             // push a name out to the task owning the map, 
2048             // so we can clean up maps 
2050             mach_port_name_t name 
= 
2052             IOMachPort::makeSendRightForTask( 
2053                                     task
, map
, IKOT_IOKIT_OBJECT 
); 
2057             // keep it with the user client 
2058             IOLockLock( gIOObjectPortLock
); 
2059             if( 0 == client
->mappings
) 
2060                 client
->mappings 
= OSSet::withCapacity(2); 
2061             if( client
->mappings
) 
2062                 client
->mappings
->setObject( map
); 
2063             IOLockUnlock( gIOObjectPortLock
); 
2066         err 
= kIOReturnSuccess
; 
2069         err 
= kIOReturnBadArgument
; 
2074 IOMemoryMap 
* IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor 
* mem
) 
2077     IOMemoryMap 
* map 
= 0; 
2079     IOLockLock(gIOObjectPortLock
); 
2081     iter 
= OSCollectionIterator::withCollection(mappings
); 
2084         while ((map 
= OSDynamicCast(IOMemoryMap
, iter
->getNextObject()))) 
2086             if(mem 
== map
->getMemoryDescriptor()) 
2089                 mappings
->removeObject(map
); 
2096     IOLockUnlock(gIOObjectPortLock
); 
2101 kern_return_t 
is_io_connect_unmap_memory( 
2102         io_object_t     connect
, 
2105         vm_address_t    mapAddr 
) 
2108     IOOptionBits        options 
= 0; 
2109     IOMemoryDescriptor 
* memory
; 
2112     CHECK( IOUserClient
, connect
, client 
); 
2114     err 
= client
->clientMemoryForType( (UInt32
) type
, &options
, &memory 
); 
2116     if( memory 
&& (kIOReturnSuccess 
== err
)) { 
2118         options 
= (options 
& ~kIOMapUserOptionsMask
) 
2119                 | kIOMapAnywhere 
| kIOMapReference
; 
2121         map 
= memory
->map( task
, mapAddr
, options 
); 
2125             IOLockLock( gIOObjectPortLock
); 
2126             if( client
->mappings
) 
2127                 client
->mappings
->removeObject( map
); 
2128             IOLockUnlock( gIOObjectPortLock
); 
2130             mach_port_name_t name 
= 0; 
2131             if (task 
!= current_task()) 
2132                 name 
= IOMachPort::makeSendRightForTask( task
, map
, IKOT_IOKIT_OBJECT 
); 
2136                 err 
= iokit_mod_send_right( task
, name
, -2 ); 
2137                 err 
= kIOReturnSuccess
; 
2140                 IOMachPort::releasePortForObject( map
, IKOT_IOKIT_OBJECT 
); 
2141             if (task 
== current_task()) 
2145             err 
= kIOReturnBadArgument
; 
2152 /* Routine io_connect_add_client */ 
2153 kern_return_t 
is_io_connect_add_client( 
2154         io_object_t connection
, 
2155         io_object_t connect_to
) 
2157     CHECK( IOUserClient
, connection
, client 
); 
2158     CHECK( IOUserClient
, connect_to
, to 
); 
2160     return( client
->connectClient( to 
) ); 
2164 /* Routine io_connect_set_properties */ 
2165 kern_return_t 
is_io_connect_set_properties( 
2166         io_object_t connection
, 
2167         io_buf_ptr_t properties
, 
2168         mach_msg_type_number_t propertiesCnt
, 
2171     return( is_io_registry_entry_set_properties( connection
, properties
, propertiesCnt
, result 
)); 
2175 /* Routine io_connect_method_scalarI_scalarO */ 
2176 kern_return_t 
is_io_connect_method_scalarI_scalarO( 
2177         io_object_t     connect
, 
2180         IOByteCount     inputCount
, 
2182         IOByteCount 
*   outputCount 
) 
2185     IOExternalMethod 
*  method
; 
2189     CHECK( IOUserClient
, connect
, client
); 
2190     if( (method 
= client
->getTargetAndMethodForIndex(&object
, index
))) { 
2192         err 
= kIOReturnBadArgument
; 
2193         if( kIOUCScalarIScalarO 
!= (method
->flags 
& kIOUCTypeMask
)) 
2195         if( inputCount 
!= method
->count0
) 
2197         if( *outputCount 
!= method
->count1
) 
2200         func 
= method
->func
; 
2202         switch( inputCount
) { 
2205                 err 
= (object
->*func
)(  input
[0], input
[1], input
[2], 
2206                                         input
[3], input
[4], input
[5] ); 
2209                 err 
= (object
->*func
)(  input
[0], input
[1], input
[2], 
2214                 err 
= (object
->*func
)(  input
[0], input
[1], input
[2], 
2216                                         &output
[0], &output
[1] ); 
2219                 err 
= (object
->*func
)(  input
[0], input
[1], input
[2], 
2220                                         &output
[0], &output
[1], &output
[2] ); 
2223                 err 
= (object
->*func
)(  input
[0], input
[1], 
2224                                         &output
[0], &output
[1], &output
[2], 
2228                 err 
= (object
->*func
)(  input
[0], 
2229                                         &output
[0], &output
[1], &output
[2], 
2230                                         &output
[3], &output
[4] ); 
2233                 err 
= (object
->*func
)(  &output
[0], &output
[1], &output
[2], 
2234                                         &output
[3], &output
[4], &output
[5] ); 
2238                 IOLog("%s: Bad method table\n", client
->getName()); 
2243         err 
= kIOReturnUnsupported
; 
2248 /* Routine io_connect_method_scalarI_structureO */ 
2249 kern_return_t 
is_io_connect_method_scalarI_structureO( 
2250         io_object_t     connect
, 
2253         IOByteCount     inputCount
, 
2255         IOByteCount 
*   outputCount 
) 
2258     IOExternalMethod 
*  method
; 
2262     CHECK( IOUserClient
, connect
, client
); 
2264     if( (method 
= client
->getTargetAndMethodForIndex(&object
, index
)) ) { 
2266         err 
= kIOReturnBadArgument
; 
2267         if( kIOUCScalarIStructO 
!= (method
->flags 
& kIOUCTypeMask
)) 
2269         if( inputCount 
!= method
->count0
) 
2271         if( (0xffffffff != method
->count1
) 
2272                 && (*outputCount 
!= method
->count1
)) 
2275         func 
= method
->func
; 
2277         switch( inputCount
) { 
2280                 err 
= (object
->*func
)(  input
[0], input
[1], input
[2], 
2285                 err 
= (object
->*func
)(  input
[0], input
[1], input
[2], 
2287                                         output
, (void *)outputCount 
); 
2290                 err 
= (object
->*func
)(  input
[0], input
[1], input
[2], 
2291                                         output
, (void *)outputCount
, 0 ); 
2294                 err 
= (object
->*func
)(  input
[0], input
[1], 
2295                                         output
, (void *)outputCount
, 0, 0 ); 
2298                 err 
= (object
->*func
)(  input
[0], 
2299                                         output
, (void *)outputCount
, 0, 0, 0 ); 
2302                 err 
= (object
->*func
)(  output
, (void *)outputCount
, 0, 0, 0, 0 ); 
2306                 IOLog("%s: Bad method table\n", client
->getName()); 
2311         err 
= kIOReturnUnsupported
; 
2316 /* Routine io_connect_method_scalarI_structureI */ 
2317 kern_return_t 
is_io_connect_method_scalarI_structureI( 
2318         io_connect_t    connect
, 
2321         IOByteCount     inputCount
, 
2322         UInt8 
*         inputStruct
, 
2323         IOByteCount     inputStructCount 
) 
2326     IOExternalMethod 
*  method
; 
2330     CHECK( IOUserClient
, connect
, client
); 
2332     if( (method 
= client
->getTargetAndMethodForIndex(&object
, index
)) ) { 
2334         err 
= kIOReturnBadArgument
; 
2335         if( kIOUCScalarIStructI 
!= (method
->flags 
& kIOUCTypeMask
)) 
2337         if( (0xffffffff != method
->count0
) 
2338                 && (inputCount 
!= method
->count0
)) 
2340         if( (0xffffffff != method
->count1
) 
2341                 && (inputStructCount 
!= method
->count1
)) 
2344         func 
= method
->func
; 
2346         switch( inputCount
) { 
2349                 err 
= (object
->*func
)( input
[0], input
[1], input
[2], 
2354                 err 
= (object
->*func
)( input
[0], input
[1], input
[2], 
2356                                         inputStruct
, (void *)inputStructCount 
); 
2359                 err 
= (object
->*func
)( input
[0], input
[1], input
[2], 
2360                                         inputStruct
, (void *)inputStructCount
, 
2364                 err 
= (object
->*func
)( input
[0], input
[1], 
2365                                         inputStruct
, (void *)inputStructCount
, 
2369                 err 
= (object
->*func
)( input
[0], 
2370                                         inputStruct
, (void *)inputStructCount
, 
2374                 err 
= (object
->*func
)( inputStruct
, (void *)inputStructCount
, 
2379                 IOLog("%s: Bad method table\n", client
->getName()); 
2384         err 
= kIOReturnUnsupported
; 
2389 /* Routine io_connect_method_structureI_structureO */ 
2390 kern_return_t 
is_io_connect_method_structureI_structureO( 
2391         io_object_t     connect
, 
2394         IOByteCount     inputCount
, 
2396         IOByteCount 
*   outputCount 
) 
2399     IOExternalMethod 
*  method
; 
2403     CHECK( IOUserClient
, connect
, client
); 
2405     if( (method 
= client
->getTargetAndMethodForIndex(&object
, index
)) ) { 
2407         err 
= kIOReturnBadArgument
; 
2408         if( kIOUCStructIStructO 
!= (method
->flags 
& kIOUCTypeMask
)) 
2410         if( (0xffffffff != method
->count0
) 
2411                 && (inputCount 
!= method
->count0
)) 
2413         if( (0xffffffff != method
->count1
) 
2414                 && (*outputCount 
!= method
->count1
)) 
2417         func 
= method
->func
; 
2419         if( method
->count1
) { 
2420             if( method
->count0
) { 
2421                 err 
= (object
->*func
)( input
, output
, 
2422                                         (void *)inputCount
, outputCount
, 0, 0 ); 
2424                 err 
= (object
->*func
)( output
, outputCount
, 0, 0, 0, 0 ); 
2427                 err 
= (object
->*func
)( input
, (void *)inputCount
, 0, 0, 0, 0 ); 
2433         err 
= kIOReturnUnsupported
; 
2438 kern_return_t 
is_io_async_method_scalarI_scalarO( 
2439         io_object_t     connect
, 
2440         mach_port_t     wakePort
, 
2441         io_async_ref_t          reference
, 
2442         mach_msg_type_number_t  referenceCnt
, 
2445         IOByteCount     inputCount
, 
2447         IOByteCount 
*   outputCount 
) 
2450     IOExternalAsyncMethod 
*method
; 
2454     CHECK( IOUserClient
, connect
, client
); 
2455     if( (method 
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) { 
2457         err 
= kIOReturnBadArgument
; 
2458         if( kIOUCScalarIScalarO 
!= (method
->flags 
& kIOUCTypeMask
)) 
2460         if( inputCount 
!= method
->count0
) 
2462         if( *outputCount 
!= method
->count1
) 
2465         reference
[0] = (natural_t
) wakePort
; 
2466         func 
= method
->func
; 
2468         switch( inputCount
) { 
2471                 err 
= (object
->*func
)(  reference
, 
2472                                         input
[0], input
[1], input
[2], 
2473                                         input
[3], input
[4], input
[5] ); 
2476                 err 
= (object
->*func
)(  reference
, 
2477                                         input
[0], input
[1], input
[2], 
2482                 err 
= (object
->*func
)(  reference
, 
2483                                         input
[0], input
[1], input
[2], 
2485                                         &output
[0], &output
[1] ); 
2488                 err 
= (object
->*func
)(  reference
, 
2489                                         input
[0], input
[1], input
[2], 
2490                                         &output
[0], &output
[1], &output
[2] ); 
2493                 err 
= (object
->*func
)(  reference
, 
2495                                         &output
[0], &output
[1], &output
[2], 
2499                 err 
= (object
->*func
)(  reference
, 
2501                                         &output
[0], &output
[1], &output
[2], 
2502                                         &output
[3], &output
[4] ); 
2505                 err 
= (object
->*func
)(  reference
, 
2506                                         &output
[0], &output
[1], &output
[2], 
2507                                         &output
[3], &output
[4], &output
[5] ); 
2511                 IOLog("%s: Bad method table\n", client
->getName()); 
2516         err 
= kIOReturnUnsupported
; 
2521 kern_return_t 
is_io_async_method_scalarI_structureO( 
2522         io_object_t     connect
, 
2523         mach_port_t     wakePort
, 
2524         io_async_ref_t          reference
, 
2525         mach_msg_type_number_t  referenceCnt
, 
2528         IOByteCount     inputCount
, 
2530         IOByteCount 
*   outputCount 
) 
2533     IOExternalAsyncMethod 
*method
; 
2537     CHECK( IOUserClient
, connect
, client
); 
2539     if( (method 
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) { 
2541         err 
= kIOReturnBadArgument
; 
2542         if( kIOUCScalarIStructO 
!= (method
->flags 
& kIOUCTypeMask
)) 
2544         if( inputCount 
!= method
->count0
) 
2546         if( (0xffffffff != method
->count1
) 
2547                 && (*outputCount 
!= method
->count1
)) 
2550         reference
[0] = (natural_t
) wakePort
; 
2551         func 
= method
->func
; 
2553         switch( inputCount
) { 
2556                 err 
= (object
->*func
)(  reference
, 
2557                                         input
[0], input
[1], input
[2], 
2562                 err 
= (object
->*func
)(  reference
, 
2563                                         input
[0], input
[1], input
[2], 
2565                                         output
, (void *)outputCount 
); 
2568                 err 
= (object
->*func
)(  reference
, 
2569                                         input
[0], input
[1], input
[2], 
2570                                         output
, (void *)outputCount
, 0 ); 
2573                 err 
= (object
->*func
)(  reference
, 
2575                                         output
, (void *)outputCount
, 0, 0 ); 
2578                 err 
= (object
->*func
)(  reference
, 
2580                                         output
, (void *)outputCount
, 0, 0, 0 ); 
2583                 err 
= (object
->*func
)(  reference
, 
2584                                         output
, (void *)outputCount
, 0, 0, 0, 0 ); 
2588                 IOLog("%s: Bad method table\n", client
->getName()); 
2593         err 
= kIOReturnUnsupported
; 
2598 kern_return_t 
is_io_async_method_scalarI_structureI( 
2599             io_connect_t        connect
, 
2600             mach_port_t         wakePort
, 
2601             io_async_ref_t          reference
, 
2602             mach_msg_type_number_t  referenceCnt
, 
2605             IOByteCount inputCount
, 
2606             UInt8 
*             inputStruct
, 
2607             IOByteCount inputStructCount 
) 
2610     IOExternalAsyncMethod 
*method
; 
2614     CHECK( IOUserClient
, connect
, client
); 
2616     if( (method 
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) { 
2618         err 
= kIOReturnBadArgument
; 
2619         if( kIOUCScalarIStructI 
!= (method
->flags 
& kIOUCTypeMask
)) 
2621         if( (0xffffffff != method
->count0
) 
2622                 && (inputCount 
!= method
->count0
)) 
2624         if( (0xffffffff != method
->count1
) 
2625                 && (inputStructCount 
!= method
->count1
)) 
2628         reference
[0] = (natural_t
) wakePort
; 
2629         func 
= method
->func
; 
2631         switch( inputCount
) { 
2634                 err 
= (object
->*func
)(  reference
, 
2635                                         input
[0], input
[1], input
[2], 
2640                 err 
= (object
->*func
)(  reference
, 
2641                                         input
[0], input
[1], input
[2], 
2643                                         inputStruct
, (void *)inputStructCount 
); 
2646                 err 
= (object
->*func
)(  reference
, 
2647                                         input
[0], input
[1], input
[2], 
2648                                         inputStruct
, (void *)inputStructCount
, 
2652                 err 
= (object
->*func
)(  reference
, 
2654                                         inputStruct
, (void *)inputStructCount
, 
2658                 err 
= (object
->*func
)(  reference
, 
2660                                         inputStruct
, (void *)inputStructCount
, 
2664                 err 
= (object
->*func
)(  reference
, 
2665                                         inputStruct
, (void *)inputStructCount
, 
2670                 IOLog("%s: Bad method table\n", client
->getName()); 
2675         err 
= kIOReturnUnsupported
; 
2680 kern_return_t 
is_io_async_method_structureI_structureO( 
2681         io_object_t     connect
, 
2682         mach_port_t wakePort
, 
2683         io_async_ref_t          reference
, 
2684         mach_msg_type_number_t  referenceCnt
, 
2687         IOByteCount     inputCount
, 
2689         IOByteCount 
*   outputCount 
) 
2692     IOExternalAsyncMethod 
*method
; 
2696     CHECK( IOUserClient
, connect
, client
); 
2698     if( (method 
= client
->getAsyncTargetAndMethodForIndex(&object
, index
)) ) { 
2700         err 
= kIOReturnBadArgument
; 
2701         if( kIOUCStructIStructO 
!= (method
->flags 
& kIOUCTypeMask
)) 
2703         if( (0xffffffff != method
->count0
) 
2704                 && (inputCount 
!= method
->count0
)) 
2706         if( (0xffffffff != method
->count1
) 
2707                 && (*outputCount 
!= method
->count1
)) 
2710         reference
[0] = (natural_t
) wakePort
; 
2711         func 
= method
->func
; 
2713         if( method
->count1
) { 
2714             if( method
->count0
) { 
2715                 err 
= (object
->*func
)( reference
, 
2717                                         (void *)inputCount
, outputCount
, 0, 0 ); 
2719                 err 
= (object
->*func
)( reference
, 
2720                                        output
, outputCount
, 0, 0, 0, 0 ); 
2723                 err 
= (object
->*func
)( reference
, 
2724                                        input
, (void *)inputCount
, 0, 0, 0, 0 ); 
2730         err 
= kIOReturnUnsupported
; 
2734 /* Routine io_make_matching */ 
2735 kern_return_t 
is_io_make_matching( 
2736         mach_port_t     master_port
, 
2738         IOOptionBits    options
, 
2740         IOByteCount     inputCount
, 
2741         io_string_t     matching 
) 
2744     IOReturn            err 
= kIOReturnSuccess
; 
2745     OSDictionary 
*      dict
; 
2747     if( master_port 
!= master_device_port
) 
2748         return( kIOReturnNotPrivileged
); 
2752         case kIOServiceMatching
: 
2753             dict 
= IOService::serviceMatching( gIOServiceKey 
); 
2756         case kIOBSDNameMatching
: 
2757             dict 
= IOBSDNameMatching( (const char *) input 
); 
2760         case kIOOFPathMatching
: 
2761             dict 
= IOOFPathMatching( (const char *) input
, 
2762                                     matching
, sizeof( io_string_t
)); 
2770         return( kIOReturnUnsupported
); 
2773         s 
= OSSerialize::withCapacity(4096); 
2775             err 
= kIOReturnNoMemory
; 
2779         if( !dict
->serialize( s 
)) { 
2780             err 
= kIOReturnUnsupported
; 
2784         if( s
->getLength() > sizeof( io_string_t
)) { 
2785             err 
= kIOReturnNoMemory
; 
2788             strcpy( matching
, s
->text()); 
2800 /* Routine io_catalog_send_data */ 
2801 kern_return_t 
is_io_catalog_send_data( 
2802         mach_port_t             master_port
, 
2804         io_buf_ptr_t            inData
, 
2805         mach_msg_type_number_t  inDataCount
, 
2810     kern_return_t kr 
= kIOReturnError
; 
2812     //printf("io_catalog_send_data called. flag: %d\n", flag); 
2814     if( master_port 
!= master_device_port
) 
2815         return kIOReturnNotPrivileged
; 
2817     // FIXME: This is a hack. Should have own function for removeKernelLinker() 
2818     if(flag 
!= kIOCatalogRemoveKernelLinker 
&& ( !inData 
|| !inDataCount
) ) 
2819         return kIOReturnBadArgument
; 
2822         vm_map_offset_t map_data
; 
2824         kr 
= vm_map_copyout( kernel_map
, &map_data
, (vm_map_copy_t
)inData
); 
2825         data 
= CAST_DOWN(vm_offset_t
, map_data
); 
2827         if( kr 
!= KERN_SUCCESS
) 
2830         // must return success after vm_map_copyout() succeeds 
2833             obj 
= (OSObject 
*)OSUnserializeXML((const char *)data
); 
2834             vm_deallocate( kernel_map
, data
, inDataCount 
); 
2836                 *result 
= kIOReturnNoMemory
; 
2837                 return( KERN_SUCCESS
); 
2843         case kIOCatalogAddDrivers
:  
2844         case kIOCatalogAddDriversNoMatch
: { 
2847                 array 
= OSDynamicCast(OSArray
, obj
); 
2849                     if ( !gIOCatalogue
->addDrivers( array 
,  
2850                                           flag 
== kIOCatalogAddDrivers
) ) { 
2851                         kr 
= kIOReturnError
; 
2855                     kr 
= kIOReturnBadArgument
; 
2860         case kIOCatalogRemoveDrivers
:  
2861         case kIOCatalogRemoveDriversNoMatch
: { 
2862                 OSDictionary 
* dict
; 
2864                 dict 
= OSDynamicCast(OSDictionary
, obj
); 
2866                     if ( !gIOCatalogue
->removeDrivers( dict
,  
2867                                           flag 
== kIOCatalogRemoveDrivers 
) ) { 
2868                         kr 
= kIOReturnError
; 
2872                     kr 
= kIOReturnBadArgument
; 
2877         case kIOCatalogStartMatching
: { 
2878                 OSDictionary 
* dict
; 
2880                 dict 
= OSDynamicCast(OSDictionary
, obj
); 
2882                     if ( !gIOCatalogue
->startMatching( dict 
) ) { 
2883                         kr 
= kIOReturnError
; 
2887                     kr 
= kIOReturnBadArgument
; 
2892         case kIOCatalogRemoveKernelLinker
: { 
2893                 if (gIOCatalogue
->removeKernelLinker() != KERN_SUCCESS
) { 
2894                     kr 
= kIOReturnError
; 
2896                     kr 
= kIOReturnSuccess
; 
2902             kr 
= kIOReturnBadArgument
; 
2906     if (obj
) obj
->release(); 
2909     return( KERN_SUCCESS
); 
2912 /* Routine io_catalog_terminate */ 
2913 kern_return_t 
is_io_catalog_terminate( 
2914         mach_port_t master_port
, 
2920     if( master_port 
!= master_device_port 
) 
2921         return kIOReturnNotPrivileged
; 
2923     kr 
= IOUserClient::clientHasPrivilege( (void *) current_task(), 
2924                                             kIOClientPrivilegeAdministrator 
); 
2925     if( kIOReturnSuccess 
!= kr
) 
2929         case kIOCatalogServiceTerminate
: 
2931             IOService 
*         service
; 
2933             iter 
= IORegistryIterator::iterateOver(gIOServicePlane
, 
2934                                         kIORegistryIterateRecursively
); 
2936                 return kIOReturnNoMemory
; 
2940                 while( (service 
= (IOService 
*)iter
->getNextObject()) ) { 
2941                     if( service
->metaCast(name
)) { 
2942                         if ( !service
->terminate( kIOServiceRequired
 
2943                                                 | kIOServiceSynchronous
) ) { 
2944                             kr 
= kIOReturnUnsupported
; 
2949             } while( !service 
&& !iter
->isValid()); 
2953         case kIOCatalogModuleUnload
: 
2954         case kIOCatalogModuleTerminate
: 
2955             kr 
= gIOCatalogue
->terminateDriversForModule(name
, 
2956                                         flag 
== kIOCatalogModuleUnload
); 
2960             kr 
= kIOReturnBadArgument
; 
2967 /* Routine io_catalog_get_data */ 
2968 kern_return_t 
is_io_catalog_get_data( 
2969         mach_port_t             master_port
, 
2971         io_buf_ptr_t            
*outData
, 
2972         mach_msg_type_number_t  
*outDataCount
) 
2974     kern_return_t kr 
= kIOReturnSuccess
; 
2977     if( master_port 
!= master_device_port
) 
2978         return kIOReturnNotPrivileged
; 
2980     //printf("io_catalog_get_data called. flag: %d\n", flag); 
2982     s 
= OSSerialize::withCapacity(4096); 
2984         return kIOReturnNoMemory
; 
2988     kr 
= gIOCatalogue
->serializeData(flag
, s
); 
2990     if ( kr 
== kIOReturnSuccess 
) { 
2995         size 
= s
->getLength(); 
2996         kr 
= vm_allocate(kernel_map
, &data
, size
, VM_FLAGS_ANYWHERE
); 
2997         if ( kr 
== kIOReturnSuccess 
) { 
2998             bcopy(s
->text(), (void *)data
, size
); 
2999             kr 
= vm_map_copyin(kernel_map
, (vm_map_address_t
)data
, 
3000                                (vm_map_size_t
)size
, true, ©
); 
3001             *outData 
= (char *)copy
; 
3002             *outDataCount 
= size
; 
3011 /* Routine io_catalog_get_gen_count */ 
3012 kern_return_t 
is_io_catalog_get_gen_count( 
3013         mach_port_t             master_port
, 
3016     if( master_port 
!= master_device_port
) 
3017         return kIOReturnNotPrivileged
; 
3019     //printf("io_catalog_get_gen_count called.\n"); 
3022         return kIOReturnBadArgument
; 
3024     *genCount 
= gIOCatalogue
->getGenerationCount(); 
3026     return kIOReturnSuccess
; 
3029 /* Routine io_catalog_module_loaded */ 
3030 kern_return_t 
is_io_catalog_module_loaded( 
3031         mach_port_t             master_port
, 
3034     if( master_port 
!= master_device_port
) 
3035         return kIOReturnNotPrivileged
; 
3037     //printf("io_catalog_module_loaded called. name %s\n", name); 
3040         return kIOReturnBadArgument
; 
3042     gIOCatalogue
->moduleHasLoaded(name
); 
3044     return kIOReturnSuccess
; 
3047 kern_return_t 
is_io_catalog_reset( 
3048         mach_port_t             master_port
, 
3051     if( master_port 
!= master_device_port
) 
3052         return kIOReturnNotPrivileged
; 
3055         case kIOCatalogResetDefault
: 
3056             gIOCatalogue
->reset(); 
3060             return kIOReturnBadArgument
; 
3063     return kIOReturnSuccess
; 
3066 kern_return_t 
iokit_user_client_trap(struct iokit_user_client_trap_args 
*args
) 
3068     kern_return_t result 
= kIOReturnBadArgument
; 
3069     IOUserClient 
*userClient
; 
3071     if ((userClient 
= OSDynamicCast(IOUserClient
, 
3072             iokit_lookup_connect_ref_current_task((OSObject 
*)(args
->userClientRef
))))) { 
3073         IOExternalTrap 
*trap
; 
3074         IOService 
*target 
= NULL
; 
3076         trap 
= userClient
->getTargetAndTrapForIndex(&target
, args
->index
); 
3078         if (trap 
&& target
) { 
3084                 result 
= (target
->*func
)(args
->p1
, args
->p2
, args
->p3
, args
->p4
, args
->p5
, args
->p6
); 
3088         userClient
->release(); 
3096 OSMetaClassDefineReservedUnused(IOUserClient
, 0); 
3097 OSMetaClassDefineReservedUnused(IOUserClient
, 1); 
3098 OSMetaClassDefineReservedUnused(IOUserClient
, 2); 
3099 OSMetaClassDefineReservedUnused(IOUserClient
, 3); 
3100 OSMetaClassDefineReservedUnused(IOUserClient
, 4); 
3101 OSMetaClassDefineReservedUnused(IOUserClient
, 5); 
3102 OSMetaClassDefineReservedUnused(IOUserClient
, 6); 
3103 OSMetaClassDefineReservedUnused(IOUserClient
, 7); 
3104 OSMetaClassDefineReservedUnused(IOUserClient
, 8); 
3105 OSMetaClassDefineReservedUnused(IOUserClient
, 9); 
3106 OSMetaClassDefineReservedUnused(IOUserClient
, 10); 
3107 OSMetaClassDefineReservedUnused(IOUserClient
, 11); 
3108 OSMetaClassDefineReservedUnused(IOUserClient
, 12); 
3109 OSMetaClassDefineReservedUnused(IOUserClient
, 13); 
3110 OSMetaClassDefineReservedUnused(IOUserClient
, 14); 
3111 OSMetaClassDefineReservedUnused(IOUserClient
, 15);