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))) { // printf("No factories for type\n"); if (factories) CFRelease(factories); if (plists) CFRelease(plists); return( kIOReturnUnsupported ); } candidates = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); scores = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); // allocate and Probe all 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) { // printf("Failed to create instance (link error?)\n"); continue; } (*iunknown)->QueryInterface(iunknown, CFUUIDGetUUIDBytes(interfaceType), (LPVOID *)&interface); // Now we are done with IUnknown interface (*iunknown)->Release(iunknown); if (!interface) { // printf("Failed to get interface.\n"); continue; } if (plists) plist = (CFDictionaryRef) CFArrayGetValueAtIndex( plists, index ); score = 0; // from property table kr = (*interface)->Probe(interface, plist, service, &score); if (kIOReturnSuccess == kr) { CFIndex numscores = CFArrayGetCount(scores); for (insert = 0; insert < numscores; insert++) { if (score > (SInt32) ((intptr_t) CFArrayGetValueAtIndex(scores, insert))) break; } CFArrayInsertValueAtIndex(candidates, insert, (void *) interface); CFArrayInsertValueAtIndex(scores, insert, (void *) (intptr_t) score); } else (*interface)->Release(interface); } } // Start in score order 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) (intptr_t) 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); // CFRelease(plugin); return (haveOne ? kIOReturnSuccess : kIOReturnNoResources); }
static CFPlugInRef MyLoadPlugIn( void ) { CFPlugInRef newPlugIn; CFURLRef bundleURL; CFURLRef plugInURL; Boolean foundInterface = false; // Obtain a URL to the PlugIns directory inside our application. bundleURL = CFBundleCopyBuiltInPlugInsURL( CFBundleGetMainBundle() ); // We just want to load our test plug-in, so append its name to the URL. plugInURL = CFURLCreateCopyAppendingPathComponent( NULL, bundleURL, CFSTR( kPlugInName ), FALSE ); // Create a CFPlugin using the URL. This step causes the plug-in's types and factories to // be registered with the system. Note that the plug-in's code is not actually loaded at // this stage unless the plug-in is using dynamic registration. newPlugIn = CFPlugInCreate( NULL, plugInURL ); CFRelease( bundleURL ); CFRelease( plugInURL ); // The plug-in was located. Now locate the interface. if( newPlugIn ) { CFArrayRef factories; // See if this plug-in implements the Test type. factories = CFPlugInFindFactoriesForPlugInTypeInPlugIn( kTestTypeID, newPlugIn ); // If there are factories for the Test type, attempt to get the IUnknown interface. if ( factories != NULL ) { CFIndex factoryCount; CFIndex index; factoryCount = CFArrayGetCount( factories ); if ( factoryCount > 0 ) { for ( index = 0 ; (index < factoryCount) && (foundInterface == false) ; index++ ) { CFUUIDRef factoryID; // Get the factory ID for the first location in the array of IDs. factoryID = (CFUUIDRef) CFArrayGetValueAtIndex( factories, index ); if ( factoryID ) { IUnknownVTbl **iunknown; // Use the factory ID to get an IUnknown interface. Here the plug-in code is loaded. iunknown = (IUnknownVTbl **) CFPlugInInstanceCreate( NULL, factoryID, kTestTypeID ); if ( iunknown ) { // If this is an IUnknown interface, query for the test interface. (*iunknown)->QueryInterface( iunknown, CFUUIDGetUUIDBytes( kTestInterfaceID ), (LPVOID *)( &gDrawBallInterface ) ); // Now we are done with IUnknown (*iunknown)->Release( iunknown ); if ( gDrawBallInterface ) { // We found the interface we need foundInterface = true; } } } } } } CFRelease( factories ); } if ( foundInterface == false ) { CFRelease( newPlugIn ); newPlugIn = NULL; } return( newPlugIn ); }