1/*
2 * Copyright (c) 1998-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29
30#include <libkern/c++/OSKext.h>
31#include <IOKit/IOKitServer.h>
32#include <IOKit/IOKitKeysPrivate.h>
33#include <IOKit/IOUserClient.h>
34#include <IOKit/IOService.h>
35#include <IOKit/IORegistryEntry.h>
36#include <IOKit/IOCatalogue.h>
37#include <IOKit/IOMemoryDescriptor.h>
38#include <IOKit/IOBufferMemoryDescriptor.h>
39#include <IOKit/IOLib.h>
40#include <IOKit/IOStatisticsPrivate.h>
41#include <IOKit/IOTimeStamp.h>
42#include <libkern/OSDebug.h>
43#include <sys/proc.h>
44#include <sys/kauth.h>
45
46#if CONFIG_MACF
47
48extern "C" {
49#include <security/mac_framework.h>
50};
51#include <sys/kauth.h>
52
53#define IOMACF_LOG 0
54
55#endif /* CONFIG_MACF */
56
57#include <IOKit/assert.h>
58
59#include "IOServicePrivate.h"
60#include "IOKitKernelInternal.h"
61
62#define SCALAR64(x) ((io_user_scalar_t)((unsigned int)x))
63#define SCALAR32(x) ((uint32_t )x)
64#define ARG32(x)    ((void *)SCALAR32(x))
65#define REF64(x)    ((io_user_reference_t)((UInt64)(x)))
66#define REF32(x)    ((int)(x))
67
68enum
69{
70    kIOUCAsync0Flags = 3ULL,
71    kIOUCAsync64Flag = 1ULL
72};
73
74#if IOKITSTATS
75
76#define IOStatisticsRegisterCounter() \
77do { \
78	reserved->counter = IOStatistics::registerUserClient(this); \
79} while (0)
80
81#define IOStatisticsUnregisterCounter() \
82do { \
83	if (reserved) \
84		IOStatistics::unregisterUserClient(reserved->counter); \
85} while (0)
86
87#define IOStatisticsClientCall() \
88do { \
89	IOStatistics::countUserClientCall(client); \
90} while (0)
91
92#else
93
94#define IOStatisticsRegisterCounter()
95#define IOStatisticsUnregisterCounter()
96#define IOStatisticsClientCall()
97
98#endif /* IOKITSTATS */
99
100/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
101
102// definitions we should get from osfmk
103
104//typedef struct ipc_port * ipc_port_t;
105typedef natural_t ipc_kobject_type_t;
106
107#define IKOT_IOKIT_SPARE	27
108#define IKOT_IOKIT_CONNECT	29
109#define IKOT_IOKIT_OBJECT	30
110
111extern "C" {
112
113extern ipc_port_t iokit_alloc_object_port( io_object_t obj,
114			ipc_kobject_type_t type );
115
116extern kern_return_t iokit_destroy_object_port( ipc_port_t port );
117
118extern mach_port_name_t iokit_make_send_right( task_t task,
119				io_object_t obj, ipc_kobject_type_t type );
120
121extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta );
122
123extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task);
124
125extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef);
126
127extern ipc_port_t master_device_port;
128
129extern void iokit_retain_port( ipc_port_t port );
130extern void iokit_release_port( ipc_port_t port );
131extern void iokit_release_port_send( ipc_port_t port );
132
133extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type );
134
135#include <mach/mach_traps.h>
136#include <vm/vm_map.h>
137
138} /* extern "C" */
139
140
141/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
142
143// IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
144
145class IOMachPort : public OSObject
146{
147    OSDeclareDefaultStructors(IOMachPort)
148public:
149    OSObject *	object;
150    ipc_port_t	port;
151    UInt32      mscount;
152    UInt8	holdDestroy;
153
154    static IOMachPort * portForObject( OSObject * obj,
155				ipc_kobject_type_t type );
156    static bool noMoreSendersForObject( OSObject * obj,
157				ipc_kobject_type_t type, mach_port_mscount_t * mscount );
158    static void releasePortForObject( OSObject * obj,
159				ipc_kobject_type_t type );
160    static void setHoldDestroy( OSObject * obj, ipc_kobject_type_t type );
161
162    static OSDictionary * dictForType( ipc_kobject_type_t type );
163
164    static mach_port_name_t makeSendRightForTask( task_t task,
165				io_object_t obj, ipc_kobject_type_t type );
166
167    virtual void free();
168};
169
170#define super OSObject
171OSDefineMetaClassAndStructors(IOMachPort, OSObject)
172
173static IOLock *		gIOObjectPortLock;
174
175/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
176
177// not in dictForType() for debugging ease
178static OSDictionary *	gIOObjectPorts;
179static OSDictionary *	gIOConnectPorts;
180
181OSDictionary * IOMachPort::dictForType( ipc_kobject_type_t type )
182{
183    OSDictionary **	 	dict;
184
185    if( IKOT_IOKIT_OBJECT == type )
186	dict = &gIOObjectPorts;
187    else if( IKOT_IOKIT_CONNECT == type )
188	dict = &gIOConnectPorts;
189    else
190	return( 0 );
191
192    if( 0 == *dict)
193        *dict = OSDictionary::withCapacity( 1 );
194
195    return( *dict );
196}
197
198IOMachPort * IOMachPort::portForObject ( OSObject * obj,
199				ipc_kobject_type_t type )
200{
201    IOMachPort * 	inst = 0;
202    OSDictionary *	dict;
203
204    IOTakeLock( gIOObjectPortLock);
205
206    do {
207
208	dict = dictForType( type );
209	if( !dict)
210	    continue;
211
212        if( (inst = (IOMachPort *)
213                dict->getObject( (const OSSymbol *) obj ))) {
214	    inst->mscount++;
215	    inst->retain();
216            continue;
217	}
218
219        inst = new IOMachPort;
220        if( inst && !inst->init()) {
221            inst = 0;
222            continue;
223	}
224
225        inst->port = iokit_alloc_object_port( obj, type );
226        if( inst->port) {
227	    // retains obj
228            dict->setObject( (const OSSymbol *) obj, inst );
229	    inst->mscount++;
230
231        } else {
232            inst->release();
233            inst = 0;
234        }
235
236    } while( false );
237
238    IOUnlock( gIOObjectPortLock);
239
240    return( inst );
241}
242
243bool IOMachPort::noMoreSendersForObject( OSObject * obj,
244				ipc_kobject_type_t type, mach_port_mscount_t * mscount )
245{
246    OSDictionary *	dict;
247    IOMachPort *	machPort;
248    bool		destroyed = true;
249
250    IOTakeLock( gIOObjectPortLock);
251
252    if( (dict = dictForType( type ))) {
253        obj->retain();
254
255	machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
256	if( machPort) {
257	    destroyed = (machPort->mscount <= *mscount);
258	    if( destroyed)
259		dict->removeObject( (const OSSymbol *) obj );
260	    else
261		*mscount = machPort->mscount;
262	}
263	obj->release();
264    }
265
266    IOUnlock( gIOObjectPortLock);
267
268    return( destroyed );
269}
270
271void IOMachPort::releasePortForObject( OSObject * obj,
272				ipc_kobject_type_t type )
273{
274    OSDictionary *	dict;
275    IOMachPort *	machPort;
276
277    IOTakeLock( gIOObjectPortLock);
278
279    if( (dict = dictForType( type ))) {
280        obj->retain();
281	machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
282	if( machPort && !machPort->holdDestroy)
283            dict->removeObject( (const OSSymbol *) obj );
284        obj->release();
285    }
286
287    IOUnlock( gIOObjectPortLock);
288}
289
290void IOMachPort::setHoldDestroy( OSObject * obj, ipc_kobject_type_t type )
291{
292    OSDictionary *	dict;
293    IOMachPort * 	machPort;
294
295    IOLockLock( gIOObjectPortLock );
296
297    if( (dict = dictForType( type ))) {
298        machPort = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
299        if( machPort)
300            machPort->holdDestroy = true;
301    }
302
303    IOLockUnlock( gIOObjectPortLock );
304}
305
306void IOUserClient::destroyUserReferences( OSObject * obj )
307{
308    IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
309
310    // panther, 3160200
311    // IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
312
313    OSDictionary * dict;
314
315    IOTakeLock( gIOObjectPortLock);
316    obj->retain();
317
318    if( (dict = IOMachPort::dictForType( IKOT_IOKIT_CONNECT )))
319    {
320	IOMachPort * port;
321	port = (IOMachPort *) dict->getObject( (const OSSymbol *) obj );
322	if (port)
323	{
324	    IOUserClient * uc;
325	    if ((uc = OSDynamicCast(IOUserClient, obj)) && uc->mappings)
326	    {
327		dict->setObject((const OSSymbol *) uc->mappings, port);
328		iokit_switch_object_port(port->port, uc->mappings, IKOT_IOKIT_CONNECT);
329
330		uc->mappings->release();
331		uc->mappings = 0;
332	    }
333	    dict->removeObject( (const OSSymbol *) obj );
334	}
335    }
336    obj->release();
337    IOUnlock( gIOObjectPortLock);
338}
339
340mach_port_name_t IOMachPort::makeSendRightForTask( task_t task,
341				io_object_t obj, ipc_kobject_type_t type )
342{
343    return( iokit_make_send_right( task, obj, type ));
344}
345
346void IOMachPort::free( void )
347{
348    if( port)
349	iokit_destroy_object_port( port );
350    super::free();
351}
352
353/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
354
355class IOUserNotification : public OSIterator
356{
357    OSDeclareDefaultStructors(IOUserNotification)
358
359    IONotifier 	* 	holdNotify;
360    IOLock 	*	lock;
361
362public:
363
364    virtual bool init( void );
365    virtual void free();
366
367    virtual void setNotification( IONotifier * obj );
368
369    virtual void reset();
370    virtual bool isValid();
371};
372
373/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
374
375extern "C" {
376
377// functions called from osfmk/device/iokit_rpc.c
378
379void
380iokit_add_reference( io_object_t obj )
381{
382    if( obj)
383	obj->retain();
384}
385
386void
387iokit_remove_reference( io_object_t obj )
388{
389    if( obj)
390	obj->release();
391}
392
393ipc_port_t
394iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type )
395{
396    IOMachPort * machPort;
397    ipc_port_t	 port;
398
399    if( (machPort = IOMachPort::portForObject( obj, type ))) {
400
401	port = machPort->port;
402	if( port)
403	    iokit_retain_port( port );
404
405	machPort->release();
406
407    } else
408	port = NULL;
409
410    return( port );
411}
412
413kern_return_t
414iokit_client_died( io_object_t obj, ipc_port_t /* port */,
415			ipc_kobject_type_t type, mach_port_mscount_t * mscount )
416{
417    IOUserClient *	client;
418    IOMemoryMap *	map;
419    IOUserNotification * notify;
420
421    if( !IOMachPort::noMoreSendersForObject( obj, type, mscount ))
422	return( kIOReturnNotReady );
423
424    if( IKOT_IOKIT_CONNECT == type)
425    {
426	if( (client = OSDynamicCast( IOUserClient, obj ))) {
427		IOStatisticsClientCall();
428	    client->clientDied();
429    }
430    }
431    else if( IKOT_IOKIT_OBJECT == type)
432    {
433	if( (map = OSDynamicCast( IOMemoryMap, obj )))
434	    map->taskDied();
435	else if( (notify = OSDynamicCast( IOUserNotification, obj )))
436	    notify->setNotification( 0 );
437    }
438
439    return( kIOReturnSuccess );
440}
441
442};	/* extern "C" */
443
444/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
445
446class IOServiceUserNotification : public IOUserNotification
447{
448    OSDeclareDefaultStructors(IOServiceUserNotification)
449
450    struct PingMsg {
451        mach_msg_header_t		msgHdr;
452        OSNotificationHeader64		notifyHeader;
453    };
454
455    enum { kMaxOutstanding = 1024 };
456
457    PingMsg	*	pingMsg;
458    vm_size_t		msgSize;
459    OSArray 	*	newSet;
460    OSObject	*	lastEntry;
461    bool		armed;
462
463public:
464
465    virtual bool init( mach_port_t port, natural_t type,
466                       void * reference, vm_size_t referenceSize,
467		       bool clientIs64 );
468    virtual void free();
469
470    static bool _handler( void * target,
471                          void * ref, IOService * newService, IONotifier * notifier );
472    virtual bool handler( void * ref, IOService * newService );
473
474    virtual OSObject * getNextObject();
475};
476
477class IOServiceMessageUserNotification : public IOUserNotification
478{
479    OSDeclareDefaultStructors(IOServiceMessageUserNotification)
480
481    struct PingMsg {
482        mach_msg_header_t		msgHdr;
483	mach_msg_body_t			msgBody;
484	mach_msg_port_descriptor_t	ports[1];
485        OSNotificationHeader64		notifyHeader __attribute__ ((packed));
486    };
487
488    PingMsg *		pingMsg;
489    vm_size_t		msgSize;
490    uint8_t		clientIs64;
491    int			owningPID;
492
493public:
494
495    virtual bool init( mach_port_t port, natural_t type,
496		       void * reference, vm_size_t referenceSize,
497		       vm_size_t extraSize,
498		       bool clientIs64 );
499
500    virtual void free();
501
502    static IOReturn _handler( void * target, void * ref,
503                              UInt32 messageType, IOService * provider,
504                              void * messageArgument, vm_size_t argSize );
505    virtual IOReturn handler( void * ref,
506                              UInt32 messageType, IOService * provider,
507                              void * messageArgument, vm_size_t argSize );
508
509    virtual OSObject * getNextObject();
510};
511
512/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
513
514#undef super
515#define super OSIterator
516OSDefineMetaClass( IOUserNotification, OSIterator )
517OSDefineAbstractStructors( IOUserNotification, OSIterator )
518
519/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
520
521bool IOUserNotification::init( void )
522{
523    if( !super::init())
524	return( false );
525
526    lock = IOLockAlloc();
527    if( !lock)
528        return( false );
529
530    return( true );
531}
532
533void IOUserNotification::free( void )
534{
535    if( holdNotify)
536	holdNotify->remove();
537    // can't be in handler now
538
539    if( lock)
540	IOLockFree( lock );
541
542    super::free();
543}
544
545
546void IOUserNotification::setNotification( IONotifier * notify )
547{
548    IONotifier * previousNotify;
549
550    IOLockLock( gIOObjectPortLock);
551
552    previousNotify = holdNotify;
553    holdNotify = notify;
554
555    IOLockUnlock( gIOObjectPortLock);
556
557    if( previousNotify)
558	previousNotify->remove();
559}
560
561void IOUserNotification::reset()
562{
563    // ?
564}
565
566bool IOUserNotification::isValid()
567{
568    return( true );
569}
570
571/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
572
573#undef super
574#define super IOUserNotification
575OSDefineMetaClassAndStructors(IOServiceUserNotification, IOUserNotification)
576
577/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
578
579bool IOServiceUserNotification::init( mach_port_t port, natural_t type,
580				       void * reference, vm_size_t referenceSize,
581				       bool clientIs64 )
582{
583    if( !super::init())
584        return( false );
585
586    newSet = OSArray::withCapacity( 1 );
587    if( !newSet)
588        return( false );
589
590    if (referenceSize > sizeof(OSAsyncReference64))
591        return( false );
592
593    msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize;
594    pingMsg = (PingMsg *) IOMalloc( msgSize);
595    if( !pingMsg)
596        return( false );
597
598    bzero( pingMsg, msgSize);
599
600    pingMsg->msgHdr.msgh_remote_port	= port;
601    pingMsg->msgHdr.msgh_bits 		= MACH_MSGH_BITS(
602                                            MACH_MSG_TYPE_COPY_SEND /*remote*/,
603                                            MACH_MSG_TYPE_MAKE_SEND /*local*/);
604    pingMsg->msgHdr.msgh_size 		= msgSize;
605    pingMsg->msgHdr.msgh_id		= kOSNotificationMessageID;
606
607    pingMsg->notifyHeader.size = 0;
608    pingMsg->notifyHeader.type = type;
609    bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
610
611    return( true );
612}
613
614void IOServiceUserNotification::free( void )
615{
616    PingMsg   *	_pingMsg;
617    vm_size_t	_msgSize;
618    OSArray   *	_newSet;
619    OSObject  *	_lastEntry;
620
621    _pingMsg   = pingMsg;
622    _msgSize   = msgSize;
623    _lastEntry = lastEntry;
624    _newSet    = newSet;
625
626    super::free();
627
628    if( _pingMsg && _msgSize) {
629		if (_pingMsg->msgHdr.msgh_remote_port) {
630			iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port);
631		}
632        IOFree(_pingMsg, _msgSize);
633	}
634
635    if( _lastEntry)
636        _lastEntry->release();
637
638    if( _newSet)
639        _newSet->release();
640}
641
642bool IOServiceUserNotification::_handler( void * target,
643                                    void * ref, IOService * newService, IONotifier * notifier )
644{
645    return( ((IOServiceUserNotification *) target)->handler( ref, newService ));
646}
647
648bool IOServiceUserNotification::handler( void * ref,
649                                IOService * newService )
650{
651    unsigned int	count;
652    kern_return_t	kr;
653    ipc_port_t		port = NULL;
654    bool		sendPing = false;
655
656    IOTakeLock( lock );
657
658    count = newSet->getCount();
659    if( count < kMaxOutstanding) {
660
661        newSet->setObject( newService );
662        if( (sendPing = (armed && (0 == count))))
663            armed = false;
664    }
665
666    IOUnlock( lock );
667
668    if( kIOServiceTerminatedNotificationType == pingMsg->notifyHeader.type)
669        IOMachPort::setHoldDestroy( newService, IKOT_IOKIT_OBJECT );
670
671    if( sendPing) {
672	if( (port = iokit_port_for_object( this, IKOT_IOKIT_OBJECT ) ))
673            pingMsg->msgHdr.msgh_local_port = port;
674	else
675            pingMsg->msgHdr.msgh_local_port = NULL;
676
677        kr = mach_msg_send_from_kernel_proper( &pingMsg->msgHdr,
678                                        pingMsg->msgHdr.msgh_size);
679	if( port)
680	    iokit_release_port( port );
681
682        if( KERN_SUCCESS != kr)
683            IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
684    }
685
686    return( true );
687}
688
689OSObject * IOServiceUserNotification::getNextObject()
690{
691    unsigned int	count;
692    OSObject *		result;
693
694    IOTakeLock( lock );
695
696    if( lastEntry)
697        lastEntry->release();
698
699    count = newSet->getCount();
700    if( count ) {
701        result = newSet->getObject( count - 1 );
702        result->retain();
703        newSet->removeObject( count - 1);
704    } else {
705        result = 0;
706        armed = true;
707    }
708    lastEntry = result;
709
710    IOUnlock( lock );
711
712    return( result );
713}
714
715/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
716
717OSDefineMetaClassAndStructors(IOServiceMessageUserNotification, IOUserNotification)
718
719/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
720
721bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
722				void * reference, vm_size_t referenceSize, vm_size_t extraSize,
723				bool client64 )
724{
725    if( !super::init())
726        return( false );
727
728    if (referenceSize > sizeof(OSAsyncReference64))
729        return( false );
730
731    clientIs64 = client64;
732
733    owningPID = proc_selfpid();
734
735    extraSize += sizeof(IOServiceInterestContent64);
736    msgSize = sizeof(PingMsg) - sizeof(OSAsyncReference64) + referenceSize + extraSize;
737    pingMsg = (PingMsg *) IOMalloc( msgSize);
738    if( !pingMsg)
739        return( false );
740
741    bzero( pingMsg, msgSize);
742
743    pingMsg->msgHdr.msgh_remote_port	= port;
744    pingMsg->msgHdr.msgh_bits 		= MACH_MSGH_BITS_COMPLEX
745					|  MACH_MSGH_BITS(
746                                            MACH_MSG_TYPE_COPY_SEND /*remote*/,
747                                            MACH_MSG_TYPE_MAKE_SEND /*local*/);
748    pingMsg->msgHdr.msgh_size 		= msgSize;
749    pingMsg->msgHdr.msgh_id		= kOSNotificationMessageID;
750
751    pingMsg->msgBody.msgh_descriptor_count = 1;
752
753    pingMsg->ports[0].name 		= 0;
754    pingMsg->ports[0].disposition 	= MACH_MSG_TYPE_MAKE_SEND;
755    pingMsg->ports[0].type 		= MACH_MSG_PORT_DESCRIPTOR;
756
757    pingMsg->notifyHeader.size 		= extraSize;
758    pingMsg->notifyHeader.type 		= type;
759    bcopy( reference, pingMsg->notifyHeader.reference, referenceSize );
760
761    return( true );
762}
763
764void IOServiceMessageUserNotification::free( void )
765{
766    PingMsg *	_pingMsg;
767    vm_size_t	_msgSize;
768
769    _pingMsg   = pingMsg;
770    _msgSize   = msgSize;
771
772    super::free();
773
774    if( _pingMsg && _msgSize) {
775		if (_pingMsg->msgHdr.msgh_remote_port) {
776			iokit_release_port_send(_pingMsg->msgHdr.msgh_remote_port);
777		}
778        IOFree( _pingMsg, _msgSize);
779	}
780}
781
782IOReturn IOServiceMessageUserNotification::_handler( void * target, void * ref,
783                                            UInt32 messageType, IOService * provider,
784                                            void * argument, vm_size_t argSize )
785{
786    return( ((IOServiceMessageUserNotification *) target)->handler(
787                                ref, messageType, provider, argument, argSize));
788}
789
790IOReturn IOServiceMessageUserNotification::handler( void * ref,
791                                    UInt32 messageType, IOService * provider,
792                                    void * messageArgument, vm_size_t argSize )
793{
794    kern_return_t		 kr;
795    ipc_port_t 			 thisPort, providerPort;
796    IOServiceInterestContent64 * data = (IOServiceInterestContent64 *)
797					((((uint8_t *) pingMsg) + msgSize) - pingMsg->notifyHeader.size);
798                                        // == pingMsg->notifyHeader.content;
799
800    if (kIOMessageCopyClientID == messageType)
801    {
802        *((void **) messageArgument) = OSNumber::withNumber(owningPID, 32);
803        return (kIOReturnSuccess);
804    }
805
806    data->messageType = messageType;
807
808    if( argSize == 0)
809    {
810	data->messageArgument[0] = (io_user_reference_t) messageArgument;
811	if (clientIs64)
812	    argSize = sizeof(data->messageArgument[0]);
813	else
814	{
815	    data->messageArgument[0] |= (data->messageArgument[0] << 32);
816	    argSize = sizeof(uint32_t);
817	}
818    }
819    else
820    {
821        if( argSize > kIOUserNotifyMaxMessageSize)
822            argSize = kIOUserNotifyMaxMessageSize;
823        bcopy( messageArgument, data->messageArgument, argSize );
824    }
825    pingMsg->msgHdr.msgh_size = msgSize - pingMsg->notifyHeader.size
826        + sizeof( IOServiceInterestContent64 )
827        - sizeof( data->messageArgument)
828        + argSize;
829
830    providerPort = iokit_port_for_object( provider, IKOT_IOKIT_OBJECT );
831    pingMsg->ports[0].name = providerPort;
832    thisPort = iokit_port_for_object( this, IKOT_IOKIT_OBJECT );
833    pingMsg->msgHdr.msgh_local_port = thisPort;
834    kr = mach_msg_send_from_kernel_proper( &pingMsg->msgHdr,
835				    pingMsg->msgHdr.msgh_size);
836    if( thisPort)
837	iokit_release_port( thisPort );
838    if( providerPort)
839	iokit_release_port( providerPort );
840
841    if( KERN_SUCCESS != kr)
842        IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
843
844    return( kIOReturnSuccess );
845}
846
847OSObject * IOServiceMessageUserNotification::getNextObject()
848{
849    return( 0 );
850}
851
852/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
853
854#undef super
855#define super IOService
856OSDefineMetaClassAndAbstractStructors( IOUserClient, IOService )
857
858void IOUserClient::initialize( void )
859{
860    gIOObjectPortLock = IOLockAlloc();
861
862    assert( gIOObjectPortLock );
863}
864
865void IOUserClient::setAsyncReference(OSAsyncReference asyncRef,
866                                     mach_port_t wakePort,
867                                     void *callback, void *refcon)
868{
869    asyncRef[kIOAsyncReservedIndex]      = ((uintptr_t) wakePort)
870					 | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
871    asyncRef[kIOAsyncCalloutFuncIndex]   = (uintptr_t) callback;
872    asyncRef[kIOAsyncCalloutRefconIndex] = (uintptr_t) refcon;
873}
874
875void IOUserClient::setAsyncReference64(OSAsyncReference64 asyncRef,
876					mach_port_t wakePort,
877					mach_vm_address_t callback, io_user_reference_t refcon)
878{
879    asyncRef[kIOAsyncReservedIndex]      = ((io_user_reference_t) wakePort)
880					 | (kIOUCAsync0Flags & asyncRef[kIOAsyncReservedIndex]);
881    asyncRef[kIOAsyncCalloutFuncIndex]   = (io_user_reference_t) callback;
882    asyncRef[kIOAsyncCalloutRefconIndex] = refcon;
883}
884
885static OSDictionary * CopyConsoleUser(UInt32 uid)
886{
887	OSArray * array;
888	OSDictionary * user = 0;
889
890	if ((array = OSDynamicCast(OSArray,
891	    IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey))))
892	{
893	    for (unsigned int idx = 0;
894		    (user = OSDynamicCast(OSDictionary, array->getObject(idx)));
895		    idx++) {
896            OSNumber * num;
897
898            if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionUIDKey)))
899              && (uid == num->unsigned32BitValue())) {
900                user->retain();
901                break;
902            }
903	    }
904	    array->release();
905	}
906    return user;
907}
908
909static OSDictionary * CopyUserOnConsole(void)
910{
911    OSArray * array;
912    OSDictionary * user = 0;
913
914    if ((array = OSDynamicCast(OSArray,
915	IORegistryEntry::getRegistryRoot()->copyProperty(gIOConsoleUsersKey))))
916    {
917	for (unsigned int idx = 0;
918		(user = OSDynamicCast(OSDictionary, array->getObject(idx)));
919		idx++)
920	{
921	    if (kOSBooleanTrue == user->getObject(gIOConsoleSessionOnConsoleKey))
922	    {
923		user->retain();
924		break;
925	    }
926	}
927	array->release();
928    }
929    return (user);
930}
931
932IOReturn IOUserClient::clientHasPrivilege( void * securityToken,
933                                            const char * privilegeName )
934{
935    kern_return_t           kr;
936    security_token_t        token;
937    mach_msg_type_number_t  count;
938    task_t                  task;
939    OSDictionary *          user;
940    bool                    secureConsole;
941
942
943    if (!strncmp(privilegeName, kIOClientPrivilegeForeground,
944                sizeof(kIOClientPrivilegeForeground)))
945    {
946	/* is graphics access denied for current task? */
947	if (proc_get_task_selfgpuacc_deny() != 0)
948		return (kIOReturnNotPrivileged);
949	else
950		return (kIOReturnSuccess);
951    }
952
953    if (!strncmp(privilegeName, kIOClientPrivilegeConsoleSession,
954                                sizeof(kIOClientPrivilegeConsoleSession)))
955    {
956	kauth_cred_t cred;
957	proc_t       p;
958
959        task = (task_t) securityToken;
960	if (!task)
961	    task = current_task();
962	p = (proc_t) get_bsdtask_info(task);
963	kr = kIOReturnNotPrivileged;
964
965	if (p && (cred = kauth_cred_proc_ref(p)))
966	{
967	    user = CopyUserOnConsole();
968	    if (user)
969	    {
970		OSNumber * num;
971		if ((num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionAuditIDKey)))
972		  && (cred->cr_audit.as_aia_p->ai_asid == (au_asid_t) num->unsigned32BitValue()))
973		{
974		    kr = kIOReturnSuccess;
975		}
976		user->release();
977	    }
978	    kauth_cred_unref(&cred);
979	}
980	return (kr);
981    }
982
983    if ((secureConsole = !strncmp(privilegeName, kIOClientPrivilegeSecureConsoleProcess,
984            sizeof(kIOClientPrivilegeSecureConsoleProcess))))
985        task = (task_t)((IOUCProcessToken *)securityToken)->token;
986    else
987        task = (task_t)securityToken;
988
989    count = TASK_SECURITY_TOKEN_COUNT;
990    kr = task_info( task, TASK_SECURITY_TOKEN, (task_info_t) &token, &count );
991
992    if (KERN_SUCCESS != kr)
993    {}
994    else if (!strncmp(privilegeName, kIOClientPrivilegeAdministrator,
995                sizeof(kIOClientPrivilegeAdministrator))) {
996        if (0 != token.val[0])
997            kr = kIOReturnNotPrivileged;
998    } else if (!strncmp(privilegeName, kIOClientPrivilegeLocalUser,
999                sizeof(kIOClientPrivilegeLocalUser))) {
1000        user = CopyConsoleUser(token.val[0]);
1001        if ( user )
1002            user->release();
1003        else
1004            kr = kIOReturnNotPrivileged;
1005    } else if (secureConsole || !strncmp(privilegeName, kIOClientPrivilegeConsoleUser,
1006                                    sizeof(kIOClientPrivilegeConsoleUser))) {
1007        user = CopyConsoleUser(token.val[0]);
1008        if ( user ) {
1009            if (user->getObject(gIOConsoleSessionOnConsoleKey) != kOSBooleanTrue)
1010                kr = kIOReturnNotPrivileged;
1011            else if ( secureConsole ) {
1012                OSNumber * pid = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionSecureInputPIDKey));
1013                if ( pid && pid->unsigned32BitValue() != ((IOUCProcessToken *)securityToken)->pid)
1014                    kr = kIOReturnNotPrivileged;
1015            }
1016            user->release();
1017        }
1018        else
1019            kr = kIOReturnNotPrivileged;
1020    } else
1021        kr = kIOReturnUnsupported;
1022
1023    return (kr);
1024}
1025
1026bool IOUserClient::init()
1027{
1028	if (getPropertyTable() || super::init())
1029		return reserve();
1030
1031	return false;
1032}
1033
1034bool IOUserClient::init(OSDictionary * dictionary)
1035{
1036	if (getPropertyTable() || super::init(dictionary))
1037		return reserve();
1038
1039	return false;
1040}
1041
1042bool IOUserClient::initWithTask(task_t owningTask,
1043                                void * securityID,
1044                                UInt32 type )
1045{
1046	if (getPropertyTable() || super::init())
1047		return reserve();
1048
1049	return false;
1050}
1051
1052bool IOUserClient::initWithTask(task_t owningTask,
1053                                void * securityID,
1054                                UInt32 type,
1055                                OSDictionary * properties )
1056{
1057    bool ok;
1058
1059    ok = super::init( properties );
1060    ok &= initWithTask( owningTask, securityID, type );
1061
1062    return( ok );
1063}
1064
1065bool IOUserClient::reserve()
1066{
1067	if(!reserved) {
1068		reserved = IONew(ExpansionData, 1);
1069		if (!reserved) {
1070			return false;
1071		}
1072	}
1073
1074	IOStatisticsRegisterCounter();
1075
1076	return true;
1077}
1078
1079void IOUserClient::free()
1080{
1081    if( mappings)
1082        mappings->release();
1083
1084    IOStatisticsUnregisterCounter();
1085
1086    if (reserved)
1087        IODelete(reserved, ExpansionData, 1);
1088
1089    super::free();
1090}
1091
1092IOReturn IOUserClient::clientDied( void )
1093{
1094    return( clientClose());
1095}
1096
1097IOReturn IOUserClient::clientClose( void )
1098{
1099    return( kIOReturnUnsupported );
1100}
1101
1102IOService * IOUserClient::getService( void )
1103{
1104    return( 0 );
1105}
1106
1107IOReturn IOUserClient::registerNotificationPort(
1108		mach_port_t 	/* port */,
1109		UInt32		/* type */,
1110                UInt32		/* refCon */)
1111{
1112    return( kIOReturnUnsupported);
1113}
1114
1115IOReturn IOUserClient::registerNotificationPort(
1116		mach_port_t port,
1117		UInt32		type,
1118		io_user_reference_t refCon)
1119{
1120    return (registerNotificationPort(port, type, (UInt32) refCon));
1121}
1122
1123IOReturn IOUserClient::getNotificationSemaphore( UInt32 notification_type,
1124                                    semaphore_t * semaphore )
1125{
1126    return( kIOReturnUnsupported);
1127}
1128
1129IOReturn IOUserClient::connectClient( IOUserClient * /* client */ )
1130{
1131    return( kIOReturnUnsupported);
1132}
1133
1134IOReturn IOUserClient::clientMemoryForType( UInt32 type,
1135			        IOOptionBits * options,
1136				IOMemoryDescriptor ** memory )
1137{
1138    return( kIOReturnUnsupported);
1139}
1140
1141#if !__LP64__
1142IOMemoryMap * IOUserClient::mapClientMemory(
1143	IOOptionBits		type,
1144	task_t			task,
1145	IOOptionBits		mapFlags,
1146	IOVirtualAddress	atAddress )
1147{
1148    return (NULL);
1149}
1150#endif
1151
1152IOMemoryMap * IOUserClient::mapClientMemory64(
1153	IOOptionBits		type,
1154	task_t			task,
1155	IOOptionBits		mapFlags,
1156	mach_vm_address_t	atAddress )
1157{
1158    IOReturn		err;
1159    IOOptionBits	options = 0;
1160    IOMemoryDescriptor * memory;
1161    IOMemoryMap *	map = 0;
1162
1163    err = clientMemoryForType( (UInt32) type, &options, &memory );
1164
1165    if( memory && (kIOReturnSuccess == err)) {
1166
1167        options = (options & ~kIOMapUserOptionsMask)
1168		| (mapFlags & kIOMapUserOptionsMask);
1169	map = memory->createMappingInTask( task, atAddress, options );
1170	memory->release();
1171    }
1172
1173    return( map );
1174}
1175
1176IOReturn IOUserClient::exportObjectToClient(task_t task,
1177			OSObject *obj, io_object_t *clientObj)
1178{
1179    mach_port_name_t	name;
1180
1181    name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT );
1182    assert( name );
1183
1184    *(mach_port_name_t *)clientObj = name;
1185    return kIOReturnSuccess;
1186}
1187
1188IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
1189{
1190    return( 0 );
1191}
1192
1193IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */)
1194{
1195    return( 0 );
1196}
1197
1198IOExternalMethod * IOUserClient::
1199getTargetAndMethodForIndex(IOService **targetP, UInt32 index)
1200{
1201    IOExternalMethod *method = getExternalMethodForIndex(index);
1202
1203    if (method)
1204        *targetP = (IOService *) method->object;
1205
1206    return method;
1207}
1208
1209IOExternalAsyncMethod * IOUserClient::
1210getAsyncTargetAndMethodForIndex(IOService ** targetP, UInt32 index)
1211{
1212    IOExternalAsyncMethod *method = getExternalAsyncMethodForIndex(index);
1213
1214    if (method)
1215        *targetP = (IOService *) method->object;
1216
1217    return method;
1218}
1219
1220IOExternalTrap * IOUserClient::
1221getExternalTrapForIndex(UInt32 index)
1222{
1223	return NULL;
1224}
1225
1226IOExternalTrap * IOUserClient::
1227getTargetAndTrapForIndex(IOService ** targetP, UInt32 index)
1228{
1229      IOExternalTrap *trap = getExternalTrapForIndex(index);
1230
1231      if (trap) {
1232              *targetP = trap->object;
1233      }
1234
1235      return trap;
1236}
1237
1238IOReturn IOUserClient::releaseAsyncReference64(OSAsyncReference64 reference)
1239{
1240    mach_port_t port;
1241    port = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags);
1242
1243    if (MACH_PORT_NULL != port)
1244	iokit_release_port_send(port);
1245
1246    return (kIOReturnSuccess);
1247}
1248
1249IOReturn IOUserClient::releaseNotificationPort(mach_port_t port)
1250{
1251    if (MACH_PORT_NULL != port)
1252	iokit_release_port_send(port);
1253
1254    return (kIOReturnSuccess);
1255}
1256
1257IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference,
1258                                       IOReturn result, void *args[], UInt32 numArgs)
1259{
1260    OSAsyncReference64  reference64;
1261    io_user_reference_t args64[kMaxAsyncArgs];
1262    unsigned int        idx;
1263
1264    if (numArgs > kMaxAsyncArgs)
1265        return kIOReturnMessageTooLarge;
1266
1267    for (idx = 0; idx < kOSAsyncRef64Count; idx++)
1268	reference64[idx] = REF64(reference[idx]);
1269
1270    for (idx = 0; idx < numArgs; idx++)
1271	args64[idx] = REF64(args[idx]);
1272
1273    return (sendAsyncResult64(reference64, result, args64, numArgs));
1274}
1275
1276IOReturn IOUserClient::sendAsyncResult64(OSAsyncReference64 reference,
1277                                        IOReturn result, io_user_reference_t args[], UInt32 numArgs)
1278{
1279    struct ReplyMsg
1280    {
1281	mach_msg_header_t msgHdr;
1282	union
1283	{
1284	    struct
1285	    {
1286		OSNotificationHeader	 notifyHdr;
1287		IOAsyncCompletionContent asyncContent;
1288		uint32_t		 args[kMaxAsyncArgs];
1289	    } msg32;
1290	    struct
1291	    {
1292		OSNotificationHeader64	 notifyHdr;
1293		IOAsyncCompletionContent asyncContent;
1294		io_user_reference_t	 args[kMaxAsyncArgs] __attribute__ ((packed));
1295	    } msg64;
1296	} m;
1297    };
1298    ReplyMsg      replyMsg;
1299    mach_port_t	  replyPort;
1300    kern_return_t kr;
1301
1302    // If no reply port, do nothing.
1303    replyPort = (mach_port_t) (reference[0] & ~kIOUCAsync0Flags);
1304    if (replyPort == MACH_PORT_NULL)
1305        return kIOReturnSuccess;
1306
1307    if (numArgs > kMaxAsyncArgs)
1308        return kIOReturnMessageTooLarge;
1309
1310    replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND /*remote*/,
1311						0 /*local*/);
1312    replyMsg.msgHdr.msgh_remote_port = replyPort;
1313    replyMsg.msgHdr.msgh_local_port  = 0;
1314    replyMsg.msgHdr.msgh_id          = kOSNotificationMessageID;
1315    if (kIOUCAsync64Flag & reference[0])
1316    {
1317	replyMsg.msgHdr.msgh_size =
1318	    sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg64)
1319	    - (kMaxAsyncArgs - numArgs) * sizeof(io_user_reference_t);
1320	replyMsg.m.msg64.notifyHdr.size = sizeof(IOAsyncCompletionContent)
1321					+ numArgs * sizeof(io_user_reference_t);
1322	replyMsg.m.msg64.notifyHdr.type = kIOAsyncCompletionNotificationType;
1323	bcopy(reference, replyMsg.m.msg64.notifyHdr.reference, sizeof(OSAsyncReference64));
1324
1325	replyMsg.m.msg64.asyncContent.result = result;
1326	if (numArgs)
1327	    bcopy(args, replyMsg.m.msg64.args, numArgs * sizeof(io_user_reference_t));
1328    }
1329    else
1330    {
1331	unsigned int idx;
1332
1333	replyMsg.msgHdr.msgh_size =
1334	    sizeof(replyMsg.msgHdr) + sizeof(replyMsg.m.msg32)
1335	    - (kMaxAsyncArgs - numArgs) * sizeof(uint32_t);
1336
1337	replyMsg.m.msg32.notifyHdr.size = sizeof(IOAsyncCompletionContent)
1338					+ numArgs * sizeof(uint32_t);
1339	replyMsg.m.msg32.notifyHdr.type = kIOAsyncCompletionNotificationType;
1340
1341	for (idx = 0; idx < kOSAsyncRefCount; idx++)
1342	    replyMsg.m.msg32.notifyHdr.reference[idx] = REF32(reference[idx]);
1343
1344	replyMsg.m.msg32.asyncContent.result = result;
1345
1346	for (idx = 0; idx < numArgs; idx++)
1347	    replyMsg.m.msg32.args[idx] = REF32(args[idx]);
1348    }
1349
1350     kr = mach_msg_send_from_kernel_proper( &replyMsg.msgHdr,
1351            replyMsg.msgHdr.msgh_size);
1352    if( KERN_SUCCESS != kr)
1353        IOLog("%s: mach_msg_send_from_kernel_proper {%x}\n", __FILE__, kr );
1354    return kr;
1355}
1356
1357
1358/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1359
1360extern "C" {
1361
1362#define CHECK(cls,obj,out)			\
1363	cls * out;				\
1364	if( !(out = OSDynamicCast( cls, obj)))	\
1365	    return( kIOReturnBadArgument )
1366
1367/* Routine io_object_get_class */
1368kern_return_t is_io_object_get_class(
1369	io_object_t object,
1370	io_name_t className )
1371{
1372	const OSMetaClass* my_obj = NULL;
1373
1374	if( !object)
1375		return( kIOReturnBadArgument );
1376
1377	my_obj = object->getMetaClass();
1378	if (!my_obj) {
1379		return (kIOReturnNotFound);
1380	}
1381
1382    strlcpy( className, my_obj->getClassName(), sizeof(io_name_t));
1383    return( kIOReturnSuccess );
1384}
1385
1386/* Routine io_object_get_superclass */
1387kern_return_t is_io_object_get_superclass(
1388	mach_port_t master_port,
1389	io_name_t obj_name,
1390	io_name_t class_name)
1391{
1392	const OSMetaClass* my_obj = NULL;
1393	const OSMetaClass* superclass = NULL;
1394	const OSSymbol *my_name = NULL;
1395	const char *my_cstr = NULL;
1396
1397	if (!obj_name || !class_name)
1398		return (kIOReturnBadArgument);
1399
1400    if( master_port != master_device_port)
1401        return( kIOReturnNotPrivileged);
1402
1403	my_name = OSSymbol::withCString(obj_name);
1404
1405	if (my_name) {
1406		my_obj = OSMetaClass::getMetaClassWithName(my_name);
1407		my_name->release();
1408	}
1409	if (my_obj) {
1410		superclass = my_obj->getSuperClass();
1411	}
1412
1413	if (!superclass)  {
1414		return( kIOReturnNotFound );
1415	}
1416
1417	my_cstr = superclass->getClassName();
1418
1419	if (my_cstr) {
1420		strlcpy(class_name, my_cstr, sizeof(io_name_t));
1421		return( kIOReturnSuccess );
1422	}
1423	return (kIOReturnNotFound);
1424}
1425
1426/* Routine io_object_get_bundle_identifier */
1427kern_return_t is_io_object_get_bundle_identifier(
1428	mach_port_t master_port,
1429	io_name_t obj_name,
1430	io_name_t bundle_name)
1431{
1432	const OSMetaClass* my_obj = NULL;
1433	const OSSymbol *my_name = NULL;
1434	const OSSymbol *identifier = NULL;
1435	const char *my_cstr = NULL;
1436
1437	if (!obj_name || !bundle_name)
1438		return (kIOReturnBadArgument);
1439
1440    if( master_port != master_device_port)
1441        return( kIOReturnNotPrivileged);
1442
1443	my_name = OSSymbol::withCString(obj_name);
1444
1445	if (my_name) {
1446		my_obj = OSMetaClass::getMetaClassWithName(my_name);
1447		my_name->release();
1448	}
1449
1450	if (my_obj) {
1451		identifier = my_obj->getKmodName();
1452	}
1453	if (!identifier) {
1454		return( kIOReturnNotFound );
1455	}
1456
1457	my_cstr = identifier->getCStringNoCopy();
1458	if (my_cstr) {
1459		strlcpy(bundle_name, identifier->getCStringNoCopy(), sizeof(io_name_t));
1460		return( kIOReturnSuccess );
1461	}
1462
1463	return (kIOReturnBadArgument);
1464}
1465
1466/* Routine io_object_conforms_to */
1467kern_return_t is_io_object_conforms_to(
1468	io_object_t object,
1469	io_name_t className,
1470	boolean_t *conforms )
1471{
1472    if( !object)
1473        return( kIOReturnBadArgument );
1474
1475    *conforms = (0 != object->metaCast( className ));
1476    return( kIOReturnSuccess );
1477}
1478
1479/* Routine io_object_get_retain_count */
1480kern_return_t is_io_object_get_retain_count(
1481	io_object_t object,
1482	uint32_t *retainCount )
1483{
1484    if( !object)
1485        return( kIOReturnBadArgument );
1486
1487    *retainCount = object->getRetainCount();
1488    return( kIOReturnSuccess );
1489}
1490
1491/* Routine io_iterator_next */
1492kern_return_t is_io_iterator_next(
1493	io_object_t iterator,
1494	io_object_t *object )
1495{
1496    OSObject *	obj;
1497
1498    CHECK( OSIterator, iterator, iter );
1499
1500    obj = iter->getNextObject();
1501    if( obj) {
1502	obj->retain();
1503	*object = obj;
1504        return( kIOReturnSuccess );
1505    } else
1506        return( kIOReturnNoDevice );
1507}
1508
1509/* Routine io_iterator_reset */
1510kern_return_t is_io_iterator_reset(
1511	io_object_t iterator )
1512{
1513    CHECK( OSIterator, iterator, iter );
1514
1515    iter->reset();
1516
1517    return( kIOReturnSuccess );
1518}
1519
1520/* Routine io_iterator_is_valid */
1521kern_return_t is_io_iterator_is_valid(
1522	io_object_t iterator,
1523	boolean_t *is_valid )
1524{
1525    CHECK( OSIterator, iterator, iter );
1526
1527    *is_valid = iter->isValid();
1528
1529    return( kIOReturnSuccess );
1530}
1531
1532/* Routine io_service_match_property_table */
1533kern_return_t is_io_service_match_property_table(
1534	io_service_t _service,
1535	io_string_t matching,
1536	boolean_t *matches )
1537{
1538    CHECK( IOService, _service, service );
1539
1540    kern_return_t	kr;
1541    OSObject *		obj;
1542    OSDictionary *	dict;
1543
1544    obj = OSUnserializeXML( matching );
1545
1546    if( (dict = OSDynamicCast( OSDictionary, obj))) {
1547        *matches = service->passiveMatch( dict );
1548	kr = kIOReturnSuccess;
1549    } else
1550	kr = kIOReturnBadArgument;
1551
1552    if( obj)
1553        obj->release();
1554
1555    return( kr );
1556}
1557
1558/* Routine io_service_match_property_table_ool */
1559kern_return_t is_io_service_match_property_table_ool(
1560	io_object_t service,
1561	io_buf_ptr_t matching,
1562	mach_msg_type_number_t matchingCnt,
1563	kern_return_t *result,
1564	boolean_t *matches )
1565{
1566    kern_return_t	  kr;
1567    vm_offset_t 	  data;
1568    vm_map_offset_t	  map_data;
1569
1570    kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1571    data = CAST_DOWN(vm_offset_t, map_data);
1572
1573    if( KERN_SUCCESS == kr) {
1574        // must return success after vm_map_copyout() succeeds
1575	*result = is_io_service_match_property_table( service,
1576		(char *) data, matches );
1577	vm_deallocate( kernel_map, data, matchingCnt );
1578    }
1579
1580    return( kr );
1581}
1582
1583/* Routine io_service_get_matching_services */
1584kern_return_t is_io_service_get_matching_services(
1585	mach_port_t master_port,
1586	io_string_t matching,
1587	io_iterator_t *existing )
1588{
1589    kern_return_t	kr;
1590    OSObject *		obj;
1591    OSDictionary *	dict;
1592
1593    if( master_port != master_device_port)
1594        return( kIOReturnNotPrivileged);
1595
1596    obj = OSUnserializeXML( matching );
1597
1598    if( (dict = OSDynamicCast( OSDictionary, obj))) {
1599        *existing = IOService::getMatchingServices( dict );
1600	kr = kIOReturnSuccess;
1601    } else
1602	kr = kIOReturnBadArgument;
1603
1604    if( obj)
1605        obj->release();
1606
1607    return( kr );
1608}
1609
1610/* Routine io_service_get_matching_services_ool */
1611kern_return_t is_io_service_get_matching_services_ool(
1612	mach_port_t master_port,
1613	io_buf_ptr_t matching,
1614	mach_msg_type_number_t matchingCnt,
1615	kern_return_t *result,
1616	io_object_t *existing )
1617{
1618    kern_return_t	kr;
1619    vm_offset_t 	data;
1620    vm_map_offset_t	map_data;
1621
1622    kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1623    data = CAST_DOWN(vm_offset_t, map_data);
1624
1625    if( KERN_SUCCESS == kr) {
1626        // must return success after vm_map_copyout() succeeds
1627	*result = is_io_service_get_matching_services( master_port,
1628			(char *) data, existing );
1629	vm_deallocate( kernel_map, data, matchingCnt );
1630    }
1631
1632    return( kr );
1633}
1634
1635
1636/* Routine io_service_get_matching_service */
1637kern_return_t is_io_service_get_matching_service(
1638	mach_port_t master_port,
1639	io_string_t matching,
1640	io_service_t *service )
1641{
1642    kern_return_t	kr;
1643    OSObject *		obj;
1644    OSDictionary *	dict;
1645
1646    if( master_port != master_device_port)
1647        return( kIOReturnNotPrivileged);
1648
1649    obj = OSUnserializeXML( matching );
1650
1651    if( (dict = OSDynamicCast( OSDictionary, obj))) {
1652        *service = IOService::copyMatchingService( dict );
1653	kr = *service ? kIOReturnSuccess : kIOReturnNotFound;
1654    } else
1655	kr = kIOReturnBadArgument;
1656
1657    if( obj)
1658        obj->release();
1659
1660    return( kr );
1661}
1662
1663/* Routine io_service_get_matching_services_ool */
1664kern_return_t is_io_service_get_matching_service_ool(
1665	mach_port_t master_port,
1666	io_buf_ptr_t matching,
1667	mach_msg_type_number_t matchingCnt,
1668	kern_return_t *result,
1669	io_object_t *service )
1670{
1671    kern_return_t	kr;
1672    vm_offset_t 	data;
1673    vm_map_offset_t	map_data;
1674
1675    kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1676    data = CAST_DOWN(vm_offset_t, map_data);
1677
1678    if( KERN_SUCCESS == kr) {
1679        // must return success after vm_map_copyout() succeeds
1680	*result = is_io_service_get_matching_service( master_port,
1681			(char *) data, service );
1682	vm_deallocate( kernel_map, data, matchingCnt );
1683    }
1684
1685    return( kr );
1686}
1687
1688
1689static kern_return_t internal_io_service_add_notification(
1690	mach_port_t master_port,
1691	io_name_t notification_type,
1692	io_string_t matching,
1693	mach_port_t port,
1694	void * reference,
1695	vm_size_t referenceSize,
1696	bool client64,
1697	io_object_t * notification )
1698{
1699    IOServiceUserNotification *	userNotify = 0;
1700    IONotifier *		notify = 0;
1701    const OSSymbol *		sym;
1702    OSDictionary *		dict;
1703    IOReturn			err;
1704    unsigned long int		userMsgType;
1705
1706
1707    if( master_port != master_device_port)
1708        return( kIOReturnNotPrivileged);
1709
1710    do {
1711        err = kIOReturnNoResources;
1712
1713        if( !(sym = OSSymbol::withCString( notification_type )))
1714	    err = kIOReturnNoResources;
1715
1716        if( !(dict = OSDynamicCast( OSDictionary,
1717                    OSUnserializeXML( matching )))) {
1718            err = kIOReturnBadArgument;
1719	    continue;
1720	}
1721
1722	if( (sym == gIOPublishNotification)
1723	 || (sym == gIOFirstPublishNotification))
1724	    userMsgType = kIOServicePublishNotificationType;
1725	else if( (sym == gIOMatchedNotification)
1726	      || (sym == gIOFirstMatchNotification))
1727	    userMsgType = kIOServiceMatchedNotificationType;
1728	else if( sym == gIOTerminatedNotification)
1729	    userMsgType = kIOServiceTerminatedNotificationType;
1730	else
1731	    userMsgType = kLastIOKitNotificationType;
1732
1733        userNotify = new IOServiceUserNotification;
1734
1735        if( userNotify && !userNotify->init( port, userMsgType,
1736                                             reference, referenceSize, client64)) {
1737			iokit_release_port_send(port);
1738            userNotify->release();
1739            userNotify = 0;
1740        }
1741        if( !userNotify)
1742	    continue;
1743
1744        notify = IOService::addMatchingNotification( sym, dict,
1745                                             &userNotify->_handler, userNotify );
1746	if( notify) {
1747            *notification = userNotify;
1748	    userNotify->setNotification( notify );
1749	    err = kIOReturnSuccess;
1750	} else
1751	    err = kIOReturnUnsupported;
1752
1753    } while( false );
1754
1755    if( sym)
1756	sym->release();
1757    if( dict)
1758	dict->release();
1759
1760    return( err );
1761}
1762
1763
1764/* Routine io_service_add_notification */
1765kern_return_t is_io_service_add_notification(
1766	mach_port_t master_port,
1767	io_name_t notification_type,
1768	io_string_t matching,
1769	mach_port_t port,
1770	io_async_ref_t reference,
1771	mach_msg_type_number_t referenceCnt,
1772	io_object_t * notification )
1773{
1774    return (internal_io_service_add_notification(master_port, notification_type,
1775		matching, port, &reference[0], sizeof(io_async_ref_t),
1776		false, notification));
1777}
1778
1779/* Routine io_service_add_notification_64 */
1780kern_return_t is_io_service_add_notification_64(
1781	mach_port_t master_port,
1782	io_name_t notification_type,
1783	io_string_t matching,
1784	mach_port_t wake_port,
1785	io_async_ref64_t reference,
1786	mach_msg_type_number_t referenceCnt,
1787	io_object_t *notification )
1788{
1789    return (internal_io_service_add_notification(master_port, notification_type,
1790		matching, wake_port, &reference[0], sizeof(io_async_ref64_t),
1791		true, notification));
1792}
1793
1794
1795static kern_return_t internal_io_service_add_notification_ool(
1796	mach_port_t master_port,
1797	io_name_t notification_type,
1798	io_buf_ptr_t matching,
1799	mach_msg_type_number_t matchingCnt,
1800	mach_port_t wake_port,
1801	void * reference,
1802	vm_size_t referenceSize,
1803	bool client64,
1804	kern_return_t *result,
1805	io_object_t *notification )
1806{
1807    kern_return_t	kr;
1808    vm_offset_t 	data;
1809    vm_map_offset_t	map_data;
1810
1811    kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
1812    data = CAST_DOWN(vm_offset_t, map_data);
1813
1814    if( KERN_SUCCESS == kr) {
1815        // must return success after vm_map_copyout() succeeds
1816	*result = internal_io_service_add_notification( master_port, notification_type,
1817			(char *) data, wake_port, reference, referenceSize, client64, notification );
1818	vm_deallocate( kernel_map, data, matchingCnt );
1819    }
1820
1821    return( kr );
1822}
1823
1824/* Routine io_service_add_notification_ool */
1825kern_return_t is_io_service_add_notification_ool(
1826	mach_port_t master_port,
1827	io_name_t notification_type,
1828	io_buf_ptr_t matching,
1829	mach_msg_type_number_t matchingCnt,
1830	mach_port_t wake_port,
1831	io_async_ref_t reference,
1832	mach_msg_type_number_t referenceCnt,
1833	kern_return_t *result,
1834	io_object_t *notification )
1835{
1836    return (internal_io_service_add_notification_ool(master_port, notification_type,
1837		matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref_t),
1838		false, result, notification));
1839}
1840
1841/* Routine io_service_add_notification_ool_64 */
1842kern_return_t is_io_service_add_notification_ool_64(
1843	mach_port_t master_port,
1844	io_name_t notification_type,
1845	io_buf_ptr_t matching,
1846	mach_msg_type_number_t matchingCnt,
1847	mach_port_t wake_port,
1848	io_async_ref64_t reference,
1849	mach_msg_type_number_t referenceCnt,
1850	kern_return_t *result,
1851	io_object_t *notification )
1852{
1853    return (internal_io_service_add_notification_ool(master_port, notification_type,
1854		matching, matchingCnt, wake_port, &reference[0], sizeof(io_async_ref64_t),
1855		true, result, notification));
1856}
1857
1858/* Routine io_service_add_notification_old */
1859kern_return_t is_io_service_add_notification_old(
1860	mach_port_t master_port,
1861	io_name_t notification_type,
1862	io_string_t matching,
1863	mach_port_t port,
1864	// for binary compatibility reasons, this must be natural_t for ILP32
1865	natural_t ref,
1866	io_object_t * notification )
1867{
1868    return( is_io_service_add_notification( master_port, notification_type,
1869            matching, port, &ref, 1, notification ));
1870}
1871
1872
1873static kern_return_t internal_io_service_add_interest_notification(
1874        io_object_t _service,
1875        io_name_t type_of_interest,
1876        mach_port_t port,
1877	void * reference,
1878	vm_size_t referenceSize,
1879	bool client64,
1880        io_object_t * notification )
1881{
1882
1883    IOServiceMessageUserNotification *	userNotify = 0;
1884    IONotifier *			notify = 0;
1885    const OSSymbol *			sym;
1886    IOReturn				err;
1887
1888    CHECK( IOService, _service, service );
1889
1890    err = kIOReturnNoResources;
1891    if( (sym = OSSymbol::withCString( type_of_interest ))) do {
1892
1893        userNotify = new IOServiceMessageUserNotification;
1894
1895        if( userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
1896                                             reference, referenceSize,
1897					     kIOUserNotifyMaxMessageSize,
1898					     client64 )) {
1899			iokit_release_port_send(port);
1900            userNotify->release();
1901            userNotify = 0;
1902        }
1903        if( !userNotify)
1904            continue;
1905
1906        notify = service->registerInterest( sym,
1907                                    &userNotify->_handler, userNotify );
1908        if( notify) {
1909            *notification = userNotify;
1910            userNotify->setNotification( notify );
1911            err = kIOReturnSuccess;
1912        } else
1913            err = kIOReturnUnsupported;
1914
1915	sym->release();
1916
1917    } while( false );
1918
1919    return( err );
1920}
1921
1922/* Routine io_service_add_message_notification */
1923kern_return_t is_io_service_add_interest_notification(
1924        io_object_t service,
1925        io_name_t type_of_interest,
1926        mach_port_t port,
1927	io_async_ref_t reference,
1928	mach_msg_type_number_t referenceCnt,
1929        io_object_t * notification )
1930{
1931    return (internal_io_service_add_interest_notification(service, type_of_interest,
1932		    port, &reference[0], sizeof(io_async_ref_t), false, notification));
1933}
1934
1935/* Routine io_service_add_interest_notification_64 */
1936kern_return_t is_io_service_add_interest_notification_64(
1937	io_object_t service,
1938	io_name_t type_of_interest,
1939	mach_port_t wake_port,
1940	io_async_ref64_t reference,
1941	mach_msg_type_number_t referenceCnt,
1942	io_object_t *notification )
1943{
1944    return (internal_io_service_add_interest_notification(service, type_of_interest,
1945		    wake_port, &reference[0], sizeof(io_async_ref64_t), true, notification));
1946}
1947
1948
1949/* Routine io_service_acknowledge_notification */
1950kern_return_t is_io_service_acknowledge_notification(
1951	io_object_t _service,
1952	natural_t notify_ref,
1953	natural_t response )
1954{
1955    CHECK( IOService, _service, service );
1956
1957    return( service->acknowledgeNotification( (IONotificationRef) notify_ref,
1958                                              (IOOptionBits) response ));
1959
1960}
1961
1962/* Routine io_connect_get_semaphore */
1963kern_return_t is_io_connect_get_notification_semaphore(
1964	io_connect_t connection,
1965	natural_t notification_type,
1966	semaphore_t *semaphore )
1967{
1968    CHECK( IOUserClient, connection, client );
1969
1970    IOStatisticsClientCall();
1971    return( client->getNotificationSemaphore( (UInt32) notification_type,
1972                                              semaphore ));
1973}
1974
1975/* Routine io_registry_get_root_entry */
1976kern_return_t is_io_registry_get_root_entry(
1977	mach_port_t master_port,
1978	io_object_t *root )
1979{
1980    IORegistryEntry *	entry;
1981
1982    if( master_port != master_device_port)
1983        return( kIOReturnNotPrivileged);
1984
1985    entry = IORegistryEntry::getRegistryRoot();
1986    if( entry)
1987	entry->retain();
1988    *root = entry;
1989
1990    return( kIOReturnSuccess );
1991}
1992
1993/* Routine io_registry_create_iterator */
1994kern_return_t is_io_registry_create_iterator(
1995	mach_port_t master_port,
1996	io_name_t plane,
1997	uint32_t options,
1998	io_object_t *iterator )
1999{
2000    if( master_port != master_device_port)
2001        return( kIOReturnNotPrivileged);
2002
2003    *iterator = IORegistryIterator::iterateOver(
2004	IORegistryEntry::getPlane( plane ), options );
2005
2006    return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
2007}
2008
2009/* Routine io_registry_entry_create_iterator */
2010kern_return_t is_io_registry_entry_create_iterator(
2011	io_object_t registry_entry,
2012	io_name_t plane,
2013	uint32_t options,
2014	io_object_t *iterator )
2015{
2016    CHECK( IORegistryEntry, registry_entry, entry );
2017
2018    *iterator = IORegistryIterator::iterateOver( entry,
2019	IORegistryEntry::getPlane( plane ), options );
2020
2021    return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
2022}
2023
2024/* Routine io_registry_iterator_enter */
2025kern_return_t is_io_registry_iterator_enter_entry(
2026	io_object_t iterator )
2027{
2028    CHECK( IORegistryIterator, iterator, iter );
2029
2030    iter->enterEntry();
2031
2032    return( kIOReturnSuccess );
2033}
2034
2035/* Routine io_registry_iterator_exit */
2036kern_return_t is_io_registry_iterator_exit_entry(
2037	io_object_t iterator )
2038{
2039    bool	didIt;
2040
2041    CHECK( IORegistryIterator, iterator, iter );
2042
2043    didIt = iter->exitEntry();
2044
2045    return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
2046}
2047
2048/* Routine io_registry_entry_from_path */
2049kern_return_t is_io_registry_entry_from_path(
2050	mach_port_t master_port,
2051	io_string_t path,
2052	io_object_t *registry_entry )
2053{
2054    IORegistryEntry *	entry;
2055
2056    if( master_port != master_device_port)
2057        return( kIOReturnNotPrivileged);
2058
2059    entry = IORegistryEntry::fromPath( path );
2060
2061    *registry_entry = entry;
2062
2063    return( kIOReturnSuccess );
2064}
2065
2066/* Routine io_registry_entry_in_plane */
2067kern_return_t is_io_registry_entry_in_plane(
2068	io_object_t registry_entry,
2069	io_name_t plane,
2070	boolean_t *inPlane )
2071{
2072    CHECK( IORegistryEntry, registry_entry, entry );
2073
2074    *inPlane = entry->inPlane( IORegistryEntry::getPlane( plane ));
2075
2076    return( kIOReturnSuccess );
2077}
2078
2079
2080/* Routine io_registry_entry_get_path */
2081kern_return_t is_io_registry_entry_get_path(
2082	io_object_t registry_entry,
2083	io_name_t plane,
2084	io_string_t path )
2085{
2086    int		length;
2087    CHECK( IORegistryEntry, registry_entry, entry );
2088
2089    length = sizeof( io_string_t);
2090    if( entry->getPath( path, &length, IORegistryEntry::getPlane( plane )))
2091	return( kIOReturnSuccess );
2092    else
2093	return( kIOReturnBadArgument );
2094}
2095
2096
2097/* Routine io_registry_entry_get_name */
2098kern_return_t is_io_registry_entry_get_name(
2099	io_object_t registry_entry,
2100	io_name_t name )
2101{
2102    CHECK( IORegistryEntry, registry_entry, entry );
2103
2104    strncpy( name, entry->getName(), sizeof( io_name_t));
2105
2106    return( kIOReturnSuccess );
2107}
2108
2109/* Routine io_registry_entry_get_name_in_plane */
2110kern_return_t is_io_registry_entry_get_name_in_plane(
2111	io_object_t registry_entry,
2112	io_name_t planeName,
2113	io_name_t name )
2114{
2115    const IORegistryPlane * plane;
2116    CHECK( IORegistryEntry, registry_entry, entry );
2117
2118    if( planeName[0])
2119        plane = IORegistryEntry::getPlane( planeName );
2120    else
2121        plane = 0;
2122
2123    strncpy( name, entry->getName( plane), sizeof( io_name_t));
2124
2125    return( kIOReturnSuccess );
2126}
2127
2128/* Routine io_registry_entry_get_location_in_plane */
2129kern_return_t is_io_registry_entry_get_location_in_plane(
2130	io_object_t registry_entry,
2131	io_name_t planeName,
2132	io_name_t location )
2133{
2134    const IORegistryPlane * plane;
2135    CHECK( IORegistryEntry, registry_entry, entry );
2136
2137    if( planeName[0])
2138        plane = IORegistryEntry::getPlane( planeName );
2139    else
2140        plane = 0;
2141
2142    const char * cstr = entry->getLocation( plane );
2143
2144    if( cstr) {
2145        strncpy( location, cstr, sizeof( io_name_t));
2146        return( kIOReturnSuccess );
2147    } else
2148        return( kIOReturnNotFound );
2149}
2150
2151/* Routine io_registry_entry_get_registry_entry_id */
2152kern_return_t is_io_registry_entry_get_registry_entry_id(
2153	io_object_t registry_entry,
2154	uint64_t *entry_id )
2155{
2156    CHECK( IORegistryEntry, registry_entry, entry );
2157
2158    *entry_id = entry->getRegistryEntryID();
2159
2160    return (kIOReturnSuccess);
2161}
2162
2163// Create a vm_map_copy_t or kalloc'ed data for memory
2164// to be copied out. ipc will free after the copyout.
2165
2166static kern_return_t copyoutkdata( const void * data, vm_size_t len,
2167                                    io_buf_ptr_t * buf )
2168{
2169    kern_return_t	err;
2170    vm_map_copy_t	copy;
2171
2172    err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
2173                    false /* src_destroy */, &copy);
2174
2175    assert( err == KERN_SUCCESS );
2176    if( err == KERN_SUCCESS )
2177        *buf = (char *) copy;
2178
2179    return( err );
2180}
2181
2182/* Routine io_registry_entry_get_property */
2183kern_return_t is_io_registry_entry_get_property_bytes(
2184	io_object_t registry_entry,
2185	io_name_t property_name,
2186	io_struct_inband_t buf,
2187	mach_msg_type_number_t *dataCnt )
2188{
2189    OSObject	*	obj;
2190    OSData 	*	data;
2191    OSString 	*	str;
2192    OSBoolean	*	boo;
2193    OSNumber 	*	off;
2194    UInt64		offsetBytes;
2195    unsigned int	len = 0;
2196    const void *	bytes = 0;
2197    IOReturn		ret = kIOReturnSuccess;
2198
2199    CHECK( IORegistryEntry, registry_entry, entry );
2200
2201    obj = entry->copyProperty(property_name);
2202    if( !obj)
2203        return( kIOReturnNoResources );
2204
2205    // One day OSData will be a common container base class
2206    // until then...
2207    if( (data = OSDynamicCast( OSData, obj ))) {
2208	len = data->getLength();
2209	bytes = data->getBytesNoCopy();
2210
2211    } else if( (str = OSDynamicCast( OSString, obj ))) {
2212	len = str->getLength() + 1;
2213	bytes = str->getCStringNoCopy();
2214
2215    } else if( (boo = OSDynamicCast( OSBoolean, obj ))) {
2216	len = boo->isTrue() ? sizeof("Yes") : sizeof("No");
2217	bytes = boo->isTrue() ? "Yes" : "No";
2218
2219    } else if( (off = OSDynamicCast( OSNumber, obj ))) {
2220	offsetBytes = off->unsigned64BitValue();
2221	len = off->numberOfBytes();
2222	bytes = &offsetBytes;
2223#ifdef __BIG_ENDIAN__
2224	bytes = (const void *)
2225		(((UInt32) bytes) + (sizeof( UInt64) - len));
2226#endif
2227
2228    } else
2229	ret = kIOReturnBadArgument;
2230
2231    if( bytes) {
2232	if( *dataCnt < len)
2233	    ret = kIOReturnIPCError;
2234	else {
2235            *dataCnt = len;
2236            bcopy( bytes, buf, len );
2237	}
2238    }
2239    obj->release();
2240
2241    return( ret );
2242}
2243
2244
2245/* Routine io_registry_entry_get_property */
2246kern_return_t is_io_registry_entry_get_property(
2247	io_object_t registry_entry,
2248	io_name_t property_name,
2249	io_buf_ptr_t *properties,
2250	mach_msg_type_number_t *propertiesCnt )
2251{
2252    kern_return_t	err;
2253    vm_size_t 		len;
2254    OSObject *		obj;
2255
2256    CHECK( IORegistryEntry, registry_entry, entry );
2257
2258    obj = entry->copyProperty(property_name);
2259    if( !obj)
2260        return( kIOReturnNotFound );
2261
2262    OSSerialize * s = OSSerialize::withCapacity(4096);
2263    if( !s) {
2264        obj->release();
2265	return( kIOReturnNoMemory );
2266    }
2267    s->clearText();
2268
2269    if( obj->serialize( s )) {
2270        len = s->getLength();
2271        *propertiesCnt = len;
2272        err = copyoutkdata( s->text(), len, properties );
2273
2274    } else
2275        err = kIOReturnUnsupported;
2276
2277    s->release();
2278    obj->release();
2279
2280    return( err );
2281}
2282
2283/* Routine io_registry_entry_get_property_recursively */
2284kern_return_t is_io_registry_entry_get_property_recursively(
2285	io_object_t registry_entry,
2286	io_name_t plane,
2287	io_name_t property_name,
2288        uint32_t options,
2289	io_buf_ptr_t *properties,
2290	mach_msg_type_number_t *propertiesCnt )
2291{
2292    kern_return_t	err;
2293    vm_size_t 		len;
2294    OSObject *		obj;
2295
2296    CHECK( IORegistryEntry, registry_entry, entry );
2297
2298    obj = entry->copyProperty( property_name,
2299                               IORegistryEntry::getPlane( plane ), options);
2300    if( !obj)
2301        return( kIOReturnNotFound );
2302
2303    OSSerialize * s = OSSerialize::withCapacity(4096);
2304    if( !s) {
2305        obj->release();
2306	return( kIOReturnNoMemory );
2307    }
2308
2309    s->clearText();
2310
2311    if( obj->serialize( s )) {
2312        len = s->getLength();
2313        *propertiesCnt = len;
2314        err = copyoutkdata( s->text(), len, properties );
2315
2316    } else
2317        err = kIOReturnUnsupported;
2318
2319    s->release();
2320    obj->release();
2321
2322    return( err );
2323}
2324
2325/* Routine io_registry_entry_get_properties */
2326kern_return_t is_io_registry_entry_get_properties(
2327	io_object_t registry_entry,
2328	io_buf_ptr_t *properties,
2329	mach_msg_type_number_t *propertiesCnt )
2330{
2331    kern_return_t	err;
2332    vm_size_t 		len;
2333
2334    CHECK( IORegistryEntry, registry_entry, entry );
2335
2336    OSSerialize * s = OSSerialize::withCapacity(4096);
2337    if( !s)
2338	return( kIOReturnNoMemory );
2339
2340    s->clearText();
2341
2342    if( entry->serializeProperties( s )) {
2343        len = s->getLength();
2344        *propertiesCnt = len;
2345        err = copyoutkdata( s->text(), len, properties );
2346
2347    } else
2348        err = kIOReturnUnsupported;
2349
2350    s->release();
2351
2352    return( err );
2353}
2354
2355/* Routine io_registry_entry_set_properties */
2356kern_return_t is_io_registry_entry_set_properties
2357(
2358	io_object_t registry_entry,
2359	io_buf_ptr_t properties,
2360	mach_msg_type_number_t propertiesCnt,
2361        kern_return_t * result)
2362{
2363    OSObject *		obj;
2364    kern_return_t	err;
2365    IOReturn		res;
2366    vm_offset_t 	data;
2367    vm_map_offset_t	map_data;
2368
2369    CHECK( IORegistryEntry, registry_entry, entry );
2370
2371    err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
2372    data = CAST_DOWN(vm_offset_t, map_data);
2373
2374    if( KERN_SUCCESS == err) {
2375
2376        // must return success after vm_map_copyout() succeeds
2377        obj = OSUnserializeXML( (const char *) data );
2378	vm_deallocate( kernel_map, data, propertiesCnt );
2379
2380	if (!obj)
2381	    res = kIOReturnBadArgument;
2382#if CONFIG_MACF
2383	else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
2384	    registry_entry, obj))
2385	    res = kIOReturnNotPermitted;
2386#endif
2387	else
2388            res = entry->setProperties( obj );
2389	if (obj)
2390	    obj->release();
2391    } else
2392        res = err;
2393
2394    *result = res;
2395    return( err );
2396}
2397
2398/* Routine io_registry_entry_get_child_iterator */
2399kern_return_t is_io_registry_entry_get_child_iterator(
2400	io_object_t registry_entry,
2401	io_name_t plane,
2402	io_object_t *iterator )
2403{
2404    CHECK( IORegistryEntry, registry_entry, entry );
2405
2406    *iterator = entry->getChildIterator(
2407	IORegistryEntry::getPlane( plane ));
2408
2409    return( kIOReturnSuccess );
2410}
2411
2412/* Routine io_registry_entry_get_parent_iterator */
2413kern_return_t is_io_registry_entry_get_parent_iterator(
2414	io_object_t registry_entry,
2415	io_name_t plane,
2416	io_object_t *iterator)
2417{
2418    CHECK( IORegistryEntry, registry_entry, entry );
2419
2420    *iterator = entry->getParentIterator(
2421	IORegistryEntry::getPlane( plane ));
2422
2423    return( kIOReturnSuccess );
2424}
2425
2426/* Routine io_service_get_busy_state */
2427kern_return_t is_io_service_get_busy_state(
2428	io_object_t _service,
2429	uint32_t *busyState )
2430{
2431    CHECK( IOService, _service, service );
2432
2433    *busyState = service->getBusyState();
2434
2435    return( kIOReturnSuccess );
2436}
2437
2438/* Routine io_service_get_state */
2439kern_return_t is_io_service_get_state(
2440	io_object_t _service,
2441	uint64_t *state,
2442	uint32_t *busy_state,
2443	uint64_t *accumulated_busy_time )
2444{
2445    CHECK( IOService, _service, service );
2446
2447    *state                 = service->getState();
2448    *busy_state            = service->getBusyState();
2449    *accumulated_busy_time = service->getAccumulatedBusyTime();
2450
2451    return( kIOReturnSuccess );
2452}
2453
2454/* Routine io_service_wait_quiet */
2455kern_return_t is_io_service_wait_quiet(
2456	io_object_t _service,
2457	mach_timespec_t wait_time )
2458{
2459    uint64_t    timeoutNS;
2460
2461    CHECK( IOService, _service, service );
2462
2463    timeoutNS = wait_time.tv_sec;
2464    timeoutNS *= kSecondScale;
2465    timeoutNS += wait_time.tv_nsec;
2466
2467    return( service->waitQuiet(timeoutNS) );
2468}
2469
2470/* Routine io_service_request_probe */
2471kern_return_t is_io_service_request_probe(
2472	io_object_t _service,
2473	uint32_t options )
2474{
2475    CHECK( IOService, _service, service );
2476
2477    return( service->requestProbe( options ));
2478}
2479
2480/* Routine io_service_open_ndr */
2481kern_return_t is_io_service_open_extended(
2482	io_object_t _service,
2483	task_t owningTask,
2484	uint32_t connect_type,
2485	NDR_record_t ndr,
2486	io_buf_ptr_t properties,
2487	mach_msg_type_number_t propertiesCnt,
2488        kern_return_t * result,
2489	io_object_t *connection )
2490{
2491    IOUserClient * client = 0;
2492    kern_return_t  err = KERN_SUCCESS;
2493    IOReturn	   res = kIOReturnSuccess;
2494    OSDictionary * propertiesDict = 0;
2495    bool	   crossEndian;
2496    bool	   disallowAccess;
2497
2498    CHECK( IOService, _service, service );
2499
2500    do
2501    {
2502	if (properties)
2503	{
2504	    OSObject *	    obj;
2505	    vm_offset_t     data;
2506	    vm_map_offset_t map_data;
2507
2508	    err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
2509	    res = err;
2510	    data = CAST_DOWN(vm_offset_t, map_data);
2511	    if (KERN_SUCCESS == err)
2512	    {
2513		// must return success after vm_map_copyout() succeeds
2514		obj = OSUnserializeXML( (const char *) data );
2515		vm_deallocate( kernel_map, data, propertiesCnt );
2516		propertiesDict = OSDynamicCast(OSDictionary, obj);
2517		if (!propertiesDict)
2518		{
2519		    res = kIOReturnBadArgument;
2520		    if (obj)
2521			obj->release();
2522		}
2523	    }
2524	    if (kIOReturnSuccess != res)
2525		break;
2526	}
2527
2528	crossEndian = (ndr.int_rep != NDR_record.int_rep);
2529	if (crossEndian)
2530	{
2531	    if (!propertiesDict)
2532		propertiesDict = OSDictionary::withCapacity(4);
2533	    OSData * data = OSData::withBytes(&ndr, sizeof(ndr));
2534	    if (data)
2535	    {
2536		if (propertiesDict)
2537		    propertiesDict->setObject(kIOUserClientCrossEndianKey, data);
2538		data->release();
2539	    }
2540	}
2541
2542	res = service->newUserClient( owningTask, (void *) owningTask,
2543		    connect_type, propertiesDict, &client );
2544
2545	if (propertiesDict)
2546	    propertiesDict->release();
2547
2548	if (res == kIOReturnSuccess)
2549	{
2550	    assert( OSDynamicCast(IOUserClient, client) );
2551
2552	    disallowAccess = (crossEndian
2553		&& (kOSBooleanTrue != service->getProperty(kIOUserClientCrossEndianCompatibleKey))
2554		&& (kOSBooleanTrue != client->getProperty(kIOUserClientCrossEndianCompatibleKey)));
2555            if (disallowAccess) res = kIOReturnUnsupported;
2556#if CONFIG_MACF
2557	    else if (0 != mac_iokit_check_open(kauth_cred_get(), client, connect_type))
2558		res = kIOReturnNotPermitted;
2559#endif
2560	    if (kIOReturnSuccess != res)
2561	    {
2562		IOStatisticsClientCall();
2563		client->clientClose();
2564		client->release();
2565		client = 0;
2566		break;
2567	    }
2568	    client->sharedInstance = (0 != client->getProperty(kIOUserClientSharedInstanceKey));
2569	    OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
2570	    if (creatorName)
2571	    {
2572		client->setProperty(kIOUserClientCreatorKey, creatorName);
2573		creatorName->release();
2574	    }
2575	}
2576    }
2577    while (false);
2578
2579    *connection = client;
2580    *result = res;
2581
2582    return (err);
2583}
2584
2585/* Routine io_service_close */
2586kern_return_t is_io_service_close(
2587	io_object_t connection )
2588{
2589    OSSet * mappings;
2590    if ((mappings = OSDynamicCast(OSSet, connection)))
2591	return( kIOReturnSuccess );
2592
2593    CHECK( IOUserClient, connection, client );
2594
2595    IOStatisticsClientCall();
2596    client->clientClose();
2597
2598    return( kIOReturnSuccess );
2599}
2600
2601/* Routine io_connect_get_service */
2602kern_return_t is_io_connect_get_service(
2603	io_object_t connection,
2604	io_object_t *service )
2605{
2606    IOService * theService;
2607
2608    CHECK( IOUserClient, connection, client );
2609
2610    theService = client->getService();
2611    if( theService)
2612	theService->retain();
2613
2614    *service = theService;
2615
2616    return( theService ? kIOReturnSuccess : kIOReturnUnsupported );
2617}
2618
2619/* Routine io_connect_set_notification_port */
2620kern_return_t is_io_connect_set_notification_port(
2621	io_object_t connection,
2622	uint32_t notification_type,
2623	mach_port_t port,
2624	uint32_t reference)
2625{
2626    CHECK( IOUserClient, connection, client );
2627
2628    IOStatisticsClientCall();
2629    return( client->registerNotificationPort( port, notification_type,
2630						(io_user_reference_t) reference ));
2631}
2632
2633/* Routine io_connect_set_notification_port */
2634kern_return_t is_io_connect_set_notification_port_64(
2635	io_object_t connection,
2636	uint32_t notification_type,
2637	mach_port_t port,
2638	io_user_reference_t reference)
2639{
2640    CHECK( IOUserClient, connection, client );
2641
2642    IOStatisticsClientCall();
2643    return( client->registerNotificationPort( port, notification_type,
2644						reference ));
2645}
2646
2647/* Routine io_connect_map_memory_into_task */
2648kern_return_t is_io_connect_map_memory_into_task
2649(
2650	io_connect_t connection,
2651	uint32_t memory_type,
2652	task_t into_task,
2653	mach_vm_address_t *address,
2654	mach_vm_size_t *size,
2655	uint32_t flags
2656)
2657{
2658    IOReturn		err;
2659    IOMemoryMap *	map;
2660
2661    CHECK( IOUserClient, connection, client );
2662
2663    IOStatisticsClientCall();
2664    map = client->mapClientMemory64( memory_type, into_task, flags, *address );
2665
2666    if( map) {
2667        *address = map->getAddress();
2668        if( size)
2669            *size = map->getSize();
2670
2671        if( client->sharedInstance
2672	    || (into_task != current_task())) {
2673            // push a name out to the task owning the map,
2674            // so we can clean up maps
2675	    mach_port_name_t name __unused =
2676		IOMachPort::makeSendRightForTask(
2677                                    into_task, map, IKOT_IOKIT_OBJECT );
2678            assert( name );
2679
2680        } else {
2681            // keep it with the user client
2682            IOLockLock( gIOObjectPortLock);
2683            if( 0 == client->mappings)
2684                client->mappings = OSSet::withCapacity(2);
2685            if( client->mappings)
2686                client->mappings->setObject( map);
2687            IOLockUnlock( gIOObjectPortLock);
2688            map->release();
2689        }
2690        err = kIOReturnSuccess;
2691
2692    } else
2693	err = kIOReturnBadArgument;
2694
2695    return( err );
2696}
2697
2698/* Routine is_io_connect_map_memory */
2699kern_return_t is_io_connect_map_memory(
2700	io_object_t     connect,
2701	uint32_t	type,
2702	task_t		task,
2703	vm_address_t *	mapAddr,
2704	vm_size_t    *	mapSize,
2705	uint32_t	flags )
2706{
2707    IOReturn	      err;
2708    mach_vm_address_t address;
2709    mach_vm_size_t    size;
2710
2711    address = SCALAR64(*mapAddr);
2712    size    = SCALAR64(*mapSize);
2713
2714    err = is_io_connect_map_memory_into_task(connect, type, task, &address, &size, flags);
2715
2716    *mapAddr = SCALAR32(address);
2717    *mapSize = SCALAR32(size);
2718
2719    return (err);
2720}
2721
2722} /* extern "C" */
2723
2724IOMemoryMap * IOUserClient::removeMappingForDescriptor(IOMemoryDescriptor * mem)
2725{
2726    OSIterator *  iter;
2727    IOMemoryMap * map = 0;
2728
2729    IOLockLock(gIOObjectPortLock);
2730
2731    iter = OSCollectionIterator::withCollection(mappings);
2732    if(iter)
2733    {
2734        while ((map = OSDynamicCast(IOMemoryMap, iter->getNextObject())))
2735        {
2736            if(mem == map->getMemoryDescriptor())
2737            {
2738                map->retain();
2739                mappings->removeObject(map);
2740                break;
2741            }
2742        }
2743        iter->release();
2744    }
2745
2746    IOLockUnlock(gIOObjectPortLock);
2747
2748    return (map);
2749}
2750
2751extern "C" {
2752
2753/* Routine io_connect_unmap_memory_from_task */
2754kern_return_t is_io_connect_unmap_memory_from_task
2755(
2756	io_connect_t connection,
2757	uint32_t memory_type,
2758	task_t from_task,
2759	mach_vm_address_t address)
2760{
2761    IOReturn		err;
2762    IOOptionBits	options = 0;
2763    IOMemoryDescriptor * memory;
2764    IOMemoryMap *	map;
2765
2766    CHECK( IOUserClient, connection, client );
2767
2768    IOStatisticsClientCall();
2769    err = client->clientMemoryForType( (UInt32) memory_type, &options, &memory );
2770
2771    if( memory && (kIOReturnSuccess == err)) {
2772
2773        options = (options & ~kIOMapUserOptionsMask)
2774		| kIOMapAnywhere | kIOMapReference;
2775
2776	map = memory->createMappingInTask( from_task, address, options );
2777	memory->release();
2778        if( map)
2779	{
2780            IOLockLock( gIOObjectPortLock);
2781            if( client->mappings)
2782                client->mappings->removeObject( map);
2783            IOLockUnlock( gIOObjectPortLock);
2784
2785	    mach_port_name_t name = 0;
2786	    if (from_task != current_task())
2787		name = IOMachPort::makeSendRightForTask( from_task, map, IKOT_IOKIT_OBJECT );
2788	    if (name)
2789	    {
2790		map->userClientUnmap();
2791		err = iokit_mod_send_right( from_task, name, -2 );
2792		err = kIOReturnSuccess;
2793	    }
2794	    else
2795		IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT );
2796	    if (from_task == current_task())
2797		map->release();
2798        }
2799	else
2800            err = kIOReturnBadArgument;
2801    }
2802
2803    return( err );
2804}
2805
2806kern_return_t is_io_connect_unmap_memory(
2807	io_object_t     connect,
2808	uint32_t	type,
2809	task_t		task,
2810	vm_address_t 	mapAddr )
2811{
2812    IOReturn		err;
2813    mach_vm_address_t   address;
2814
2815    address = SCALAR64(mapAddr);
2816
2817    err = is_io_connect_unmap_memory_from_task(connect, type, task, mapAddr);
2818
2819    return (err);
2820}
2821
2822
2823/* Routine io_connect_add_client */
2824kern_return_t is_io_connect_add_client(
2825	io_object_t connection,
2826	io_object_t connect_to)
2827{
2828    CHECK( IOUserClient, connection, client );
2829    CHECK( IOUserClient, connect_to, to );
2830
2831    IOStatisticsClientCall();
2832    return( client->connectClient( to ) );
2833}
2834
2835
2836/* Routine io_connect_set_properties */
2837kern_return_t is_io_connect_set_properties(
2838	io_object_t connection,
2839	io_buf_ptr_t properties,
2840	mach_msg_type_number_t propertiesCnt,
2841        kern_return_t * result)
2842{
2843    return( is_io_registry_entry_set_properties( connection, properties, propertiesCnt, result ));
2844}
2845
2846/* Routine io_user_client_method */
2847kern_return_t is_io_connect_method_var_output
2848(
2849	io_connect_t connection,
2850	uint32_t selector,
2851	io_scalar_inband64_t scalar_input,
2852	mach_msg_type_number_t scalar_inputCnt,
2853	io_struct_inband_t inband_input,
2854	mach_msg_type_number_t inband_inputCnt,
2855	mach_vm_address_t ool_input,
2856	mach_vm_size_t ool_input_size,
2857	io_struct_inband_t inband_output,
2858	mach_msg_type_number_t *inband_outputCnt,
2859	io_scalar_inband64_t scalar_output,
2860	mach_msg_type_number_t *scalar_outputCnt,
2861	io_buf_ptr_t *var_output,
2862	mach_msg_type_number_t *var_outputCnt
2863)
2864{
2865    CHECK( IOUserClient, connection, client );
2866
2867    IOExternalMethodArguments args;
2868    IOReturn ret;
2869    IOMemoryDescriptor * inputMD  = 0;
2870    OSObject *           structureVariableOutputData = 0;
2871
2872    bzero(&args.__reserved[0], sizeof(args.__reserved));
2873    args.version = kIOExternalMethodArgumentsCurrentVersion;
2874
2875    args.selector = selector;
2876
2877    args.asyncWakePort               = MACH_PORT_NULL;
2878    args.asyncReference              = 0;
2879    args.asyncReferenceCount         = 0;
2880    args.structureVariableOutputData = &structureVariableOutputData;
2881
2882    args.scalarInput = scalar_input;
2883    args.scalarInputCount = scalar_inputCnt;
2884    args.structureInput = inband_input;
2885    args.structureInputSize = inband_inputCnt;
2886
2887    if (ool_input)
2888	inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
2889						    kIODirectionOut, current_task());
2890
2891    args.structureInputDescriptor = inputMD;
2892
2893    args.scalarOutput = scalar_output;
2894    args.scalarOutputCount = *scalar_outputCnt;
2895    args.structureOutput = inband_output;
2896    args.structureOutputSize = *inband_outputCnt;
2897    args.structureOutputDescriptor = NULL;
2898    args.structureOutputDescriptorSize = 0;
2899
2900    IOStatisticsClientCall();
2901    ret = client->externalMethod( selector, &args );
2902
2903    *scalar_outputCnt = args.scalarOutputCount;
2904    *inband_outputCnt = args.structureOutputSize;
2905
2906    if (var_outputCnt && var_output && (kIOReturnSuccess == ret))
2907    {
2908    	OSSerialize * serialize;
2909    	OSData      * data;
2910	vm_size_t     len;
2911
2912	if ((serialize = OSDynamicCast(OSSerialize, structureVariableOutputData)))
2913	{
2914	    len = serialize->getLength();
2915	    *var_outputCnt = len;
2916	    ret = copyoutkdata(serialize->text(), len, var_output);
2917	}
2918	else if ((data = OSDynamicCast(OSData, structureVariableOutputData)))
2919	{
2920	    len = data->getLength();
2921	    *var_outputCnt = len;
2922	    ret = copyoutkdata(data->getBytesNoCopy(), len, var_output);
2923	}
2924	else
2925	{
2926	    ret = kIOReturnUnderrun;
2927	}
2928    }
2929
2930    if (inputMD)
2931	inputMD->release();
2932    if (structureVariableOutputData)
2933    	structureVariableOutputData->release();
2934
2935    return (ret);
2936}
2937
2938/* Routine io_user_client_method */
2939kern_return_t is_io_connect_method
2940(
2941	io_connect_t connection,
2942	uint32_t selector,
2943	io_scalar_inband64_t scalar_input,
2944	mach_msg_type_number_t scalar_inputCnt,
2945	io_struct_inband_t inband_input,
2946	mach_msg_type_number_t inband_inputCnt,
2947	mach_vm_address_t ool_input,
2948	mach_vm_size_t ool_input_size,
2949	io_struct_inband_t inband_output,
2950	mach_msg_type_number_t *inband_outputCnt,
2951	io_scalar_inband64_t scalar_output,
2952	mach_msg_type_number_t *scalar_outputCnt,
2953	mach_vm_address_t ool_output,
2954	mach_vm_size_t *ool_output_size
2955)
2956{
2957    CHECK( IOUserClient, connection, client );
2958
2959    IOExternalMethodArguments args;
2960    IOReturn ret;
2961    IOMemoryDescriptor * inputMD  = 0;
2962    IOMemoryDescriptor * outputMD = 0;
2963
2964    bzero(&args.__reserved[0], sizeof(args.__reserved));
2965    args.version = kIOExternalMethodArgumentsCurrentVersion;
2966
2967    args.selector = selector;
2968
2969    args.asyncWakePort               = MACH_PORT_NULL;
2970    args.asyncReference              = 0;
2971    args.asyncReferenceCount         = 0;
2972    args.structureVariableOutputData = 0;
2973
2974    args.scalarInput = scalar_input;
2975    args.scalarInputCount = scalar_inputCnt;
2976    args.structureInput = inband_input;
2977    args.structureInputSize = inband_inputCnt;
2978
2979    if (ool_input)
2980	inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
2981						    kIODirectionOut, current_task());
2982
2983    args.structureInputDescriptor = inputMD;
2984
2985    args.scalarOutput = scalar_output;
2986    args.scalarOutputCount = *scalar_outputCnt;
2987    args.structureOutput = inband_output;
2988    args.structureOutputSize = *inband_outputCnt;
2989
2990    if (ool_output && ool_output_size)
2991    {
2992	outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size,
2993						    kIODirectionIn, current_task());
2994    }
2995
2996    args.structureOutputDescriptor = outputMD;
2997    args.structureOutputDescriptorSize = ool_output_size ? *ool_output_size : 0;
2998
2999    IOStatisticsClientCall();
3000    ret = client->externalMethod( selector, &args );
3001
3002    *scalar_outputCnt = args.scalarOutputCount;
3003    *inband_outputCnt = args.structureOutputSize;
3004    *ool_output_size  = args.structureOutputDescriptorSize;
3005
3006    if (inputMD)
3007	inputMD->release();
3008    if (outputMD)
3009	outputMD->release();
3010
3011    return (ret);
3012}
3013
3014/* Routine io_async_user_client_method */
3015kern_return_t is_io_connect_async_method
3016(
3017	io_connect_t connection,
3018	mach_port_t wake_port,
3019	io_async_ref64_t reference,
3020	mach_msg_type_number_t referenceCnt,
3021	uint32_t selector,
3022	io_scalar_inband64_t scalar_input,
3023	mach_msg_type_number_t scalar_inputCnt,
3024	io_struct_inband_t inband_input,
3025	mach_msg_type_number_t inband_inputCnt,
3026	mach_vm_address_t ool_input,
3027	mach_vm_size_t ool_input_size,
3028	io_struct_inband_t inband_output,
3029	mach_msg_type_number_t *inband_outputCnt,
3030	io_scalar_inband64_t scalar_output,
3031	mach_msg_type_number_t *scalar_outputCnt,
3032	mach_vm_address_t ool_output,
3033	mach_vm_size_t * ool_output_size
3034)
3035{
3036    CHECK( IOUserClient, connection, client );
3037
3038    IOExternalMethodArguments args;
3039    IOReturn ret;
3040    IOMemoryDescriptor * inputMD  = 0;
3041    IOMemoryDescriptor * outputMD = 0;
3042
3043    bzero(&args.__reserved[0], sizeof(args.__reserved));
3044    args.version = kIOExternalMethodArgumentsCurrentVersion;
3045
3046    reference[0]	     = (io_user_reference_t) wake_port;
3047    if (vm_map_is_64bit(get_task_map(current_task())))
3048	reference[0]	     |= kIOUCAsync64Flag;
3049
3050    args.selector = selector;
3051
3052    args.asyncWakePort       = wake_port;
3053    args.asyncReference      = reference;
3054    args.asyncReferenceCount = referenceCnt;
3055
3056    args.scalarInput = scalar_input;
3057    args.scalarInputCount = scalar_inputCnt;
3058    args.structureInput = inband_input;
3059    args.structureInputSize = inband_inputCnt;
3060
3061    if (ool_input)
3062	inputMD = IOMemoryDescriptor::withAddressRange(ool_input, ool_input_size,
3063						    kIODirectionOut, current_task());
3064
3065    args.structureInputDescriptor = inputMD;
3066
3067    args.scalarOutput = scalar_output;
3068    args.scalarOutputCount = *scalar_outputCnt;
3069    args.structureOutput = inband_output;
3070    args.structureOutputSize = *inband_outputCnt;
3071
3072    if (ool_output)
3073    {
3074	outputMD = IOMemoryDescriptor::withAddressRange(ool_output, *ool_output_size,
3075						    kIODirectionIn, current_task());
3076    }
3077
3078    args.structureOutputDescriptor = outputMD;
3079    args.structureOutputDescriptorSize = *ool_output_size;
3080
3081    IOStatisticsClientCall();
3082    ret = client->externalMethod( selector, &args );
3083
3084    *inband_outputCnt = args.structureOutputSize;
3085    *ool_output_size  = args.structureOutputDescriptorSize;
3086
3087    if (inputMD)
3088	inputMD->release();
3089    if (outputMD)
3090	outputMD->release();
3091
3092    return (ret);
3093}
3094
3095/* Routine io_connect_method_scalarI_scalarO */
3096kern_return_t is_io_connect_method_scalarI_scalarO(
3097	io_object_t	   connect,
3098	uint32_t	   index,
3099        io_scalar_inband_t       input,
3100        mach_msg_type_number_t	 inputCount,
3101        io_scalar_inband_t       output,
3102        mach_msg_type_number_t * outputCount )
3103{
3104    IOReturn err;
3105    uint32_t i;
3106    io_scalar_inband64_t _input;
3107    io_scalar_inband64_t _output;
3108
3109    mach_msg_type_number_t struct_outputCnt = 0;
3110    mach_vm_size_t ool_output_size = 0;
3111
3112    for (i = 0; i < inputCount; i++)
3113	_input[i] = SCALAR64(input[i]);
3114
3115    err = is_io_connect_method(connect, index,
3116		    _input, inputCount,
3117		    NULL, 0,
3118		    0, 0,
3119		    NULL, &struct_outputCnt,
3120		    _output, outputCount,
3121		    0, &ool_output_size);
3122
3123    for (i = 0; i < *outputCount; i++)
3124	output[i] = SCALAR32(_output[i]);
3125
3126    return (err);
3127}
3128
3129kern_return_t shim_io_connect_method_scalarI_scalarO(
3130	IOExternalMethod *	method,
3131	IOService *		object,
3132        const io_user_scalar_t * input,
3133        mach_msg_type_number_t	 inputCount,
3134        io_user_scalar_t * output,
3135        mach_msg_type_number_t * outputCount )
3136{
3137    IOMethod		func;
3138    io_scalar_inband_t  _output;
3139    IOReturn 		err;
3140    err = kIOReturnBadArgument;
3141
3142    do {
3143
3144	if( inputCount != method->count0)
3145	{
3146	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3147	    continue;
3148	}
3149	if( *outputCount != method->count1)
3150	{
3151	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3152	    continue;
3153	}
3154
3155	func = method->func;
3156
3157	switch( inputCount) {
3158
3159	    case 6:
3160		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3161					ARG32(input[3]), ARG32(input[4]), ARG32(input[5]) );
3162		break;
3163	    case 5:
3164		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3165					ARG32(input[3]), ARG32(input[4]),
3166					&_output[0] );
3167		break;
3168	    case 4:
3169		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3170					ARG32(input[3]),
3171					&_output[0], &_output[1] );
3172		break;
3173	    case 3:
3174		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3175					&_output[0], &_output[1], &_output[2] );
3176		break;
3177	    case 2:
3178		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]),
3179					&_output[0], &_output[1], &_output[2],
3180					&_output[3] );
3181		break;
3182	    case 1:
3183		err = (object->*func)(  ARG32(input[0]),
3184					&_output[0], &_output[1], &_output[2],
3185					&_output[3], &_output[4] );
3186		break;
3187	    case 0:
3188		err = (object->*func)(  &_output[0], &_output[1], &_output[2],
3189					&_output[3], &_output[4], &_output[5] );
3190		break;
3191
3192	    default:
3193		IOLog("%s: Bad method table\n", object->getName());
3194	}
3195    }
3196    while( false);
3197
3198    uint32_t i;
3199    for (i = 0; i < *outputCount; i++)
3200	output[i] = SCALAR32(_output[i]);
3201
3202    return( err);
3203}
3204
3205/* Routine io_async_method_scalarI_scalarO */
3206kern_return_t is_io_async_method_scalarI_scalarO(
3207	io_object_t	   connect,
3208	mach_port_t wake_port,
3209	io_async_ref_t reference,
3210	mach_msg_type_number_t referenceCnt,
3211	uint32_t	   index,
3212        io_scalar_inband_t       input,
3213        mach_msg_type_number_t	 inputCount,
3214        io_scalar_inband_t       output,
3215        mach_msg_type_number_t * outputCount )
3216{
3217    IOReturn err;
3218    uint32_t i;
3219    io_scalar_inband64_t _input;
3220    io_scalar_inband64_t _output;
3221    io_async_ref64_t _reference;
3222
3223    for (i = 0; i < referenceCnt; i++)
3224	_reference[i] = REF64(reference[i]);
3225
3226    mach_msg_type_number_t struct_outputCnt = 0;
3227    mach_vm_size_t ool_output_size = 0;
3228
3229    for (i = 0; i < inputCount; i++)
3230	_input[i] = SCALAR64(input[i]);
3231
3232    err = is_io_connect_async_method(connect,
3233		    wake_port, _reference, referenceCnt,
3234		    index,
3235		    _input, inputCount,
3236		    NULL, 0,
3237		    0, 0,
3238		    NULL, &struct_outputCnt,
3239		    _output, outputCount,
3240		    0, &ool_output_size);
3241
3242    for (i = 0; i < *outputCount; i++)
3243	output[i] = SCALAR32(_output[i]);
3244
3245    return (err);
3246}
3247/* Routine io_async_method_scalarI_structureO */
3248kern_return_t is_io_async_method_scalarI_structureO(
3249	io_object_t	connect,
3250	mach_port_t wake_port,
3251	io_async_ref_t reference,
3252	mach_msg_type_number_t referenceCnt,
3253	uint32_t	index,
3254        io_scalar_inband_t input,
3255        mach_msg_type_number_t	inputCount,
3256        io_struct_inband_t		output,
3257        mach_msg_type_number_t *	outputCount )
3258{
3259    uint32_t i;
3260    io_scalar_inband64_t _input;
3261    io_async_ref64_t _reference;
3262
3263    for (i = 0; i < referenceCnt; i++)
3264	_reference[i] = REF64(reference[i]);
3265
3266    mach_msg_type_number_t scalar_outputCnt = 0;
3267    mach_vm_size_t ool_output_size = 0;
3268
3269    for (i = 0; i < inputCount; i++)
3270	_input[i] = SCALAR64(input[i]);
3271
3272    return (is_io_connect_async_method(connect,
3273		    wake_port, _reference, referenceCnt,
3274		    index,
3275		    _input, inputCount,
3276		    NULL, 0,
3277		    0, 0,
3278		    output, outputCount,
3279		    NULL, &scalar_outputCnt,
3280		    0, &ool_output_size));
3281}
3282
3283/* Routine io_async_method_scalarI_structureI */
3284kern_return_t is_io_async_method_scalarI_structureI(
3285	io_connect_t		connect,
3286	mach_port_t wake_port,
3287	io_async_ref_t reference,
3288	mach_msg_type_number_t referenceCnt,
3289	uint32_t		index,
3290        io_scalar_inband_t	input,
3291        mach_msg_type_number_t	inputCount,
3292        io_struct_inband_t	inputStruct,
3293        mach_msg_type_number_t	inputStructCount )
3294{
3295    uint32_t i;
3296    io_scalar_inband64_t _input;
3297    io_async_ref64_t _reference;
3298
3299    for (i = 0; i < referenceCnt; i++)
3300	_reference[i] = REF64(reference[i]);
3301
3302    mach_msg_type_number_t scalar_outputCnt = 0;
3303    mach_msg_type_number_t inband_outputCnt = 0;
3304    mach_vm_size_t ool_output_size = 0;
3305
3306    for (i = 0; i < inputCount; i++)
3307	_input[i] = SCALAR64(input[i]);
3308
3309    return (is_io_connect_async_method(connect,
3310		    wake_port, _reference, referenceCnt,
3311		    index,
3312		    _input, inputCount,
3313		    inputStruct, inputStructCount,
3314		    0, 0,
3315		    NULL, &inband_outputCnt,
3316		    NULL, &scalar_outputCnt,
3317		    0, &ool_output_size));
3318}
3319
3320/* Routine io_async_method_structureI_structureO */
3321kern_return_t is_io_async_method_structureI_structureO(
3322	io_object_t	connect,
3323	mach_port_t wake_port,
3324	io_async_ref_t reference,
3325	mach_msg_type_number_t referenceCnt,
3326	uint32_t	index,
3327        io_struct_inband_t		input,
3328        mach_msg_type_number_t	inputCount,
3329        io_struct_inband_t		output,
3330        mach_msg_type_number_t *	outputCount )
3331{
3332    uint32_t i;
3333    mach_msg_type_number_t scalar_outputCnt = 0;
3334    mach_vm_size_t ool_output_size = 0;
3335    io_async_ref64_t _reference;
3336
3337    for (i = 0; i < referenceCnt; i++)
3338	_reference[i] = REF64(reference[i]);
3339
3340    return (is_io_connect_async_method(connect,
3341		    wake_port, _reference, referenceCnt,
3342		    index,
3343		    NULL, 0,
3344		    input, inputCount,
3345		    0, 0,
3346		    output, outputCount,
3347		    NULL, &scalar_outputCnt,
3348		    0, &ool_output_size));
3349}
3350
3351
3352kern_return_t shim_io_async_method_scalarI_scalarO(
3353	IOExternalAsyncMethod *	method,
3354	IOService *		object,
3355	mach_port_t             asyncWakePort,
3356	io_user_reference_t *   asyncReference,
3357	uint32_t                asyncReferenceCount,
3358        const io_user_scalar_t * input,
3359        mach_msg_type_number_t	 inputCount,
3360        io_user_scalar_t * output,
3361        mach_msg_type_number_t * outputCount )
3362{
3363    IOAsyncMethod	func;
3364    uint32_t		i;
3365    io_scalar_inband_t  _output;
3366    IOReturn 		err;
3367    io_async_ref_t	reference;
3368
3369    for (i = 0; i < asyncReferenceCount; i++)
3370	reference[i] = REF32(asyncReference[i]);
3371
3372    err = kIOReturnBadArgument;
3373
3374    do {
3375
3376	if( inputCount != method->count0)
3377	{
3378	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3379	    continue;
3380	}
3381	if( *outputCount != method->count1)
3382	{
3383	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3384	    continue;
3385	}
3386
3387	func = method->func;
3388
3389        switch( inputCount) {
3390
3391            case 6:
3392                err = (object->*func)(	reference,
3393                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3394                                        ARG32(input[3]), ARG32(input[4]), ARG32(input[5]) );
3395                break;
3396            case 5:
3397                err = (object->*func)(  reference,
3398                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3399                                        ARG32(input[3]), ARG32(input[4]),
3400                                        &_output[0] );
3401                break;
3402            case 4:
3403                err = (object->*func)(  reference,
3404                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3405                                        ARG32(input[3]),
3406                                        &_output[0], &_output[1] );
3407                break;
3408            case 3:
3409                err = (object->*func)(  reference,
3410                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3411                                        &_output[0], &_output[1], &_output[2] );
3412                break;
3413            case 2:
3414                err = (object->*func)(  reference,
3415                                        ARG32(input[0]), ARG32(input[1]),
3416                                        &_output[0], &_output[1], &_output[2],
3417                                        &_output[3] );
3418                break;
3419            case 1:
3420                err = (object->*func)(  reference,
3421                                        ARG32(input[0]),
3422					&_output[0], &_output[1], &_output[2],
3423                                        &_output[3], &_output[4] );
3424                break;
3425            case 0:
3426                err = (object->*func)(  reference,
3427                                        &_output[0], &_output[1], &_output[2],
3428                                        &_output[3], &_output[4], &_output[5] );
3429                break;
3430
3431            default:
3432                IOLog("%s: Bad method table\n", object->getName());
3433        }
3434    }
3435    while( false);
3436
3437    for (i = 0; i < *outputCount; i++)
3438	output[i] = SCALAR32(_output[i]);
3439
3440    return( err);
3441}
3442
3443
3444/* Routine io_connect_method_scalarI_structureO */
3445kern_return_t is_io_connect_method_scalarI_structureO(
3446	io_object_t	connect,
3447	uint32_t	index,
3448        io_scalar_inband_t input,
3449        mach_msg_type_number_t	inputCount,
3450        io_struct_inband_t		output,
3451        mach_msg_type_number_t *	outputCount )
3452{
3453    uint32_t i;
3454    io_scalar_inband64_t _input;
3455
3456    mach_msg_type_number_t scalar_outputCnt = 0;
3457    mach_vm_size_t ool_output_size = 0;
3458
3459    for (i = 0; i < inputCount; i++)
3460	_input[i] = SCALAR64(input[i]);
3461
3462    return (is_io_connect_method(connect, index,
3463		    _input, inputCount,
3464		    NULL, 0,
3465		    0, 0,
3466		    output, outputCount,
3467		    NULL, &scalar_outputCnt,
3468		    0, &ool_output_size));
3469}
3470
3471kern_return_t shim_io_connect_method_scalarI_structureO(
3472
3473	IOExternalMethod *	method,
3474	IOService *		object,
3475        const io_user_scalar_t * input,
3476        mach_msg_type_number_t	inputCount,
3477        io_struct_inband_t		output,
3478        IOByteCount *	outputCount )
3479{
3480    IOMethod		func;
3481    IOReturn 		err;
3482
3483    err = kIOReturnBadArgument;
3484
3485    do {
3486	if( inputCount != method->count0)
3487	{
3488	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3489	    continue;
3490	}
3491	if( (kIOUCVariableStructureSize != method->count1)
3492		&& (*outputCount != method->count1))
3493	{
3494	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3495	    continue;
3496	}
3497
3498	func = method->func;
3499
3500	switch( inputCount) {
3501
3502	    case 5:
3503		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3504                                        ARG32(input[3]), ARG32(input[4]),
3505                                        output );
3506		break;
3507	    case 4:
3508		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3509					ARG32(input[3]),
3510					output, (void *)outputCount );
3511		break;
3512	    case 3:
3513		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3514					output, (void *)outputCount, 0 );
3515		break;
3516	    case 2:
3517		err = (object->*func)(  ARG32(input[0]), ARG32(input[1]),
3518					output, (void *)outputCount, 0, 0 );
3519		break;
3520	    case 1:
3521		err = (object->*func)(  ARG32(input[0]),
3522					output, (void *)outputCount, 0, 0, 0 );
3523		break;
3524	    case 0:
3525		err = (object->*func)(  output, (void *)outputCount, 0, 0, 0, 0 );
3526		break;
3527
3528	    default:
3529		IOLog("%s: Bad method table\n", object->getName());
3530	}
3531    }
3532    while( false);
3533
3534    return( err);
3535}
3536
3537
3538kern_return_t shim_io_async_method_scalarI_structureO(
3539	IOExternalAsyncMethod *	method,
3540	IOService *		object,
3541	mach_port_t             asyncWakePort,
3542	io_user_reference_t *   asyncReference,
3543	uint32_t                asyncReferenceCount,
3544        const io_user_scalar_t * input,
3545        mach_msg_type_number_t	inputCount,
3546        io_struct_inband_t		output,
3547        mach_msg_type_number_t *	outputCount )
3548{
3549    IOAsyncMethod	func;
3550    uint32_t		i;
3551    IOReturn 		err;
3552    io_async_ref_t	reference;
3553
3554    for (i = 0; i < asyncReferenceCount; i++)
3555	reference[i] = REF32(asyncReference[i]);
3556
3557    err = kIOReturnBadArgument;
3558    do {
3559	if( inputCount != method->count0)
3560	{
3561	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3562	    continue;
3563	}
3564	if( (kIOUCVariableStructureSize != method->count1)
3565		&& (*outputCount != method->count1))
3566	{
3567	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3568	    continue;
3569	}
3570
3571	func = method->func;
3572
3573        switch( inputCount) {
3574
3575            case 5:
3576                err = (object->*func)(	reference,
3577                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3578                                        ARG32(input[3]), ARG32(input[4]),
3579                                        output );
3580                break;
3581            case 4:
3582                err = (object->*func)(	reference,
3583                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3584                                        ARG32(input[3]),
3585                                        output, (void *)outputCount );
3586                break;
3587            case 3:
3588                err = (object->*func)(	reference,
3589                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3590                                        output, (void *)outputCount, 0 );
3591                break;
3592            case 2:
3593                err = (object->*func)(	reference,
3594                                        ARG32(input[0]), ARG32(input[1]),
3595                                        output, (void *)outputCount, 0, 0 );
3596                break;
3597            case 1:
3598                err = (object->*func)(	reference,
3599                                        ARG32(input[0]),
3600                                        output, (void *)outputCount, 0, 0, 0 );
3601                break;
3602            case 0:
3603                err = (object->*func)(	reference,
3604                                        output, (void *)outputCount, 0, 0, 0, 0 );
3605                break;
3606
3607            default:
3608                IOLog("%s: Bad method table\n", object->getName());
3609        }
3610    }
3611    while( false);
3612
3613    return( err);
3614}
3615
3616/* Routine io_connect_method_scalarI_structureI */
3617kern_return_t is_io_connect_method_scalarI_structureI(
3618	io_connect_t		connect,
3619	uint32_t		index,
3620        io_scalar_inband_t	input,
3621        mach_msg_type_number_t	inputCount,
3622        io_struct_inband_t	inputStruct,
3623        mach_msg_type_number_t	inputStructCount )
3624{
3625    uint32_t i;
3626    io_scalar_inband64_t _input;
3627
3628    mach_msg_type_number_t scalar_outputCnt = 0;
3629    mach_msg_type_number_t inband_outputCnt = 0;
3630    mach_vm_size_t ool_output_size = 0;
3631
3632    for (i = 0; i < inputCount; i++)
3633	_input[i] = SCALAR64(input[i]);
3634
3635    return (is_io_connect_method(connect, index,
3636		    _input, inputCount,
3637		    inputStruct, inputStructCount,
3638		    0, 0,
3639		    NULL, &inband_outputCnt,
3640		    NULL, &scalar_outputCnt,
3641		    0, &ool_output_size));
3642}
3643
3644kern_return_t shim_io_connect_method_scalarI_structureI(
3645    IOExternalMethod *	method,
3646    IOService *		object,
3647        const io_user_scalar_t * input,
3648        mach_msg_type_number_t	inputCount,
3649        io_struct_inband_t		inputStruct,
3650        mach_msg_type_number_t	inputStructCount )
3651{
3652    IOMethod		func;
3653    IOReturn		err = kIOReturnBadArgument;
3654
3655    do
3656    {
3657	if( (kIOUCVariableStructureSize != method->count0)
3658		&& (inputCount != method->count0))
3659	{
3660	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3661	    continue;
3662	}
3663	if( (kIOUCVariableStructureSize != method->count1)
3664		&& (inputStructCount != method->count1))
3665	{
3666	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3667	    continue;
3668	}
3669
3670	func = method->func;
3671
3672	switch( inputCount) {
3673
3674	    case 5:
3675		err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3676					ARG32(input[3]), ARG32(input[4]),
3677					inputStruct );
3678		break;
3679	    case 4:
3680		err = (object->*func)( ARG32(input[0]), ARG32(input[1]), (void *)  input[2],
3681					ARG32(input[3]),
3682					inputStruct, (void *)inputStructCount );
3683		break;
3684	    case 3:
3685		err = (object->*func)( ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3686					inputStruct, (void *)inputStructCount,
3687					0 );
3688		break;
3689	    case 2:
3690		err = (object->*func)( ARG32(input[0]), ARG32(input[1]),
3691					inputStruct, (void *)inputStructCount,
3692					0, 0 );
3693		break;
3694	    case 1:
3695		err = (object->*func)( ARG32(input[0]),
3696					inputStruct, (void *)inputStructCount,
3697					0, 0, 0 );
3698		break;
3699	    case 0:
3700		err = (object->*func)( inputStruct, (void *)inputStructCount,
3701					0, 0, 0, 0 );
3702		break;
3703
3704	    default:
3705		IOLog("%s: Bad method table\n", object->getName());
3706	}
3707    }
3708    while (false);
3709
3710    return( err);
3711}
3712
3713kern_return_t shim_io_async_method_scalarI_structureI(
3714	IOExternalAsyncMethod *	method,
3715	IOService *		object,
3716	mach_port_t             asyncWakePort,
3717	io_user_reference_t *   asyncReference,
3718	uint32_t                asyncReferenceCount,
3719        const io_user_scalar_t * input,
3720        mach_msg_type_number_t	inputCount,
3721        io_struct_inband_t		inputStruct,
3722        mach_msg_type_number_t	inputStructCount )
3723{
3724    IOAsyncMethod	func;
3725    uint32_t		i;
3726    IOReturn		err = kIOReturnBadArgument;
3727    io_async_ref_t	reference;
3728
3729    for (i = 0; i < asyncReferenceCount; i++)
3730	reference[i] = REF32(asyncReference[i]);
3731
3732    do
3733    {
3734	if( (kIOUCVariableStructureSize != method->count0)
3735		&& (inputCount != method->count0))
3736	{
3737	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3738	    continue;
3739	}
3740	if( (kIOUCVariableStructureSize != method->count1)
3741		&& (inputStructCount != method->count1))
3742	{
3743	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3744	    continue;
3745	}
3746
3747        func = method->func;
3748
3749        switch( inputCount) {
3750
3751            case 5:
3752                err = (object->*func)(	reference,
3753                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3754                                        ARG32(input[3]), ARG32(input[4]),
3755                                        inputStruct );
3756                break;
3757            case 4:
3758                err = (object->*func)(	reference,
3759                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3760                                        ARG32(input[3]),
3761                                        inputStruct, (void *)inputStructCount );
3762                break;
3763            case 3:
3764                err = (object->*func)(	reference,
3765                                        ARG32(input[0]), ARG32(input[1]), ARG32(input[2]),
3766                                        inputStruct, (void *)inputStructCount,
3767                                        0 );
3768                break;
3769            case 2:
3770                err = (object->*func)(	reference,
3771                                        ARG32(input[0]), ARG32(input[1]),
3772                                        inputStruct, (void *)inputStructCount,
3773                                        0, 0 );
3774                break;
3775            case 1:
3776                err = (object->*func)(	reference,
3777                                        ARG32(input[0]),
3778                                        inputStruct, (void *)inputStructCount,
3779                                        0, 0, 0 );
3780                break;
3781            case 0:
3782                err = (object->*func)(	reference,
3783                                        inputStruct, (void *)inputStructCount,
3784                                        0, 0, 0, 0 );
3785                break;
3786
3787            default:
3788                IOLog("%s: Bad method table\n", object->getName());
3789        }
3790    }
3791    while (false);
3792
3793    return( err);
3794}
3795
3796/* Routine io_connect_method_structureI_structureO */
3797kern_return_t is_io_connect_method_structureI_structureO(
3798	io_object_t	connect,
3799	uint32_t	index,
3800        io_struct_inband_t		input,
3801        mach_msg_type_number_t	inputCount,
3802        io_struct_inband_t		output,
3803        mach_msg_type_number_t *	outputCount )
3804{
3805    mach_msg_type_number_t scalar_outputCnt = 0;
3806    mach_vm_size_t ool_output_size = 0;
3807
3808    return (is_io_connect_method(connect, index,
3809		    NULL, 0,
3810		    input, inputCount,
3811		    0, 0,
3812		    output, outputCount,
3813		    NULL, &scalar_outputCnt,
3814		    0, &ool_output_size));
3815}
3816
3817kern_return_t shim_io_connect_method_structureI_structureO(
3818    IOExternalMethod *	method,
3819    IOService *		object,
3820        io_struct_inband_t		input,
3821        mach_msg_type_number_t	inputCount,
3822        io_struct_inband_t		output,
3823        IOByteCount *	outputCount )
3824{
3825    IOMethod		func;
3826    IOReturn 		err = kIOReturnBadArgument;
3827
3828    do
3829    {
3830	if( (kIOUCVariableStructureSize != method->count0)
3831		&& (inputCount != method->count0))
3832	{
3833	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3834	    continue;
3835	}
3836	if( (kIOUCVariableStructureSize != method->count1)
3837		&& (*outputCount != method->count1))
3838	{
3839	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3840	    continue;
3841	}
3842
3843	func = method->func;
3844
3845	if( method->count1) {
3846	    if( method->count0) {
3847		err = (object->*func)( input, output,
3848					(void *)inputCount, outputCount, 0, 0 );
3849	    } else {
3850		err = (object->*func)( output, outputCount, 0, 0, 0, 0 );
3851	    }
3852	} else {
3853		err = (object->*func)( input, (void *)inputCount, 0, 0, 0, 0 );
3854	}
3855    }
3856    while( false);
3857
3858
3859    return( err);
3860}
3861
3862kern_return_t shim_io_async_method_structureI_structureO(
3863	IOExternalAsyncMethod *	method,
3864	IOService *		object,
3865	mach_port_t           asyncWakePort,
3866	io_user_reference_t * asyncReference,
3867	uint32_t              asyncReferenceCount,
3868        io_struct_inband_t		input,
3869        mach_msg_type_number_t	inputCount,
3870        io_struct_inband_t		output,
3871        mach_msg_type_number_t *	outputCount )
3872{
3873    IOAsyncMethod	func;
3874    uint32_t            i;
3875    IOReturn 		err;
3876    io_async_ref_t	reference;
3877
3878    for (i = 0; i < asyncReferenceCount; i++)
3879	reference[i] = REF32(asyncReference[i]);
3880
3881    err = kIOReturnBadArgument;
3882    do
3883    {
3884	if( (kIOUCVariableStructureSize != method->count0)
3885		&& (inputCount != method->count0))
3886	{
3887	    IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
3888	    continue;
3889	}
3890	if( (kIOUCVariableStructureSize != method->count1)
3891		&& (*outputCount != method->count1))
3892	{
3893	    IOLog("%s: IOUserClient outputCount count mismatch\n", object->getName());
3894	    continue;
3895	}
3896
3897        func = method->func;
3898
3899        if( method->count1) {
3900            if( method->count0) {
3901                err = (object->*func)( reference,
3902                                       input, output,
3903                                        (void *)inputCount, outputCount, 0, 0 );
3904            } else {
3905                err = (object->*func)( reference,
3906                                       output, outputCount, 0, 0, 0, 0 );
3907            }
3908        } else {
3909                err = (object->*func)( reference,
3910                                       input, (void *)inputCount, 0, 0, 0, 0 );
3911        }
3912    }
3913    while( false);
3914
3915    return( err);
3916}
3917
3918/* Routine io_catalog_send_data */
3919kern_return_t is_io_catalog_send_data(
3920        mach_port_t		master_port,
3921        uint32_t                flag,
3922        io_buf_ptr_t 		inData,
3923        mach_msg_type_number_t 	inDataCount,
3924        kern_return_t *		result)
3925{
3926    OSObject * obj = 0;
3927    vm_offset_t data;
3928    kern_return_t kr = kIOReturnError;
3929
3930    //printf("io_catalog_send_data called. flag: %d\n", flag);
3931
3932    if( master_port != master_device_port)
3933        return kIOReturnNotPrivileged;
3934
3935    if( (flag != kIOCatalogRemoveKernelLinker &&
3936            flag != kIOCatalogKextdActive &&
3937            flag != kIOCatalogKextdFinishedLaunching) &&
3938        ( !inData || !inDataCount) )
3939    {
3940        return kIOReturnBadArgument;
3941    }
3942
3943    if (inData) {
3944        vm_map_offset_t map_data;
3945
3946        kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t)inData);
3947		data = CAST_DOWN(vm_offset_t, map_data);
3948
3949        if( kr != KERN_SUCCESS)
3950            return kr;
3951
3952        // must return success after vm_map_copyout() succeeds
3953
3954        if( inDataCount ) {
3955            obj = (OSObject *)OSUnserializeXML((const char *)data);
3956            vm_deallocate( kernel_map, data, inDataCount );
3957            if( !obj) {
3958                *result = kIOReturnNoMemory;
3959                return( KERN_SUCCESS);
3960            }
3961        }
3962    }
3963
3964    switch ( flag ) {
3965        case kIOCatalogResetDrivers:
3966        case kIOCatalogResetDriversNoMatch: {
3967                OSArray * array;
3968
3969                array = OSDynamicCast(OSArray, obj);
3970                if (array) {
3971                    if ( !gIOCatalogue->resetAndAddDrivers(array,
3972                        flag == kIOCatalogResetDrivers) ) {
3973
3974                        kr = kIOReturnError;
3975                    }
3976                } else {
3977                    kr = kIOReturnBadArgument;
3978                }
3979            }
3980            break;
3981
3982        case kIOCatalogAddDrivers:
3983        case kIOCatalogAddDriversNoMatch: {
3984                OSArray * array;
3985
3986                array = OSDynamicCast(OSArray, obj);
3987                if ( array ) {
3988                    if ( !gIOCatalogue->addDrivers( array ,
3989                                          flag == kIOCatalogAddDrivers) ) {
3990                        kr = kIOReturnError;
3991                    }
3992                }
3993                else {
3994                    kr = kIOReturnBadArgument;
3995                }
3996            }
3997            break;
3998
3999        case kIOCatalogRemoveDrivers:
4000        case kIOCatalogRemoveDriversNoMatch: {
4001                OSDictionary * dict;
4002
4003                dict = OSDynamicCast(OSDictionary, obj);
4004                if ( dict ) {
4005                    if ( !gIOCatalogue->removeDrivers( dict,
4006                                          flag == kIOCatalogRemoveDrivers ) ) {
4007                        kr = kIOReturnError;
4008                    }
4009                }
4010                else {
4011                    kr = kIOReturnBadArgument;
4012                }
4013            }
4014            break;
4015
4016        case kIOCatalogStartMatching: {
4017                OSDictionary * dict;
4018
4019                dict = OSDynamicCast(OSDictionary, obj);
4020                if ( dict ) {
4021                    if ( !gIOCatalogue->startMatching( dict ) ) {
4022                        kr = kIOReturnError;
4023                    }
4024                }
4025                else {
4026                    kr = kIOReturnBadArgument;
4027                }
4028            }
4029            break;
4030
4031        case kIOCatalogRemoveKernelLinker:
4032            kr = KERN_NOT_SUPPORTED;
4033            break;
4034
4035        case kIOCatalogKextdActive:
4036#if !NO_KEXTD
4037            IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
4038            OSKext::setKextdActive();
4039
4040           /* Dump all nonloaded startup extensions; kextd will now send them
4041            * down on request.
4042            */
4043            OSKext::flushNonloadedKexts( /* flushPrelinkedKexts */ false);
4044#endif
4045            kr = kIOReturnSuccess;
4046            break;
4047
4048        case kIOCatalogKextdFinishedLaunching: {
4049#if !NO_KEXTD
4050                static bool clearedBusy = false;
4051
4052                if (!clearedBusy) {
4053                    IOService * serviceRoot = IOService::getServiceRoot();
4054                    if (serviceRoot) {
4055                        IOServiceTrace(IOSERVICE_KEXTD_READY, 0, 0, 0, 0);
4056                        serviceRoot->adjustBusy(-1);
4057                        clearedBusy = true;
4058                    }
4059                }
4060#endif
4061                kr = kIOReturnSuccess;
4062            }
4063            break;
4064
4065        default:
4066            kr = kIOReturnBadArgument;
4067            break;
4068    }
4069
4070    if (obj) obj->release();
4071
4072    *result = kr;
4073    return( KERN_SUCCESS);
4074}
4075
4076/* Routine io_catalog_terminate */
4077kern_return_t is_io_catalog_terminate(
4078	mach_port_t master_port,
4079	uint32_t flag,
4080	io_name_t name )
4081{
4082    kern_return_t	   kr;
4083
4084    if( master_port != master_device_port )
4085        return kIOReturnNotPrivileged;
4086
4087    kr = IOUserClient::clientHasPrivilege( (void *) current_task(),
4088                                            kIOClientPrivilegeAdministrator );
4089    if( kIOReturnSuccess != kr)
4090        return( kr );
4091
4092    switch ( flag ) {
4093#if !defined(SECURE_KERNEL)
4094        case kIOCatalogServiceTerminate:
4095            OSIterator *	iter;
4096            IOService *		service;
4097
4098            iter = IORegistryIterator::iterateOver(gIOServicePlane,
4099                                        kIORegistryIterateRecursively);
4100            if ( !iter )
4101                return kIOReturnNoMemory;
4102
4103            do {
4104                iter->reset();
4105                while( (service = (IOService *)iter->getNextObject()) ) {
4106                    if( service->metaCast(name)) {
4107                        if ( !service->terminate( kIOServiceRequired
4108                                                | kIOServiceSynchronous) ) {
4109                            kr = kIOReturnUnsupported;
4110                            break;
4111                        }
4112                    }
4113                }
4114            } while( !service && !iter->isValid());
4115            iter->release();
4116            break;
4117
4118        case kIOCatalogModuleUnload:
4119        case kIOCatalogModuleTerminate:
4120            kr = gIOCatalogue->terminateDriversForModule(name,
4121                                        flag == kIOCatalogModuleUnload);
4122            break;
4123#endif
4124
4125        default:
4126            kr = kIOReturnBadArgument;
4127            break;
4128    }
4129
4130    return( kr );
4131}
4132
4133/* Routine io_catalog_get_data */
4134kern_return_t is_io_catalog_get_data(
4135        mach_port_t		master_port,
4136        uint32_t                flag,
4137        io_buf_ptr_t 		*outData,
4138        mach_msg_type_number_t 	*outDataCount)
4139{
4140    kern_return_t kr = kIOReturnSuccess;
4141    OSSerialize * s;
4142
4143    if( master_port != master_device_port)
4144        return kIOReturnNotPrivileged;
4145
4146    //printf("io_catalog_get_data called. flag: %d\n", flag);
4147
4148    s = OSSerialize::withCapacity(4096);
4149    if ( !s )
4150        return kIOReturnNoMemory;
4151
4152    s->clearText();
4153
4154    kr = gIOCatalogue->serializeData(flag, s);
4155
4156    if ( kr == kIOReturnSuccess ) {
4157        vm_offset_t data;
4158        vm_map_copy_t copy;
4159        vm_size_t size;
4160
4161        size = s->getLength();
4162        kr = vm_allocate(kernel_map, &data, size, VM_FLAGS_ANYWHERE);
4163        if ( kr == kIOReturnSuccess ) {
4164            bcopy(s->text(), (void *)data, size);
4165            kr = vm_map_copyin(kernel_map, (vm_map_address_t)data,
4166			       (vm_map_size_t)size, true, &copy);
4167            *outData = (char *)copy;
4168            *outDataCount = size;
4169        }
4170    }
4171
4172    s->release();
4173
4174    return kr;
4175}
4176
4177/* Routine io_catalog_get_gen_count */
4178kern_return_t is_io_catalog_get_gen_count(
4179        mach_port_t		master_port,
4180        uint32_t                *genCount)
4181{
4182    if( master_port != master_device_port)
4183        return kIOReturnNotPrivileged;
4184
4185    //printf("io_catalog_get_gen_count called.\n");
4186
4187    if ( !genCount )
4188        return kIOReturnBadArgument;
4189
4190    *genCount = gIOCatalogue->getGenerationCount();
4191
4192    return kIOReturnSuccess;
4193}
4194
4195/* Routine io_catalog_module_loaded.
4196 * Is invoked from IOKitLib's IOCatalogueModuleLoaded(). Doesn't seem to be used.
4197 */
4198kern_return_t is_io_catalog_module_loaded(
4199        mach_port_t		master_port,
4200        io_name_t               name)
4201{
4202    if( master_port != master_device_port)
4203        return kIOReturnNotPrivileged;
4204
4205    //printf("io_catalog_module_loaded called. name %s\n", name);
4206
4207    if ( !name )
4208        return kIOReturnBadArgument;
4209
4210    gIOCatalogue->moduleHasLoaded(name);
4211
4212    return kIOReturnSuccess;
4213}
4214
4215kern_return_t is_io_catalog_reset(
4216	mach_port_t		master_port,
4217	uint32_t		flag)
4218{
4219    if( master_port != master_device_port)
4220        return kIOReturnNotPrivileged;
4221
4222    switch ( flag ) {
4223        case kIOCatalogResetDefault:
4224            gIOCatalogue->reset();
4225            break;
4226
4227        default:
4228            return kIOReturnBadArgument;
4229    }
4230
4231    return kIOReturnSuccess;
4232}
4233
4234kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args)
4235{
4236    kern_return_t result = kIOReturnBadArgument;
4237    IOUserClient *userClient;
4238
4239    if ((userClient = OSDynamicCast(IOUserClient,
4240            iokit_lookup_connect_ref_current_task((OSObject *)(args->userClientRef))))) {
4241        IOExternalTrap *trap;
4242        IOService *target = NULL;
4243
4244        trap = userClient->getTargetAndTrapForIndex(&target, args->index);
4245
4246        if (trap && target) {
4247            IOTrap func;
4248
4249            func = trap->func;
4250
4251            if (func) {
4252                result = (target->*func)(args->p1, args->p2, args->p3, args->p4, args->p5, args->p6);
4253            }
4254        }
4255
4256        userClient->release();
4257    }
4258
4259    return result;
4260}
4261
4262} /* extern "C" */
4263
4264IOReturn IOUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args,
4265					IOExternalMethodDispatch * dispatch, OSObject * target, void * reference )
4266{
4267    IOReturn    err;
4268    IOService * object;
4269    IOByteCount structureOutputSize;
4270
4271    if (dispatch)
4272    {
4273	uint32_t count;
4274	count = dispatch->checkScalarInputCount;
4275	if ((kIOUCVariableStructureSize != count) && (count != args->scalarInputCount))
4276	{
4277	    return (kIOReturnBadArgument);
4278	}
4279
4280	count = dispatch->checkStructureInputSize;
4281	if ((kIOUCVariableStructureSize != count)
4282	    && (count != ((args->structureInputDescriptor)
4283			    ? args->structureInputDescriptor->getLength() : args->structureInputSize)))
4284	{
4285	    return (kIOReturnBadArgument);
4286	}
4287
4288	count = dispatch->checkScalarOutputCount;
4289	if ((kIOUCVariableStructureSize != count) && (count != args->scalarOutputCount))
4290	{
4291	    return (kIOReturnBadArgument);
4292	}
4293
4294	count = dispatch->checkStructureOutputSize;
4295	if ((kIOUCVariableStructureSize != count)
4296	    && (count != ((args->structureOutputDescriptor)
4297			    ? args->structureOutputDescriptor->getLength() : args->structureOutputSize)))
4298	{
4299	    return (kIOReturnBadArgument);
4300	}
4301
4302	if (dispatch->function)
4303	    err = (*dispatch->function)(target, reference, args);
4304	else
4305	    err = kIOReturnNoCompletion;	    /* implementator can dispatch */
4306
4307	return (err);
4308    }
4309
4310
4311    // pre-Leopard API's don't do ool structs
4312    if (args->structureInputDescriptor || args->structureOutputDescriptor)
4313    {
4314       err = kIOReturnIPCError;
4315       return (err);
4316    }
4317
4318    structureOutputSize = args->structureOutputSize;
4319
4320    if (args->asyncWakePort)
4321    {
4322	IOExternalAsyncMethod *	method;
4323
4324	if( !(method = getAsyncTargetAndMethodForIndex(&object, selector)) )
4325	    return (kIOReturnUnsupported);
4326
4327    if (kIOUCForegroundOnly & method->flags)
4328    {
4329	/* is graphics access denied for current task? */
4330	if (proc_get_task_selfgpuacc_deny() != 0)
4331            return (kIOReturnNotPermitted);
4332    }
4333
4334	switch (method->flags & kIOUCTypeMask)
4335	{
4336	    case kIOUCScalarIStructI:
4337		err = shim_io_async_method_scalarI_structureI( method, object,
4338					args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4339					args->scalarInput, args->scalarInputCount,
4340					(char *)args->structureInput, args->structureInputSize );
4341		break;
4342
4343	    case kIOUCScalarIScalarO:
4344		err = shim_io_async_method_scalarI_scalarO( method, object,
4345					args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4346					args->scalarInput, args->scalarInputCount,
4347					args->scalarOutput, &args->scalarOutputCount );
4348		break;
4349
4350	    case kIOUCScalarIStructO:
4351		err = shim_io_async_method_scalarI_structureO( method, object,
4352					args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4353					args->scalarInput, args->scalarInputCount,
4354					(char *) args->structureOutput, &args->structureOutputSize );
4355		break;
4356
4357
4358	    case kIOUCStructIStructO:
4359		err = shim_io_async_method_structureI_structureO( method, object,
4360					args->asyncWakePort, args->asyncReference, args->asyncReferenceCount,
4361					(char *)args->structureInput, args->structureInputSize,
4362					(char *) args->structureOutput, &args->structureOutputSize );
4363		break;
4364
4365	    default:
4366		err = kIOReturnBadArgument;
4367		break;
4368	}
4369    }
4370    else
4371    {
4372	IOExternalMethod *	method;
4373
4374	if( !(method = getTargetAndMethodForIndex(&object, selector)) )
4375	    return (kIOReturnUnsupported);
4376
4377    if (kIOUCForegroundOnly & method->flags)
4378    {
4379	/* is graphics access denied for current task? */
4380	if (proc_get_task_selfgpuacc_deny() != 0)
4381            return (kIOReturnNotPermitted);
4382
4383    }
4384
4385	switch (method->flags & kIOUCTypeMask)
4386	{
4387	    case kIOUCScalarIStructI:
4388		err = shim_io_connect_method_scalarI_structureI( method, object,
4389					args->scalarInput, args->scalarInputCount,
4390					(char *) args->structureInput, args->structureInputSize );
4391		break;
4392
4393	    case kIOUCScalarIScalarO:
4394		err = shim_io_connect_method_scalarI_scalarO( method, object,
4395					args->scalarInput, args->scalarInputCount,
4396					args->scalarOutput, &args->scalarOutputCount );
4397		break;
4398
4399	    case kIOUCScalarIStructO:
4400		err = shim_io_connect_method_scalarI_structureO( method, object,
4401					args->scalarInput, args->scalarInputCount,
4402					(char *) args->structureOutput, &structureOutputSize );
4403		break;
4404
4405
4406	    case kIOUCStructIStructO:
4407		err = shim_io_connect_method_structureI_structureO( method, object,
4408					(char *) args->structureInput, args->structureInputSize,
4409					(char *) args->structureOutput, &structureOutputSize );
4410		break;
4411
4412	    default:
4413		err = kIOReturnBadArgument;
4414		break;
4415	}
4416    }
4417
4418    args->structureOutputSize = structureOutputSize;
4419
4420    return (err);
4421}
4422
4423
4424#if __LP64__
4425OSMetaClassDefineReservedUnused(IOUserClient, 0);
4426OSMetaClassDefineReservedUnused(IOUserClient, 1);
4427#else
4428OSMetaClassDefineReservedUsed(IOUserClient, 0);
4429OSMetaClassDefineReservedUsed(IOUserClient, 1);
4430#endif
4431OSMetaClassDefineReservedUnused(IOUserClient, 2);
4432OSMetaClassDefineReservedUnused(IOUserClient, 3);
4433OSMetaClassDefineReservedUnused(IOUserClient, 4);
4434OSMetaClassDefineReservedUnused(IOUserClient, 5);
4435OSMetaClassDefineReservedUnused(IOUserClient, 6);
4436OSMetaClassDefineReservedUnused(IOUserClient, 7);
4437OSMetaClassDefineReservedUnused(IOUserClient, 8);
4438OSMetaClassDefineReservedUnused(IOUserClient, 9);
4439OSMetaClassDefineReservedUnused(IOUserClient, 10);
4440OSMetaClassDefineReservedUnused(IOUserClient, 11);
4441OSMetaClassDefineReservedUnused(IOUserClient, 12);
4442OSMetaClassDefineReservedUnused(IOUserClient, 13);
4443OSMetaClassDefineReservedUnused(IOUserClient, 14);
4444OSMetaClassDefineReservedUnused(IOUserClient, 15);
4445
4446