static mach_port_name_t makeSendRightForTask( task_t task,
io_object_t obj, ipc_kobject_type_t type );
- virtual void free();
+ virtual void free() APPLE_KEXT_OVERRIDE;
};
#define super OSObject
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-class IOUserNotification : public OSIterator
+class IOUserIterator : public OSIterator
+{
+ OSDeclareDefaultStructors(IOUserIterator)
+public:
+ OSObject * userIteratorObject;
+ IOLock * lock;
+
+ static IOUserIterator * withIterator(OSIterator * iter);
+ virtual bool init( void ) APPLE_KEXT_OVERRIDE;
+ virtual void free() APPLE_KEXT_OVERRIDE;
+
+ virtual void reset() APPLE_KEXT_OVERRIDE;
+ virtual bool isValid() APPLE_KEXT_OVERRIDE;
+ virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+class IOUserNotification : public IOUserIterator
{
OSDeclareDefaultStructors(IOUserNotification)
- IONotifier * holdNotify;
- IOLock * lock;
+#define holdNotify userIteratorObject
public:
- virtual bool init( void );
- virtual void free();
+ virtual void free() APPLE_KEXT_OVERRIDE;
virtual void setNotification( IONotifier * obj );
- virtual void reset();
- virtual bool isValid();
+ virtual void reset() APPLE_KEXT_OVERRIDE;
+ virtual bool isValid() APPLE_KEXT_OVERRIDE;
};
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+OSDefineMetaClassAndStructors( IOUserIterator, OSIterator )
+
+IOUserIterator *
+IOUserIterator::withIterator(OSIterator * iter)
+{
+ IOUserIterator * me;
+
+ if (!iter) return (0);
+
+ me = new IOUserIterator;
+ if (me && !me->init())
+ {
+ me->release();
+ me = 0;
+ }
+ if (!me) return me;
+ me->userIteratorObject = iter;
+
+ return (me);
+}
+
+bool
+IOUserIterator::init( void )
+{
+ if (!OSObject::init()) return (false);
+
+ lock = IOLockAlloc();
+ if( !lock)
+ return( false );
+
+ return (true);
+}
+
+void
+IOUserIterator::free()
+{
+ if (userIteratorObject) userIteratorObject->release();
+ if (lock) IOLockFree(lock);
+ OSObject::free();
+}
+
+void
+IOUserIterator::reset()
+{
+ IOLockLock(lock);
+ assert(OSDynamicCast(OSIterator, userIteratorObject));
+ ((OSIterator *)userIteratorObject)->reset();
+ IOLockUnlock(lock);
+}
+
+bool
+IOUserIterator::isValid()
+{
+ bool ret;
+
+ IOLockLock(lock);
+ assert(OSDynamicCast(OSIterator, userIteratorObject));
+ ret = ((OSIterator *)userIteratorObject)->isValid();
+ IOLockUnlock(lock);
+
+ return (ret);
+}
+
+OSObject *
+IOUserIterator::getNextObject()
+{
+ OSObject * ret;
+
+ IOLockLock(lock);
+ assert(OSDynamicCast(OSIterator, userIteratorObject));
+ ret = ((OSIterator *)userIteratorObject)->getNextObject();
+ IOLockUnlock(lock);
+
+ return (ret);
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
extern "C" {
virtual bool init( mach_port_t port, natural_t type,
void * reference, vm_size_t referenceSize,
bool clientIs64 );
- virtual void free();
+ virtual void free() APPLE_KEXT_OVERRIDE;
static bool _handler( void * target,
void * ref, IOService * newService, IONotifier * notifier );
virtual bool handler( void * ref, IOService * newService );
- virtual OSObject * getNextObject();
+ virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
};
class IOServiceMessageUserNotification : public IOUserNotification
vm_size_t extraSize,
bool clientIs64 );
- virtual void free();
+ virtual void free() APPLE_KEXT_OVERRIDE;
static IOReturn _handler( void * target, void * ref,
UInt32 messageType, IOService * provider,
UInt32 messageType, IOService * provider,
void * messageArgument, vm_size_t argSize );
- virtual OSObject * getNextObject();
+ virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#undef super
-#define super OSIterator
-OSDefineMetaClass( IOUserNotification, OSIterator )
-OSDefineAbstractStructors( IOUserNotification, OSIterator )
+#define super IOUserIterator
+OSDefineMetaClass( IOUserNotification, IOUserIterator )
+OSDefineAbstractStructors( IOUserNotification, IOUserIterator )
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-bool IOUserNotification::init( void )
-{
- if( !super::init())
- return( false );
-
- lock = IOLockAlloc();
- if( !lock)
- return( false );
-
- return( true );
-}
-
void IOUserNotification::free( void )
{
- if( holdNotify)
- holdNotify->remove();
+ if (holdNotify)
+ {
+ assert(OSDynamicCast(IONotifier, holdNotify));
+ ((IONotifier *)holdNotify)->remove();
+ holdNotify = 0;
+ }
// can't be in handler now
- if( lock)
- IOLockFree( lock );
-
super::free();
}
void IOUserNotification::setNotification( IONotifier * notify )
{
- IONotifier * previousNotify;
+ OSObject * previousNotify;
IOLockLock( gIOObjectPortLock);
IOLockUnlock( gIOObjectPortLock);
if( previousNotify)
- previousNotify->remove();
+ {
+ assert(OSDynamicCast(IONotifier, previousNotify));
+ ((IONotifier *)previousNotify)->remove();
+ }
}
void IOUserNotification::reset()
if( !(out = OSDynamicCast( cls, obj))) \
return( kIOReturnBadArgument )
+#define CHECKLOCKED(cls,obj,out) \
+ IOUserIterator * oIter; \
+ cls * out; \
+ if( !(oIter = OSDynamicCast(IOUserIterator, obj))) \
+ return (kIOReturnBadArgument); \
+ if( !(out = OSDynamicCast(cls, oIter->userIteratorObject))) \
+ return (kIOReturnBadArgument)
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// Create a vm_map_copy_t or kalloc'ed data for memory
+// to be copied out. ipc will free after the copyout.
+
+static kern_return_t copyoutkdata( const void * data, vm_size_t len,
+ io_buf_ptr_t * buf )
+{
+ kern_return_t err;
+ vm_map_copy_t copy;
+
+ err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
+ false /* src_destroy */, ©);
+
+ assert( err == KERN_SUCCESS );
+ if( err == KERN_SUCCESS )
+ *buf = (char *) copy;
+
+ return( err );
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Routine io_server_version */
/* Routine io_object_get_class */
kern_return_t is_io_object_get_class(
- io_object_t object,
- io_name_t className )
+ io_object_t object,
+ io_name_t className )
{
- const OSMetaClass* my_obj = NULL;
+ const OSMetaClass* my_obj = NULL;
+ const char * my_class_name = NULL;
- if( !object)
- return( kIOReturnBadArgument );
+ if( !object)
+ return( kIOReturnBadArgument );
- my_obj = object->getMetaClass();
- if (!my_obj) {
- return (kIOReturnNotFound);
- }
+ if ( !my_class_name ) {
+ my_obj = object->getMetaClass();
+ if (!my_obj) {
+ return (kIOReturnNotFound);
+ }
+
+ my_class_name = my_obj->getClassName();
+ }
- strlcpy( className, my_obj->getClassName(), sizeof(io_name_t));
+ strlcpy( className, my_class_name, sizeof(io_name_t));
+
return( kIOReturnSuccess );
}
return( kIOReturnBadArgument );
*conforms = (0 != object->metaCast( className ));
+
return( kIOReturnSuccess );
}
io_object_t iterator,
io_object_t *object )
{
+ IOReturn ret;
OSObject * obj;
CHECK( OSIterator, iterator, iter );
if( obj) {
obj->retain();
*object = obj;
- return( kIOReturnSuccess );
+ ret = kIOReturnSuccess;
} else
- return( kIOReturnNoDevice );
+ ret = kIOReturnNoDevice;
+
+ return (ret);
}
/* Routine io_iterator_reset */
obj = matching_size ? OSUnserializeXML(matching, matching_size)
: OSUnserializeXML(matching);
if( (dict = OSDynamicCast( OSDictionary, obj))) {
+
*matches = service->passiveMatch( dict );
kr = kIOReturnSuccess;
} else
obj = matching_size ? OSUnserializeXML(matching, matching_size)
: OSUnserializeXML(matching);
if( (dict = OSDynamicCast( OSDictionary, obj))) {
- *existing = IOService::getMatchingServices( dict );
+ *existing = IOUserIterator::withIterator(IOService::getMatchingServices( dict ));
kr = kIOReturnSuccess;
} else
kr = kIOReturnBadArgument;
if( master_port != master_device_port)
return( kIOReturnNotPrivileged);
- *iterator = IORegistryIterator::iterateOver(
- IORegistryEntry::getPlane( plane ), options );
+ *iterator = IOUserIterator::withIterator(
+ IORegistryIterator::iterateOver(
+ IORegistryEntry::getPlane( plane ), options ));
return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
}
{
CHECK( IORegistryEntry, registry_entry, entry );
- *iterator = IORegistryIterator::iterateOver( entry,
- IORegistryEntry::getPlane( plane ), options );
+ *iterator = IOUserIterator::withIterator(
+ IORegistryIterator::iterateOver( entry,
+ IORegistryEntry::getPlane( plane ), options ));
return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
}
kern_return_t is_io_registry_iterator_enter_entry(
io_object_t iterator )
{
- CHECK( IORegistryIterator, iterator, iter );
+ CHECKLOCKED( IORegistryIterator, iterator, iter );
+ IOLockLock(oIter->lock);
iter->enterEntry();
+ IOLockUnlock(oIter->lock);
return( kIOReturnSuccess );
}
{
bool didIt;
- CHECK( IORegistryIterator, iterator, iter );
+ CHECKLOCKED( IORegistryIterator, iterator, iter );
+ IOLockLock(oIter->lock);
didIt = iter->exitEntry();
+ IOLockUnlock(oIter->lock);
return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
}
return( kIOReturnSuccess );
}
+
+/* Routine io_registry_entry_from_path */
+kern_return_t is_io_registry_entry_from_path_ool(
+ mach_port_t master_port,
+ io_string_inband_t path,
+ io_buf_ptr_t path_ool,
+ mach_msg_type_number_t path_oolCnt,
+ kern_return_t *result,
+ io_object_t *registry_entry)
+{
+ IORegistryEntry * entry;
+ vm_map_offset_t map_data;
+ const char * cpath;
+ IOReturn res;
+ kern_return_t err;
+
+ if (master_port != master_device_port) return(kIOReturnNotPrivileged);
+
+ map_data = 0;
+ entry = 0;
+ res = err = KERN_SUCCESS;
+ if (path[0]) cpath = path;
+ else
+ {
+ if (!path_oolCnt) return(kIOReturnBadArgument);
+ if (path_oolCnt > (sizeof(io_struct_inband_t) * 1024)) return(kIOReturnMessageTooLarge);
+
+ err = vm_map_copyout(kernel_map, &map_data, (vm_map_copy_t) path_ool);
+ if (KERN_SUCCESS == err)
+ {
+ // must return success to mig after vm_map_copyout() succeeds, so result is actual
+ cpath = CAST_DOWN(const char *, map_data);
+ if (cpath[path_oolCnt - 1]) res = kIOReturnBadArgument;
+ }
+ }
+
+ if ((KERN_SUCCESS == err) && (KERN_SUCCESS == res))
+ {
+ entry = IORegistryEntry::fromPath(cpath);
+ res = entry ? kIOReturnSuccess : kIOReturnNotFound;
+ }
+
+ if (map_data) vm_deallocate(kernel_map, map_data, path_oolCnt);
+
+ if (KERN_SUCCESS != err) res = err;
+ *registry_entry = entry;
+ *result = res;
+
+ return (err);
+}
+
+
/* Routine io_registry_entry_in_plane */
kern_return_t is_io_registry_entry_in_plane(
io_object_t registry_entry,
return( kIOReturnBadArgument );
}
+/* Routine io_registry_entry_get_path */
+kern_return_t is_io_registry_entry_get_path_ool(
+ io_object_t registry_entry,
+ io_name_t plane,
+ io_string_inband_t path,
+ io_buf_ptr_t *path_ool,
+ mach_msg_type_number_t *path_oolCnt)
+{
+ enum { kMaxPath = 16384 };
+ IOReturn err;
+ int length;
+ char * buf;
+
+ CHECK( IORegistryEntry, registry_entry, entry );
+
+ *path_ool = NULL;
+ *path_oolCnt = 0;
+ length = sizeof(io_string_inband_t);
+ if (entry->getPath(path, &length, IORegistryEntry::getPlane(plane))) err = kIOReturnSuccess;
+ else
+ {
+ length = kMaxPath;
+ buf = IONew(char, length);
+ if (!buf) err = kIOReturnNoMemory;
+ else if (!entry->getPath(buf, &length, IORegistryEntry::getPlane(plane))) err = kIOReturnError;
+ else
+ {
+ *path_oolCnt = length;
+ err = copyoutkdata(buf, length, path_ool);
+ }
+ if (buf) IODelete(buf, char, kMaxPath);
+ }
+
+ return (err);
+}
+
/* Routine io_registry_entry_get_name */
kern_return_t is_io_registry_entry_get_name(
return (kIOReturnSuccess);
}
-// Create a vm_map_copy_t or kalloc'ed data for memory
-// to be copied out. ipc will free after the copyout.
-
-static kern_return_t copyoutkdata( const void * data, vm_size_t len,
- io_buf_ptr_t * buf )
-{
- kern_return_t err;
- vm_map_copy_t copy;
-
- err = vm_map_copyin( kernel_map, CAST_USER_ADDR_T(data), len,
- false /* src_destroy */, ©);
-
- assert( err == KERN_SUCCESS );
- if( err == KERN_SUCCESS )
- *buf = (char *) copy;
-
- return( err );
-}
-
/* Routine io_registry_entry_get_property */
kern_return_t is_io_registry_entry_get_property_bytes(
io_object_t registry_entry,
return( err );
}
+
/* Routine io_registry_entry_set_properties */
kern_return_t is_io_registry_entry_set_properties
(
CHECK( IOService, _service, service );
+ if (!owningTask) return (kIOReturnBadArgument);
+
do
{
if (properties)
CHECK( IOUserClient, connection, client );
+ if (!into_task) return (kIOReturnBadArgument);
+
IOStatisticsClientCall();
map = client->mapClientMemory64( memory_type, into_task, flags, *address );
CHECK( IOUserClient, connection, client );
+ if (!from_task) return (kIOReturnBadArgument);
+
IOStatisticsClientCall();
err = client->clientMemoryForType( (UInt32) memory_type, &options, &memory );
do
{
- if( (kIOUCVariableStructureSize != method->count0)
- && (inputCount != method->count0))
+ if (inputCount != method->count0)
{
IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
continue;
do
{
- if( (kIOUCVariableStructureSize != method->count0)
- && (inputCount != method->count0))
+ if (inputCount != method->count0)
{
IOLog("%s: IOUserClient inputCount count mismatch\n", object->getName());
continue;
if (args->asyncWakePort)
{
IOExternalAsyncMethod * method;
-
- if( !(method = getAsyncTargetAndMethodForIndex(&object, selector)) )
+ object = 0;
+ if( !(method = getAsyncTargetAndMethodForIndex(&object, selector)) || !object )
return (kIOReturnUnsupported);
if (kIOUCForegroundOnly & method->flags)
else
{
IOExternalMethod * method;
-
- if( !(method = getTargetAndMethodForIndex(&object, selector)) )
+ object = 0;
+ if( !(method = getTargetAndMethodForIndex(&object, selector)) || !object )
return (kIOReturnUnsupported);
if (kIOUCForegroundOnly & method->flags)