static IOReturn Feedback360Probe(void *that,CFDictionaryRef propertyTable,io_service_t service,SInt32 *order) { if ((service==0) || ((!IOObjectConformsTo(service,"Xbox360ControllerClass")) && (!IOObjectConformsTo(service,"Wireless360Controller")))) return kIOReturnBadArgument; return S_OK; }
static CFStringRef BSDNameForBlockStorageDevice( io_registry_entry_t service ) { // This should be an IOBlockStorageDevice. It'll have one child, an IOBlockStorageDriver, // which will have one child of its own, an IOMedia. We get the BSD name from the IOMedia. static CFStringRef kUnknownDiskBSDName = CFSTR("disk[??]"); kern_return_t kr = KERN_SUCCESS; io_registry_entry_t driver = MACH_PORT_NULL; kr = IORegistryEntryGetChildEntry( service, kIOServicePlane, &driver ); if ( driver == MACH_PORT_NULL ) return ( kUnknownDiskBSDName ); if ( IOObjectConformsTo(driver, kIOBlockStorageDriverClass) == FALSE ) return ( kUnknownDiskBSDName ); io_registry_entry_t media = MACH_PORT_NULL; kr = IORegistryEntryGetChildEntry( driver, kIOServicePlane, &media ); IOObjectRelease( driver ); if ( media == MACH_PORT_NULL ) return ( kUnknownDiskBSDName ); if ( IOObjectConformsTo(media, kIOMediaClass) == FALSE ) return ( kUnknownDiskBSDName ); CFStringRef str = IORegistryEntryCreateCFProperty( media, CFSTR("BSD Name"), NULL, 0 ); if ( str == NULL ) str = kUnknownDiskBSDName; IOObjectRelease( media ); return ( str ); }
/* * Given disk2s1, look up "disk2" is IOKit and attempt to determine if * it is an optical device. */ int is_optical_media(const char *bsdname) { CFMutableDictionaryRef matchingDict; int ret = 0; io_service_t service, start; kern_return_t kernResult; io_iterator_t iter; if ((matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, bsdname)) == NULL) return(0); start = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict); if (IO_OBJECT_NULL == start) return (0); service = start; // Create an iterator across all parents of the service object passed in. // since only disk2 would match with ConfirmsTo, and not disk2s1, so // we search the parents until we find "Whole", ie, disk2. kernResult = IORegistryEntryCreateIterator(service, kIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents, &iter); if (KERN_SUCCESS == kernResult) { Boolean isWholeMedia = false; IOObjectRetain(service); do { // Lookup "Whole" if we can if (IOObjectConformsTo(service, kIOMediaClass)) { CFTypeRef wholeMedia; wholeMedia = IORegistryEntryCreateCFProperty(service, CFSTR(kIOMediaWholeKey), kCFAllocatorDefault, 0); if (wholeMedia) { isWholeMedia = CFBooleanGetValue(wholeMedia); CFRelease(wholeMedia); } } // If we found "Whole", check the service type. if (isWholeMedia && ( (IOObjectConformsTo(service, kIOCDMediaClass)) || (IOObjectConformsTo(service, kIODVDMediaClass)) )) { ret = 1; // Is optical, skip } IOObjectRelease(service); } while ((service = IOIteratorNext(iter)) && !isWholeMedia); IOObjectRelease(iter); } IOObjectRelease(start); return ret; }
// returns a solid type from an entry and its properties static Solid::DeviceInterface::Type typeFromEntry(const io_registry_entry_t &entry, const QMap<QString, QVariant> &properties) { if (IOObjectConformsTo(entry, "AppleACPICPU")) { return Solid::DeviceInterface::Processor; } if (IOObjectConformsTo(entry, "AppleSmartBattery")) { return Solid::DeviceInterface::Battery; } return Solid::DeviceInterface::Unknown; }
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort) { int retval = 0; CFMutableDictionaryRef matchingDict; kern_return_t rc; io_iterator_t iter; io_service_t service; if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL) return(0); rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter); if ((rc != KERN_SUCCESS) || (!iter)) return(0); service = IOIteratorNext(iter); IOObjectRelease(iter); if (!service) return(0); rc = IORegistryEntryCreateIterator(service, kIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents, &iter); if (!iter) return(0); if (rc != KERN_SUCCESS) { IOObjectRelease(iter); return(0); } /* if */ IOObjectRetain(service); /* add an extra object reference... */ do { if (darwinIsWholeMedia(service)) { if ( (IOObjectConformsTo(service, kIOCDMediaClass)) || (IOObjectConformsTo(service, kIODVDMediaClass)) ) { retval = 1; } /* if */ } /* if */ IOObjectRelease(service); } while ((service = IOIteratorNext(iter)) && (!retval)); IOObjectRelease(iter); IOObjectRelease(service); return(retval); } /* darwinIsMountedDisc */
// returns a solid type from an entry and its properties static Solid::DeviceInterface::Type typeFromEntry(const io_registry_entry_t &entry, const QMap<QString, QVariant> &properties) { if (IOObjectConformsTo(entry, kIOEthernetInterfaceClass)) return Solid::DeviceInterface::NetworkInterface; if (IOObjectConformsTo(entry, "AppleACPICPU")) return Solid::DeviceInterface::Processor; if (IOObjectConformsTo(entry, "IOSerialBSDClient")) return Solid::DeviceInterface::SerialInterface; if (IOObjectConformsTo(entry, "AppleSmartBattery")) return Solid::DeviceInterface::Battery; return Solid::DeviceInterface::Unknown; }
uint16_t OSX_ProbeTargetDrive(const char* id3args_drive, char* mcdi_data) { uint16_t mcdi_data_len = 0; io_object_t cdobject = MACH_PORT_NULL; if (strncmp(id3args_drive, "disk", 4) != 0) { OSX_ScanForCDDrive(); exit(0); } cdobject = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching (kIOMasterPortDefault, 0, id3args_drive) ); if (cdobject == MACH_PORT_NULL) { fprintf(stdout, "No device found at %s; searching for possible drives...\n", id3args_drive); OSX_ScanForCDDrive(); } else if (IOObjectConformsTo(cdobject, kIOCDMediaClass) == false) { fprintf (stdout, "No cd present in drive at %s\n", id3args_drive ); IOObjectRelease(cdobject); cdobject = MACH_PORT_NULL; OSX_ScanForCDDrive(); } else { //we now have a cd object OSX_ReadCDTOC(cdobject); if (cdTOC != NULL) { uint8_t cdType = DetermineCDType(cdTOC); if (cdType == CDOBJECT_AUDIOCD) { mcdi_data_len = FormMCDIdata(mcdi_data); } } } IOObjectRelease(cdobject); cdobject = MACH_PORT_NULL; return mcdi_data_len; }
static io_service_t GetUsbDevice(io_service_t service) { IOReturn status; io_iterator_t iterator = 0; io_service_t device = 0; if (!service) { return device; } status = IORegistryEntryCreateIterator(service, kIOServicePlane, (kIORegistryIterateParents | kIORegistryIterateRecursively), &iterator); if (status == kIOReturnSuccess) { io_service_t currentService; while ((currentService = IOIteratorNext(iterator)) && device == 0) { io_name_t serviceName; status = IORegistryEntryGetNameInPlane(currentService, kIOServicePlane, serviceName); if (status == kIOReturnSuccess && IOObjectConformsTo(currentService, kIOUSBDeviceClassName)) { device = currentService; } else { // Release the service object which is no longer needed (void) IOObjectRelease(currentService); } } // Release the iterator (void) IOObjectRelease(iterator); } return device; }
/* * Try to record the named device as interesting. It * must be an IOMedia device. */ static int record_one_device(char *name) { io_iterator_t drivelist; io_registry_entry_t drive; kern_return_t status; /* * Find the device. */ status = IOServiceGetMatchingServices(masterPort, IOBSDNameMatching(masterPort, kNilOptions, name), &drivelist); if (status != KERN_SUCCESS) errx(1, "couldn't match '%s'", name); /* * Get the first match (should only be one) */ if ((drive = IOIteratorNext(drivelist)) == NULL) errx(1, "'%s' not found", name); if (!IOObjectConformsTo(drive, "IOMedia")) errx(1, "'%s' is not a storage device", name); /* * Record the device. */ if (record_device(drive)) errx(1, "could not record '%s' for monitoring", name); IOObjectRelease(drive); IOObjectRelease(drivelist); return(0); }
IOKitDevice::IOKitDevice(const io_service_t& hService_) : usBusNumber(0), usAddress(0), usConfigurationNum(0), ulSerialNumber(0), ulLocation(0), hSavedService(NULL) { UCHAR ucSerialIndex = 0; szProductDescription[0] = '\0'; szSerialString[0] = '\0'; memset(&stDeviceDescriptor, 0, sizeof(stDeviceDescriptor)); //!! Can initialize in stDeviceDescriptor constructor instead memset(szSystemPath, 0, sizeof(szSystemPath)); if(hService_ == 0) throw IOKitError::INVALID_PARAM; if(!IOObjectConformsTo(hService_, "IOUSBDevice")) throw IOKitError::INVALID_PARAM; IOObjectRetain(hService_); hSavedService = hService_; //IOKitError::Enum eReturn; //!!eReturn = IOKitDevice::GetNewDescriptor(ppstDeviceInterface, stDeviceDescriptor); //if(eReturn != IOKitError::SUCCESS) // throw eReturn; IOKitDevice::GetDeviceString(hService_, CFSTR("USB Product Name"), (UCHAR*)szProductDescription, sizeof(szProductDescription)); //could also use "Product Name" (with a search) to get from drivers usVid = IOKitDevice::GetDeviceNumber(hService_, CFSTR("idVendor")); usPid = IOKitDevice::GetDeviceNumber(hService_, CFSTR("idProduct")); usConfigurationNum = IOKitDevice::GetDeviceNumber(hService_, CFSTR("bNumConfigurations")); ulLocation = IOKitDevice::GetDeviceNumber(hService_, CFSTR("locationID")); usAddress = IOKitDevice::GetDeviceNumber(hService_, CFSTR("USB Address")); usBusNumber = ulLocation >> 24; UCHAR bDeviceClass = IOKitDevice::GetDeviceNumber(hService_, CFSTR("bDeviceClass")); UCHAR bDeviceSubClass = IOKitDevice::GetDeviceNumber(hService_, CFSTR("bDeviceSubClass")); ulSerialNumber = IOKitDevice::GetSerialNumber(hService_, (UCHAR*) szSerialString, sizeof(szSerialString), ucSerialIndex); stDeviceDescriptor.iSerialNumber = (UInt8)ucSerialIndex; //update descriptor with serial string index SNPRINTF(szSystemPath, sizeof(szSystemPath), "%03i-%04x-%04x-%02x-%02x", usAddress, usVid, usPid, bDeviceClass, bDeviceSubClass); //!!eReturn = CheckDeviceSanity(); //if(eReturn != IOKitError::SUCCESS) // throw eReturn; return; }
IOReturn IOFireWireSBP2LibLUN::probe( CFDictionaryRef propertyTable, io_service_t service, SInt32 *order ) { // only load against LUN's if( !service || !IOObjectConformsTo(service, "IOFireWireSBP2LUN") ) return kIOReturnBadArgument; return kIOReturnSuccess; }
IOReturn IOCFPlugIn::Probe( CFDictionaryRef propertyTable, io_service_t service, SInt32 *order ) { // only load against firewire nubs if( !service || !IOObjectConformsTo(service, "IOFireWireNub") ) return kIOReturnBadArgument; return kIOReturnSuccess; }
Boolean IsWholeMedia(io_service_t service) { // // Determine if the object passed in represents an IOMedia (or subclass) object. // If it does, retrieve the "Whole" property. // If this is the whole media object, find out if it is a CD, DVD, or something else. // If it isn't the whole media object, iterate across its parents in the IORegistry // until the whole media object is found. // // Note that media types other than CD and DVD are not distinguished by class name // but are generic IOMedia objects. // Boolean isWholeMedia = false; io_name_t className; kern_return_t kernResult; if (IOObjectConformsTo(service, kIOMediaClass)) { CFTypeRef wholeMedia; wholeMedia = IORegistryEntryCreateCFProperty(service, CFSTR(kIOMediaWholeKey), kCFAllocatorDefault, 0); if (NULL == wholeMedia) { printf("Could not retrieve Whole property\n"); } else { isWholeMedia = CFBooleanGetValue(wholeMedia); CFRelease(wholeMedia); } } if (isWholeMedia) { if (IOObjectConformsTo(service, kIOCDMediaClass)) { printf("is a CD\n"); } else if (IOObjectConformsTo(service, kIODVDMediaClass)) { printf("is a DVD\n"); } else { kernResult = IOObjectGetClass(service, className); printf("is of class %s\n", className); } } return isWholeMedia; }
/* * Check whether an IORegistryEntry refers to a valid * I/O device, and if so, collect the information. */ static int handle_drive(io_registry_entry_t drive, struct drivestats * dstat) { io_registry_entry_t parent; CFMutableDictionaryRef properties; CFStringRef name; CFNumberRef number; kern_return_t status; /* get drive's parent */ status = IORegistryEntryGetParentEntry(drive, kIOServicePlane, &parent); if (status != KERN_SUCCESS) { snmp_log(LOG_ERR, "diskio: device has no parent\n"); /* fprintf(stderr, "device has no parent\n"); */ return(1); } if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) { /* get drive properties */ status = IORegistryEntryCreateCFProperties(drive, &properties, kCFAllocatorDefault, kNilOptions); if (status != KERN_SUCCESS) { snmp_log(LOG_ERR, "diskio: device has no properties\n"); /* fprintf(stderr, "device has no properties\n"); */ return(1); } /* get BSD name and unitnumber from properties */ name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)); number = (CFNumberRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDUnitKey)); /* Collect stats and if succesful store them with the name and unitnumber */ if (name && number && !collect_drive_stats(parent, dstat->stats)) { CFStringGetCString(name, dstat->name, MAXDRIVENAME, CFStringGetSystemEncoding()); CFNumberGetValue(number, kCFNumberSInt32Type, &dstat->bsd_unit_number); num_drives++; } /* clean up, return success */ CFRelease(properties); return(0); } /* failed, don't keep parent */ IOObjectRelease(parent); return(1); }
static int update_disk(diskstats_t *stats, io_registry_entry_t drive, int index) { io_registry_entry_t device; CFDictionaryRef pproperties, properties; int status; /* Get the drives parent, from which we get statistics. */ status = IORegistryEntryGetParentEntry(drive, kIOServicePlane, &device); if (status != KERN_SUCCESS) return -oserror(); if (!IOObjectConformsTo(device, "IOBlockStorageDriver")) { IOObjectRelease(device); return 0; } /* Obtain the drive properties. */ pproperties = 0; status = IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&pproperties, kCFAllocatorDefault, kNilOptions); if (status != KERN_SUCCESS) { IOObjectRelease(device); return -oserror(); } /* Obtain the device properties. */ properties = 0; status = IORegistryEntryCreateCFProperties(device, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, kNilOptions); if (status != KERN_SUCCESS) { IOObjectRelease(device); return -oserror(); } /* Make space to store the actual values, then go get them. */ status = check_stats_size(stats, index + 1); if (status < 0) { IOObjectRelease(device); } else { update_disk_stats(&stats->disks[index], pproperties, properties); update_disk_totals(stats, &stats->disks[index]); } CFRelease(pproperties); CFRelease(properties); return status; }
/* * Determine whether an IORegistryEntry refers to a valid * I/O device, and if so, record it. */ static int record_device(io_registry_entry_t drive) { io_registry_entry_t parent; CFDictionaryRef properties; CFStringRef name; CFNumberRef number; kern_return_t status; /* get drive's parent */ status = IORegistryEntryGetParentEntry(drive, kIOServicePlane, &parent); if (status != KERN_SUCCESS) errx(1, "device has no parent"); if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) { drivestat[num_devices].driver = parent; /* get drive properties */ status = IORegistryEntryCreateCFProperties(drive, (CFMutableDictionaryRef *)&properties, kCFAllocatorDefault, kNilOptions); if (status != KERN_SUCCESS) errx(1, "device has no properties"); /* get name from properties */ name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)); CFStringGetCString(name, drivestat[num_devices].name, MAXDRIVENAME, CFStringGetSystemEncoding()); /* get blocksize from properties */ number = (CFNumberRef)CFDictionaryGetValue(properties, CFSTR(kIOMediaPreferredBlockSizeKey)); CFNumberGetValue(number, kCFNumberSInt64Type, &drivestat[num_devices].blocksize); /* clean up, return success */ CFRelease(properties); num_devices++; return(0); } /* failed, don't keep parent */ IOObjectRelease(parent); return(1); }
static int darwinIsWholeMedia(io_service_t service) { int retval = 0; CFTypeRef wholeMedia; if (!IOObjectConformsTo(service, kIOMediaClass)) return(0); wholeMedia = IORegistryEntryCreateCFProperty(service, CFSTR(kIOMediaWholeKey), kCFAllocatorDefault, 0); if (wholeMedia == NULL) return(0); retval = CFBooleanGetValue(wholeMedia); CFRelease(wholeMedia); return retval; } /* darwinIsWholeMedia */
io_object_t getInterfaceWithName( mach_port_t masterPort, char *className ) { io_iterator_t ite; io_object_t obj = 0; io_name_t name; kern_return_t rc; kern_return_t kr; kr = IORegistryCreateIterator( masterPort, kIOServicePlane, true, /* recursive */ &ite ); if ( kr != kIOReturnSuccess ) { printf( "IORegistryCreateIterator() error %08lx\n", (unsigned long)kr ); return 0; } while ( (obj = IOIteratorNext( ite )) ) { if ( IOObjectConformsTo( obj, (char*)className ) ) { // printf( "Found Realtek UserClient !!\n" ); break; } else { rc = IOObjectGetClass( obj, name ); if ( rc == kIOReturnSuccess ) { // printf( "Skipping class %s\n", name ); } } IOObjectRelease( obj ); obj = 0; } IORegistryDisposeEnumerator( ite ); return obj; }/* end getInterfaceWithName */
kern_return_t IOHIDSetHIDParameterToEventSystem(io_connect_t handle, CFStringRef key, CFTypeRef parameter) { IOHIDEventSystemClientRef client = IOHIDEventSystemClientCreateWithType (kCFAllocatorDefault, kIOHIDEventSystemClientTypeMonitor, NULL); kern_return_t kr = kIOReturnNotReady; if (!client) { goto exit; } kr = kIOReturnUnsupported; io_service_t service = 0; if (IOConnectGetService (handle, &service) == kIOReturnSuccess) { if (IOObjectConformsTo (service, "IOHIDSystem")) { IOHIDEventSystemClientSetProperty(client, key, parameter); kr = kIOReturnSuccess; } else { uint64_t entryID = 0; if (IORegistryEntryGetRegistryEntryID (service, &entryID) == kIOReturnSuccess) { IOHIDServiceClientRef serviceClient = IOHIDEventSystemClientCopyServiceForRegistryID(client, entryID); if (serviceClient) { if (IOHIDServiceClientSetProperty(serviceClient, key, parameter)) { kr = kIOReturnSuccess; } else { kr = kIOReturnInternalError; } CFRelease(serviceClient); } } } IOObjectRelease(service); } exit: if (client) { CFRelease(client); } if (kr) { os_log_error(_IOHIDLog(), "Fail to set parameter with status 0x%x", kr); } return kr; }
kern_return_t IOHIDCopyHIDParameterFromEventSystem(io_connect_t handle, CFStringRef key, CFTypeRef *parameter) { CFTypeRef param = NULL; IOHIDEventSystemClientRef client = IOHIDEventSystemClientCreateWithType (kCFAllocatorDefault, kIOHIDEventSystemClientTypePassive, NULL); kern_return_t kr = kIOReturnNotReady; if (!client) { goto exit; } io_service_t service = 0; if (IOConnectGetService (handle, &service) == kIOReturnSuccess) { if (IOObjectConformsTo (service, "IOHIDSystem")) { param = IOHIDEventSystemClientCopyProperty(client, key); } else { uint64_t entryID = 0; if (IORegistryEntryGetRegistryEntryID (service, &entryID) == kIOReturnSuccess) { IOHIDServiceClientRef serviceClient = IOHIDEventSystemClientCopyServiceForRegistryID(client, entryID); if (serviceClient) { param = IOHIDServiceClientCopyProperty(serviceClient, key); CFRelease(serviceClient); } } } IOObjectRelease(service); } exit: if (param) { *parameter = param; kr = kIOReturnSuccess; } if (client) { CFRelease(client); } if (kr) { os_log_error(_IOHIDLog(), "Fail to get parameter with status 0x%x", kr); } return kr; }
// Determine whether 'dev' is a SMART-capable device. static bool is_smart_capable (io_object_t dev) { CFTypeRef smartCapableKey; CFDictionaryRef diskChars; // If the device has kIOPropertySMARTCapableKey, then it's capable, // no matter what it looks like. smartCapableKey = IORegistryEntryCreateCFProperty (dev, CFSTR (kIOPropertySMARTCapableKey), kCFAllocatorDefault, 0); if (smartCapableKey) { CFRelease (smartCapableKey); return true; } // If it's an kIOATABlockStorageDeviceClass then we're successful // only if its ATA features indicate it supports SMART. if (IOObjectConformsTo (dev, kIOATABlockStorageDeviceClass) && (diskChars = (CFDictionaryRef)IORegistryEntryCreateCFProperty (dev, CFSTR (kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions)) != NULL) { CFNumberRef diskFeatures = NULL; UInt32 ataFeatures = 0; if (CFDictionaryGetValueIfPresent (diskChars, CFSTR ("ATA Features"), (const void **)&diskFeatures)) CFNumberGetValue (diskFeatures, kCFNumberLongType, &ataFeatures); CFRelease (diskChars); if (diskFeatures) CFRelease (diskFeatures); return (ataFeatures & kIOATAFeatureSMART) != 0; } return false; }
int main (int argc, const char *argv[]) { CFMutableDictionaryRef dictRef; io_iterator_t iter; io_service_t service; kern_return_t kr; CFNumberRef numberRef; SInt32 constantOne = 1; constantOne=42; if (argc > 1) { constantOne = atoi(argv[1]); } // The bulk of this code locates all instances of our driver running on the system. // First find all children of our driver. As opposed to nubs, drivers are often not registered // via the registerServices call because nothing is expected to match to them. Unregistered // objects in the I/O Registry are not returned by IOServiceGetMatchingServices. // IOBlockStorageServices is our child in the I/O Registry dictRef = IOServiceMatching("IOBlockStorageServices"); if (!dictRef) { fprintf(stderr, "IOServiceMatching returned NULL.\n"); return -1; } // Create an iterator over all matching IOService nubs. // This consumes a reference on dictRef. kr = IOServiceGetMatchingServices(kIOMasterPortDefault, dictRef, &iter); if (KERN_SUCCESS != kr) { fprintf(stderr, "IOServiceGetMatchingServices returned 0x%08x.\n", kr); CFRelease(dictRef); return -1; } // Create a dictionary to pass to our driver. This dictionary has the key "MyProperty" // and the value an integer 1. dictRef = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &constantOne); CFDictionarySetValue(dictRef, CFSTR("MyProperty"), numberRef); CFRelease(numberRef); // Iterate across all instances of IOBlockStorageServices. while ((service = IOIteratorNext(iter))) { io_registry_entry_t parent; // Now that our child has been found we can traverse the I/O Registry to find our driver. kr = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent); if (KERN_SUCCESS != kr) { fprintf(stderr, "IORegistryEntryGetParentEntry returned 0x%08x.\n", kr); } else { // We're only interested in the parent object if it's our driver class. if (IOObjectConformsTo(parent, "fi_dungeon_driver_IOSATDriver")) { // This is the function that results in ::setProperties() being called in our // kernel driver. The dictionary we created is passed to the driver here. kr = IORegistryEntrySetCFProperties(parent, dictRef); if (KERN_SUCCESS != kr) { fprintf(stderr, "IORegistryEntrySetCFProperties returned 0x%08x.\n", kr); } } // Done with the parent object. IOObjectRelease(parent); } // Done with the object returned by the iterator. IOObjectRelease(service); } if (iter != IO_OBJECT_NULL) { IOObjectRelease(iter); iter = IO_OBJECT_NULL; } if (dictRef) { CFRelease(dictRef); dictRef = NULL; } return 0; }
void MemoryCardDriverThreaded_MacOSX::GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut ) { LockMut( m_ChangedLock ); // First, get all device paths struct statfs *fs; int num = getfsstat( NULL, 0, MNT_NOWAIT ); fs = new struct statfs[num]; num = getfsstat( fs, num * sizeof(struct statfs), MNT_NOWAIT ); ASSERT( num != -1 ); for( int i = 0; i < num; ++i ) { if( strncmp(fs[i].f_mntfromname, _PATH_DEV, strlen(_PATH_DEV)) ) continue; const RString& sDevicePath = fs[i].f_mntfromname; const RString& sDisk = Basename( sDevicePath ); // disk#[[s#] ...] // Now that we have the disk name, look up the IOServices associated with it. CFMutableDictionaryRef dict; if( !(dict = IOBSDNameMatching(kIOMasterPortDefault, 0, sDisk)) ) continue; // Look for certain properties: Leaf, Ejectable, Writable. CFDictionarySetValue( dict, CFSTR(kIOMediaLeafKey), kCFBooleanTrue ); CFDictionarySetValue( dict, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue ); CFDictionarySetValue( dict, CFSTR(kIOMediaWritableKey), kCFBooleanTrue ); // Get the matching iterator. As always, this consumes a reference to dict. io_iterator_t iter; kern_return_t ret = IOServiceGetMatchingServices( kIOMasterPortDefault, dict, &iter ); if( ret != KERN_SUCCESS || iter == 0 ) continue; // I'm not quite sure what it means to have two services with this device. // Iterate over them all. If one contains what we want, stop. io_registry_entry_t device; // This is the same as an io_object_t. while( (device = IOIteratorNext(iter)) ) { // Look at the parent of the device until we see an IOUSBMassStorageClass while( device != MACH_PORT_NULL && !IOObjectConformsTo(device, "IOUSBMassStorageClass") ) { io_registry_entry_t entry; ret = IORegistryEntryGetParentEntry( device, kIOServicePlane, &entry ); IOObjectRelease( device ); device = ret == KERN_SUCCESS? entry:MACH_PORT_NULL; } // Now look for the corresponding IOUSBDevice, it's likely 2 up the tree while( device != MACH_PORT_NULL && !IOObjectConformsTo(device, "IOUSBDevice") ) { io_registry_entry_t entry; ret = IORegistryEntryGetParentEntry( device, kIOServicePlane, &entry ); IOObjectRelease( device ); device = ret == KERN_SUCCESS? entry:MACH_PORT_NULL; } if( device == MACH_PORT_NULL ) continue; // At this point, it is pretty safe to say that we've found a USB device. vDevicesOut.push_back( UsbStorageDevice() ); UsbStorageDevice& usbd = vDevicesOut.back(); LOG->Trace( "Found memory card at path: %s.", fs[i].f_mntonname ); usbd.SetOsMountDir( fs[i].f_mntonname ); usbd.iVolumeSizeMB = int( (uint64_t(fs[i].f_blocks) * fs[i].f_bsize) >> 20 ); // Now we can get some more information from the registry tree. usbd.iBus = GetIntProperty( device, CFSTR("USB Address") ); usbd.iPort = GetIntProperty( device, CFSTR("PortNum") ); // usbd.iLevel ? usbd.sSerial = GetStringProperty( device, CFSTR("USB Serial Number") ); usbd.sDevice = fs[i].f_mntfromname; usbd.idVendor = GetIntProperty( device, CFSTR(kUSBVendorID) ); usbd.idProduct = GetIntProperty( device, CFSTR(kUSBProductID) ); usbd.sVendor = GetStringProperty( device, CFSTR("USB Vendor Name") ); usbd.sProduct = GetStringProperty( device, CFSTR("USB Product Name") ); IOObjectRelease( device ); break; // We found what we wanted } IOObjectRelease( iter ); } m_bChanged = false; delete[] fs; }
static kern_return_t CopyUserVisiblePortName(io_object_t interface, CFMutableDictionaryRef interfaceInfo, CFStringRef *userVisibleName) // Given an IOKit device (interface) and a dictionary of // information about the device (interfaceInfo), guess at the // user-visible name for the device. The basic algorithm is // as follows: // // 1. Decide on a proposed user-visible name, using heuristics // that are based on the device type. While doing this add // keyword substition values to interfaceInfo. // // 2. Call the client's callback to see whether it wants to // modify our decision. // // 3. Finally, replace certain keywords in the string with // values from the interfaceInfo dictionary. // // This design allows the client callback to see a limited number // of strings, and hence makes it easy for the client to localise // those strings. It also means we only have one set of I/O Registry // parsing code (in step 1), rather than messing with IOKit once in // step 1 to decide on the device type and again in step 3 when // doing the keyword replacement. { kern_return_t err; CFStringRef proposedName; CFStringRef baseName; assert(interface != 0 ); assert(interfaceInfo != NULL); assert( userVisibleName != NULL); assert(*userVisibleName == NULL); proposedName = NULL; baseName = NULL; // First we synthesise our candidate user-visible name. if ( IOObjectConformsTo(interface, kIOEthernetInterfaceClass) ) { err = CopyUserVisibleNameForEthernetPort(interface, interfaceInfo, &proposedName); } else if ( IOObjectConformsTo(interface, kIOSerialBSDServiceValue) ) { err = CopyUserVisibleNameForModemOrSerialPort(interface, interfaceInfo, &proposedName); } else { err = 0; proposedName = (CFStringRef) IORegistryEntryCreateCFProperty(interface, CFSTR(kIOBSDNameKey), NULL, kNilOptions); if (proposedName == NULL) { err = -1; } } // Then we ask our client to munge it as it likes. if (gPortNameCallback != NULL) { err = gPortNameCallback(interface, interfaceInfo, proposedName, &baseName); } else { // The debug build complains if you don't install a callback because, // hey, localisability is important. #if MORE_DEBUG { static Boolean gHavePrinted; if ( !gHavePrinted ) { fprintf(stderr, "MoreSCFPortScanner.c: You should install a port name callback.\n"); gHavePrinted = true; } } #endif } // If we didn't get a baseName, just use proposedName. if ( (err == 0) && (baseName == NULL) ) { baseName = CFStringCreateCopy(NULL, proposedName); if (baseName == NULL) { err = -1; } } // Then we do keyword substitution (as specified in the header file) on the result. if (err == 0) { err = SubstituteKeywordsInUserVisibleName(interface, interfaceInfo, baseName, userVisibleName); } CFQRelease(proposedName); CFQRelease(baseName); assert( (err == 0) == (*userVisibleName != NULL) ); return err; }
/** * Guess the media that a volume/partition is on */ MythMediaType FindMediaType(io_service_t service) { kern_return_t kernResult; io_iterator_t iter; MythMediaType mediaType = MEDIATYPE_UNKNOWN; QString msg = QString("FindMediaType() - "); bool isWholeMedia = false; // Create an iterator across all parents of the service object passed in. kernResult = IORegistryEntryCreateIterator(service, kIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents, &iter); if (KERN_SUCCESS != kernResult) LOG(VB_GENERAL, LOG_CRIT, msg + QString("IORegistryEntryCreateIterator returned %1") .arg(kernResult)); else if (!iter) LOG(VB_GENERAL, LOG_CRIT, msg + "IORegistryEntryCreateIterator returned NULL iterator"); else { // A reference on the initial service object is released in // the do-while loop below, so add a reference to balance IOObjectRetain(service); do { isWholeMedia = false; if (IOObjectConformsTo(service, kIOMediaClass)) { CFTypeRef wholeMedia; wholeMedia = IORegistryEntryCreateCFProperty (service, CFSTR(kIOMediaWholeKey), kCFAllocatorDefault, 0); if (!wholeMedia) LOG(VB_GENERAL, LOG_ALERT, msg + "Could not retrieve Whole property"); else { isWholeMedia = CFBooleanGetValue((CFBooleanRef)wholeMedia); CFRelease(wholeMedia); } } if (isWholeMedia) { if (IOObjectConformsTo(service, kIODVDMediaClass)) mediaType = MEDIATYPE_DVD; else if (IOObjectConformsTo(service, kIOCDMediaClass)) mediaType = MEDIATYPE_AUDIO; } IOObjectRelease(service); } while ((service = IOIteratorNext(iter)) && (mediaType == MEDIATYPE_UNKNOWN)); IOObjectRelease(iter); } return mediaType; }
/**************************************************************************** * darwin_getTOC: get the TOC ****************************************************************************/ static CDTOC *darwin_getTOC( vlc_object_t * p_this, const vcddev_t *p_vcddev ) { mach_port_t port; char *psz_devname; kern_return_t ret; CDTOC *pTOC = NULL; io_iterator_t iterator; io_registry_entry_t service; CFMutableDictionaryRef properties; CFDataRef data; /* get the device name */ if( ( psz_devname = strrchr( p_vcddev->psz_dev, '/') ) != NULL ) ++psz_devname; else psz_devname = p_vcddev->psz_dev; /* unraw the device name */ if( *psz_devname == 'r' ) ++psz_devname; /* get port for IOKit communication */ if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IOMasterPort: 0x%08x", ret ); return( NULL ); } /* get service iterator for the device */ if( ( ret = IOServiceGetMatchingServices( port, IOBSDNameMatching( port, 0, psz_devname ), &iterator ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IOServiceGetMatchingServices: 0x%08x", ret ); return( NULL ); } /* first service */ service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); /* search for kIOCDMediaClass */ while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) ) { if( ( ret = IORegistryEntryGetParentIterator( service, kIOServicePlane, &iterator ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IORegistryEntryGetParentIterator: 0x%08x", ret ); IOObjectRelease( service ); return( NULL ); } IOObjectRelease( service ); service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); } if( !service ) { msg_Err( p_this, "search for kIOCDMediaClass came up empty" ); return( NULL ); } /* create a CF dictionary containing the TOC */ if( ( ret = IORegistryEntryCreateCFProperties( service, &properties, kCFAllocatorDefault, kNilOptions ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IORegistryEntryCreateCFProperties: 0x%08x", ret ); IOObjectRelease( service ); return( NULL ); } /* get the TOC from the dictionary */ if( ( data = (CFDataRef) CFDictionaryGetValue( properties, CFSTR(kIOCDMediaTOCKey) ) ) != NULL ) { CFRange range; CFIndex buf_len; buf_len = CFDataGetLength( data ) + 1; range = CFRangeMake( 0, buf_len ); if( ( pTOC = malloc( buf_len ) ) != NULL ) { CFDataGetBytes( data, range, (u_char *)pTOC ); } } else { msg_Err( p_this, "CFDictionaryGetValue failed" ); } CFRelease( properties ); IOObjectRelease( service ); return( pTOC ); }
void genIOKitDevice(const io_service_t& device, const io_service_t& parent, const io_name_t plane, int depth, QueryData& results) { Row r; io_name_t name, device_class; auto kr = IORegistryEntryGetName(device, name); if (kr == KERN_SUCCESS) { r["name"] = std::string(name); } // Get the device class. kr = IOObjectGetClass(device, device_class); if (kr == KERN_SUCCESS) { r["class"] = std::string(device_class); } // The entry into the registry is the ID, and is used for children as parent. uint64_t device_id, parent_id; kr = IORegistryEntryGetRegistryEntryID(device, &device_id); if (kr == KERN_SUCCESS) { r["id"] = BIGINT(device_id); } else { r["id"] = "-1"; } kr = IORegistryEntryGetRegistryEntryID(parent, &parent_id); if (kr == KERN_SUCCESS) { r["parent"] = BIGINT(parent_id); } else { r["parent"] = "-1"; } r["depth"] = INTEGER(depth); if (IORegistryEntryInPlane(device, kIODeviceTreePlane)) { io_string_t device_path; kr = IORegistryEntryGetPath(device, kIODeviceTreePlane, device_path); if (kr == KERN_SUCCESS) { // Remove the "IODeviceTree:" from the device tree path. r["device_path"] = std::string(device_path).substr(13); } } // Fill in service bits and busy/latency time. if (IOObjectConformsTo(device, "IOService")) { r["service"] = "1"; } else { r["service"] = "0"; } uint32_t busy_state; kr = IOServiceGetBusyState(device, &busy_state); if (kr == KERN_SUCCESS) { r["busy_state"] = INTEGER(busy_state); } else { r["busy_state"] = "0"; } auto retain_count = IOObjectGetKernelRetainCount(device); r["retain_count"] = INTEGER(retain_count); results.push_back(r); }
/* * Return a Python dict of tuples for disk I/O information */ static PyObject* get_disk_io_counters(PyObject* self, PyObject* args) { PyObject* py_retdict = PyDict_New(); PyObject* py_disk_info; CFDictionaryRef parent_dict; CFDictionaryRef props_dict; CFDictionaryRef stats_dict; io_registry_entry_t parent; io_registry_entry_t disk; io_iterator_t disk_list; /* Get list of disks */ if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(kIOMediaClass), &disk_list) != kIOReturnSuccess) { Py_DECREF(py_retdict); PyErr_SetString(PyExc_RuntimeError, "Unable to get the list of disks."); return NULL; } /* Iterate over disks */ while ((disk = IOIteratorNext(disk_list)) != 0) { parent_dict = NULL; props_dict = NULL; stats_dict = NULL; if (IORegistryEntryGetParentEntry(disk, kIOServicePlane, &parent) != kIOReturnSuccess) { PyErr_SetString(PyExc_RuntimeError, "Unable to get the disk's parent."); Py_DECREF(py_retdict); IOObjectRelease(disk); return NULL; } if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) { if(IORegistryEntryCreateCFProperties( disk, (CFMutableDictionaryRef *) &parent_dict, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) { PyErr_SetString(PyExc_RuntimeError, "Unable to get the parent's properties."); Py_DECREF(py_retdict); IOObjectRelease(disk); IOObjectRelease(parent); return NULL; } if (IORegistryEntryCreateCFProperties(parent, (CFMutableDictionaryRef *) &props_dict, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) { PyErr_SetString(PyExc_RuntimeError, "Unable to get the disk properties."); Py_DECREF(py_retdict); IOObjectRelease(disk); return NULL; } const int kMaxDiskNameSize = 64; CFStringRef disk_name_ref = (CFStringRef)CFDictionaryGetValue( parent_dict, CFSTR(kIOBSDNameKey)); char disk_name[kMaxDiskNameSize]; CFStringGetCString(disk_name_ref, disk_name, kMaxDiskNameSize, CFStringGetSystemEncoding()); stats_dict = (CFDictionaryRef)CFDictionaryGetValue( props_dict, CFSTR(kIOBlockStorageDriverStatisticsKey)); if (stats_dict == NULL) { PyErr_SetString(PyExc_RuntimeError, "Unable to get disk stats."); Py_DECREF(py_retdict); CFRelease(props_dict); IOObjectRelease(disk); IOObjectRelease(parent); return NULL; } CFNumberRef number; int64_t reads, writes, read_bytes, write_bytes, read_time, write_time = 0; /* Get disk reads/writes */ if ((number = (CFNumberRef)CFDictionaryGetValue( stats_dict, CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &reads); } if ((number = (CFNumberRef)CFDictionaryGetValue( stats_dict, CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &writes); } /* Get disk bytes read/written */ if ((number = (CFNumberRef)CFDictionaryGetValue( stats_dict, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &read_bytes); } if ((number = (CFNumberRef)CFDictionaryGetValue( stats_dict, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &write_bytes); } /* Get disk time spent reading/writing (nanoseconds) */ if ((number = (CFNumberRef)CFDictionaryGetValue( stats_dict, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &read_time); } if ((number = (CFNumberRef)CFDictionaryGetValue( stats_dict, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) { CFNumberGetValue(number, kCFNumberSInt64Type, &write_time); } // Read/Write time on OS X comes back in nanoseconds and in psutil // we've standardized on milliseconds so do the conversion. py_disk_info = Py_BuildValue("(KKKKKK)", reads, writes, read_bytes, write_bytes, read_time / 1000, write_time / 1000); PyDict_SetItemString(py_retdict, disk_name, py_disk_info); Py_XDECREF(py_disk_info); CFRelease(parent_dict); IOObjectRelease(parent); CFRelease(props_dict); IOObjectRelease(disk); } } IOObjectRelease (disk_list); return py_retdict; }
static IOReturn PrintSMARTDataForBSDNode ( const char * bsdNode ) { IOReturn error = kIOReturnError; io_object_t object = MACH_PORT_NULL; io_object_t parent = MACH_PORT_NULL; bool found = false; char * bsdName = NULL; char deviceName[MAXPATHLEN]; sprintf ( deviceName, "%s", bsdNode ); if ( !strncmp ( deviceName, "/dev/r", 6 ) ) { // Strip off the /dev/r from /dev/rdiskX bsdName = &deviceName[6]; } else if ( !strncmp ( deviceName, "/dev/", 5 ) ) { // Strip off the /dev/r from /dev/rdiskX bsdName = &deviceName[5]; } else { bsdName = deviceName; } require_action ( ( strncmp ( bsdName, "disk", 4 ) == 0 ), ErrorExit, PrintUsage ( ) ); object = IOServiceGetMatchingService ( kIOMasterPortDefault, IOBSDNameMatching ( kIOMasterPortDefault, 0, bsdName ) ); require ( ( object != MACH_PORT_NULL ), ErrorExit ); parent = object; while ( IOObjectConformsTo ( object, kIOATABlockStorageDeviceClass ) == false ) { #if DEBUG io_name_t className; error = IOObjectGetClass ( object, className ); printf ( "Object class = %s\n", ( char * ) className ); #endif error = IORegistryEntryGetParentEntry ( object, kIOServicePlane, &parent ); require ( ( error == kIOReturnSuccess ), ReleaseObject ); require ( ( parent != MACH_PORT_NULL ), ReleaseObject ); IOObjectRelease ( object ); object = parent; } if ( IOObjectConformsTo ( object, kIOATABlockStorageDeviceClass ) ) { PrintSMARTDataForDevice ( object ); found = true; } ReleaseObject: require ( ( object != MACH_PORT_NULL ), ErrorExit ); IOObjectRelease ( object ); object = MACH_PORT_NULL; ErrorExit: if ( found == false ) { printf ( "No S.M.A.R.T. capable device at %s\n", bsdNode ); } return error; }
int BLGetParentDeviceAndPartitionType(BLContextPtr context, const char * partitionDev, char * parentDev, uint32_t *partitionNum, BLPartitionType *partitionType) { int result = 0; kern_return_t kret; io_iterator_t services = MACH_PORT_NULL; io_iterator_t parents = MACH_PORT_NULL; io_registry_entry_t service = MACH_PORT_NULL; io_iterator_t grandparents = MACH_PORT_NULL; io_registry_entry_t service2 = MACH_PORT_NULL; io_object_t obj = MACH_PORT_NULL; CFNumberRef pn = NULL; CFStringRef content = NULL; char par[MNAMELEN]; parentDev[0] = '\0'; kret = IOServiceGetMatchingServices(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, (char *)partitionDev + 5), &services); if (kret != KERN_SUCCESS) { result = 3; goto finish; } // Should only be one IOKit object for this volume. (And we only want one.) obj = IOIteratorNext(services); if (!obj) { result = 4; goto finish; } // we have the IOMedia for the partition. pn = (CFNumberRef)IORegistryEntryCreateCFProperty(obj, CFSTR(kIOMediaPartitionIDKey), kCFAllocatorDefault, 0); if(pn == NULL) { result = 4; goto finish; } if (CFGetTypeID(pn) != CFNumberGetTypeID()) { result = 5; goto finish; } CFNumberGetValue(pn, kCFNumberSInt32Type, partitionNum); kret = IORegistryEntryGetParentIterator (obj, kIOServicePlane, &parents); if (kret) { result = 6; goto finish; /* We'll never loop forever. */ } while ( (service = IOIteratorNext(parents)) != 0 ) { kret = IORegistryEntryGetParentIterator (service, kIOServicePlane, &grandparents); IOObjectRelease(service); service = MACH_PORT_NULL; if (kret) { result = 6; goto finish; /* We'll never loop forever. */ } while ( (service2 = IOIteratorNext(grandparents)) != 0 ) { if (content) { CFRelease(content); content = NULL; } if (!IOObjectConformsTo(service2, "IOMedia")) { IOObjectRelease(service2); service2 = MACH_PORT_NULL; continue; } content = (CFStringRef) IORegistryEntryCreateCFProperty(service2, CFSTR(kIOMediaContentKey), kCFAllocatorDefault, 0); if(CFGetTypeID(content) != CFStringGetTypeID()) { result = 2; goto finish; } if(CFStringCompare(content, CFSTR("Apple_partition_scheme"), 0) == kCFCompareEqualTo) { if(partitionType) *partitionType = kBLPartitionType_APM; } else if(CFStringCompare(content, CFSTR("FDisk_partition_scheme"), 0) == kCFCompareEqualTo) { if(partitionType) *partitionType = kBLPartitionType_MBR; } else if(CFStringCompare(content, CFSTR("GUID_partition_scheme"), 0) == kCFCompareEqualTo) { if(partitionType) *partitionType = kBLPartitionType_GPT; } else { IOObjectRelease(service2); service2 = MACH_PORT_NULL; CFRelease(content); content = NULL; continue; } CFRelease(content); content = IORegistryEntryCreateCFProperty(service2, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0); if(CFGetTypeID(content) != CFStringGetTypeID()) { result = 3; goto finish; } if(!CFStringGetCString(content, par, MNAMELEN, kCFStringEncodingASCII)) { result = 4; goto finish; } CFRelease(content); content = NULL; sprintf(parentDev, "/dev/%s",par); break; } if(parentDev[0] == '\0') { break; } } if(parentDev[0] == '\0') { // nothing found result = 8; goto finish; } finish: if (services != MACH_PORT_NULL) IOObjectRelease(services); if (parents != MACH_PORT_NULL) IOObjectRelease(parents); if (service != MACH_PORT_NULL) IOObjectRelease(service); if (grandparents != MACH_PORT_NULL) IOObjectRelease(grandparents); if (service2 != MACH_PORT_NULL) IOObjectRelease(service2); if (obj != MACH_PORT_NULL) IOObjectRelease(obj); if (pn) CFRelease(pn); if (content) CFRelease(content); return result; }