#ifdef HAVE_CFPLUGIN
#include <IOKit/IOCFPlugIn.h>
CFUUIDRef gIOCFPlugInInterfaceID = NULL;
typedef struct LookUUIDContextStruct {
const void * result;
CFUUIDRef key;
} LookUUIDContext;
static void
_IOGetWithUUIDKey(const void *key, const void * value, void *ctx)
{
LookUUIDContext * context = (LookUUIDContext *) ctx;
CFUUIDRef uuid;
uuid = CFUUIDCreateFromString(NULL, (CFStringRef)key);
if( uuid) {
if( CFEqual( uuid, context->key))
context->result = value;
CFRelease(uuid);
}
}
static kern_return_t
IOFindPlugIns( io_service_t service,
CFUUIDRef pluginType,
CFArrayRef * factories, CFArrayRef * plists )
{
CFURLRef url;
CFPlugInRef onePlugin;
CFBundleRef bundle;
CFDictionaryRef plist;
CFDictionaryRef matching;
CFDictionaryRef pluginTypes;
CFMutableStringRef path;
LookUUIDContext context;
CFStringRef pluginName;
boolean_t matches;
kern_return_t kr = kIOReturnSuccess;
onePlugin = NULL;
pluginName = NULL;
path = NULL;
url = NULL;
do {
pluginTypes = IORegistryEntryCreateCFProperty( service, CFSTR(kIOCFPlugInTypesKey),
kCFAllocatorDefault, kNilOptions );
if( !pluginTypes )
continue;
context.key = pluginType;
context.result = 0;
CFDictionaryApplyFunction( pluginTypes, &_IOGetWithUUIDKey, &context);
pluginName = (CFStringRef) context.result;
if( !pluginName)
continue;
path = CFStringCreateMutable( kCFAllocatorDefault, 0 );
if( !path)
continue;
CFStringAppendCString(path,
"/System/Library/Extensions/",
kCFStringEncodingMacRoman);
CFStringAppend(path, pluginName);
url = CFURLCreateWithFileSystemPath(NULL, path,
kCFURLPOSIXPathStyle, TRUE);
if( !url)
continue;
onePlugin = CFPlugInCreate(NULL, url);
} while( false );
if( url)
CFRelease( url );
if( path)
CFRelease( path );
if( pluginTypes )
CFRelease( pluginTypes );
if( onePlugin
&& (bundle = CFPlugInGetBundle(onePlugin))
&& (plist = CFBundleGetInfoDictionary(bundle))
&& (matching = (CFDictionaryRef)
CFDictionaryGetValue(plist, CFSTR("Personality")))) {
kr = IOServiceMatchPropertyTable( service, matching, &matches);
if( kr != kIOReturnSuccess)
matches = FALSE;
} else
matches = TRUE;
if( matches) {
if( onePlugin)
*factories = CFPlugInFindFactoriesForPlugInTypeInPlugIn(pluginType, onePlugin);
else
*factories = 0; } else
*factories = 0;
*plists = 0;
return( kr );
}
kern_return_t
IOCreatePlugInInterfaceForService(io_service_t service,
CFUUIDRef pluginType, CFUUIDRef interfaceType,
IOCFPlugInInterface *** theInterface, SInt32 * theScore)
{
CFDictionaryRef plist = 0;
CFArrayRef plists;
CFArrayRef factories;
CFMutableArrayRef candidates;
CFMutableArrayRef scores;
CFIndex index;
CFIndex insert;
CFUUIDRef factoryID;
kern_return_t kr;
SInt32 score;
IOCFPlugInInterface ** interface;
Boolean haveOne;
kr = IOFindPlugIns( service, pluginType,
&factories, &plists );
if( KERN_SUCCESS != kr) {
if (factories) CFRelease(factories);
if (plists) CFRelease(plists);
return( kr );
}
if ((KERN_SUCCESS != kr)
|| (factories == NULL)
|| (0 == CFArrayGetCount(factories))) {
if (factories) CFRelease(factories);
if (plists) CFRelease(plists);
return( kIOReturnUnsupported );
}
candidates = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
scores = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
if (candidates && scores) {
CFIndex numfactories = CFArrayGetCount(factories);
for ( index = 0; index < numfactories; index++ ) {
IUnknownVTbl ** iunknown;
factoryID = (CFUUIDRef) CFArrayGetValueAtIndex(factories, index);
iunknown = (IUnknownVTbl **)
CFPlugInInstanceCreate(NULL, factoryID, pluginType);
if (!iunknown) {
continue;
}
(*iunknown)->QueryInterface(iunknown, CFUUIDGetUUIDBytes(interfaceType),
(LPVOID *)&interface);
(*iunknown)->Release(iunknown);
if (!interface) {
continue;
}
if (plists)
plist = (CFDictionaryRef) CFArrayGetValueAtIndex( plists, index );
score = 0; kr = (*interface)->Probe(interface, plist, service, &score);
if (kIOReturnSuccess == kr) {
CFIndex numscores = CFArrayGetCount(scores);
for (insert = 0; insert < numscores; insert++) {
if (score > ((SInt32) CFArrayGetValueAtIndex(scores, insert)))
break;
}
CFArrayInsertValueAtIndex(candidates, insert, (void *) interface);
CFArrayInsertValueAtIndex(scores, insert, (void *) score);
} else
(*interface)->Release(interface);
}
}
CFIndex candidatecount = CFArrayGetCount(candidates);
for (haveOne = false, index = 0;
index < candidatecount;
index++) {
Boolean freeIt;
if (plists)
plist = (CFDictionaryRef) CFArrayGetValueAtIndex(plists, index );
interface = (IOCFPlugInInterface **)
CFArrayGetValueAtIndex(candidates, index );
if (!haveOne) {
haveOne = (kIOReturnSuccess == (*interface)->Start(interface, plist, service));
freeIt = !haveOne;
if (haveOne) {
*theInterface = interface;
*theScore = (SInt32) CFArrayGetValueAtIndex(scores, index );
}
} else
freeIt = true;
if (freeIt)
(*interface)->Release(interface);
}
if (factories)
CFRelease(factories);
if (plists)
CFRelease(plists);
if (candidates)
CFRelease(candidates);
if (scores)
CFRelease(scores);
return (haveOne ? kIOReturnSuccess : kIOReturnNoResources);
}
kern_return_t
IODestroyPlugInInterface(IOCFPlugInInterface ** interface)
{
kern_return_t err;
err = (*interface)->Stop(interface);
(*interface)->Release(interface);
return( err );
}
kern_return_t
IOCreatePlugInInterfaces(CFUUIDRef pluginType, CFUUIDRef interfaceType);
#endif