1*b1cdbd2cSJim Jagielski/************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski// 23*b1cdbd2cSJim Jagielski// main.c 24*b1cdbd2cSJim Jagielski// SpotlightTester 25*b1cdbd2cSJim Jagielski// 26*b1cdbd2cSJim Jagielski// Created by Florian Heckl on 10.07.07. 27*b1cdbd2cSJim Jagielski// 28*b1cdbd2cSJim Jagielski//============================================================================== 29*b1cdbd2cSJim Jagielski// 30*b1cdbd2cSJim Jagielski// DO NO MODIFY THE CONTENT OF THIS FILE 31*b1cdbd2cSJim Jagielski// 32*b1cdbd2cSJim Jagielski// This file contains the generic CFPlug-in code necessary for your importer 33*b1cdbd2cSJim Jagielski// To complete your importer implement the function in GetMetadataForFile.c 34*b1cdbd2cSJim Jagielski// 35*b1cdbd2cSJim Jagielski//============================================================================== 36*b1cdbd2cSJim Jagielski 37*b1cdbd2cSJim Jagielski 38*b1cdbd2cSJim Jagielski 39*b1cdbd2cSJim Jagielski 40*b1cdbd2cSJim Jagielski 41*b1cdbd2cSJim Jagielski 42*b1cdbd2cSJim Jagielski#include <CoreFoundation/CoreFoundation.h> 43*b1cdbd2cSJim Jagielski#include <CoreFoundation/CFPlugInCOM.h> 44*b1cdbd2cSJim Jagielski#include <CoreServices/CoreServices.h> 45*b1cdbd2cSJim Jagielski 46*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 47*b1cdbd2cSJim Jagielski// constants 48*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 49*b1cdbd2cSJim Jagielski 50*b1cdbd2cSJim Jagielski 51*b1cdbd2cSJim Jagielski#define PLUGIN_ID "A3FCC88D-B9A6-4364-8B93-92123C8A2D18" 52*b1cdbd2cSJim Jagielski 53*b1cdbd2cSJim Jagielski// 54*b1cdbd2cSJim Jagielski// Below is the generic glue code for all plug-ins. 55*b1cdbd2cSJim Jagielski// 56*b1cdbd2cSJim Jagielski// You should not have to modify this code aside from changing 57*b1cdbd2cSJim Jagielski// names if you decide to change the names defined in the Info.plist 58*b1cdbd2cSJim Jagielski// 59*b1cdbd2cSJim Jagielski 60*b1cdbd2cSJim Jagielski 61*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 62*b1cdbd2cSJim Jagielski// typedefs 63*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 64*b1cdbd2cSJim Jagielski 65*b1cdbd2cSJim Jagielski// The import function to be implemented in GetMetadataForFile.c 66*b1cdbd2cSJim JagielskiBoolean GetMetadataForFile(void *thisInterface, 67*b1cdbd2cSJim Jagielski CFMutableDictionaryRef attributes, 68*b1cdbd2cSJim Jagielski CFStringRef contentTypeUTI, 69*b1cdbd2cSJim Jagielski CFStringRef pathToFile); 70*b1cdbd2cSJim Jagielski 71*b1cdbd2cSJim Jagielski// The layout for an instance of MetaDataImporterPlugIn 72*b1cdbd2cSJim Jagielskitypedef struct __MetadataImporterPluginType 73*b1cdbd2cSJim Jagielski{ 74*b1cdbd2cSJim Jagielski MDImporterInterfaceStruct *conduitInterface; 75*b1cdbd2cSJim Jagielski CFUUIDRef factoryID; 76*b1cdbd2cSJim Jagielski UInt32 refCount; 77*b1cdbd2cSJim Jagielski} MetadataImporterPluginType; 78*b1cdbd2cSJim Jagielski 79*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 80*b1cdbd2cSJim Jagielski// prototypes 81*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 82*b1cdbd2cSJim Jagielski// Forward declaration for the IUnknown implementation. 83*b1cdbd2cSJim Jagielski// 84*b1cdbd2cSJim Jagielski 85*b1cdbd2cSJim JagielskiMetadataImporterPluginType *AllocMetadataImporterPluginType(CFUUIDRef inFactoryID); 86*b1cdbd2cSJim Jagielskivoid DeallocMetadataImporterPluginType(MetadataImporterPluginType *thisInstance); 87*b1cdbd2cSJim JagielskiHRESULT MetadataImporterQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv); 88*b1cdbd2cSJim Jagielskivoid *MetadataImporterPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID); 89*b1cdbd2cSJim JagielskiULONG MetadataImporterPluginAddRef(void *thisInstance); 90*b1cdbd2cSJim JagielskiULONG MetadataImporterPluginRelease(void *thisInstance); 91*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 92*b1cdbd2cSJim Jagielski// testInterfaceFtbl definition 93*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 94*b1cdbd2cSJim Jagielski// The TestInterface function table. 95*b1cdbd2cSJim Jagielski// 96*b1cdbd2cSJim Jagielski 97*b1cdbd2cSJim Jagielskistatic MDImporterInterfaceStruct testInterfaceFtbl = { 98*b1cdbd2cSJim Jagielski NULL, 99*b1cdbd2cSJim Jagielski MetadataImporterQueryInterface, 100*b1cdbd2cSJim Jagielski MetadataImporterPluginAddRef, 101*b1cdbd2cSJim Jagielski MetadataImporterPluginRelease, 102*b1cdbd2cSJim Jagielski GetMetadataForFile 103*b1cdbd2cSJim Jagielski}; 104*b1cdbd2cSJim Jagielski 105*b1cdbd2cSJim Jagielski 106*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 107*b1cdbd2cSJim Jagielski// AllocMetadataImporterPluginType 108*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 109*b1cdbd2cSJim Jagielski// Utility function that allocates a new instance. 110*b1cdbd2cSJim Jagielski// You can do some initial setup for the importer here if you wish 111*b1cdbd2cSJim Jagielski// like allocating globals etc... 112*b1cdbd2cSJim Jagielski// 113*b1cdbd2cSJim JagielskiMetadataImporterPluginType *AllocMetadataImporterPluginType(CFUUIDRef inFactoryID) 114*b1cdbd2cSJim Jagielski{ 115*b1cdbd2cSJim Jagielski MetadataImporterPluginType *theNewInstance; 116*b1cdbd2cSJim Jagielski 117*b1cdbd2cSJim Jagielski theNewInstance = (MetadataImporterPluginType *)malloc(sizeof(MetadataImporterPluginType)); 118*b1cdbd2cSJim Jagielski memset(theNewInstance,0,sizeof(MetadataImporterPluginType)); 119*b1cdbd2cSJim Jagielski 120*b1cdbd2cSJim Jagielski /* Point to the function table */ 121*b1cdbd2cSJim Jagielski theNewInstance->conduitInterface = &testInterfaceFtbl; 122*b1cdbd2cSJim Jagielski 123*b1cdbd2cSJim Jagielski /* Retain and keep an open instance refcount for each factory. */ 124*b1cdbd2cSJim Jagielski theNewInstance->factoryID = CFRetain(inFactoryID); 125*b1cdbd2cSJim Jagielski CFPlugInAddInstanceForFactory(inFactoryID); 126*b1cdbd2cSJim Jagielski 127*b1cdbd2cSJim Jagielski /* This function returns the IUnknown interface so set the refCount to one. */ 128*b1cdbd2cSJim Jagielski theNewInstance->refCount = 1; 129*b1cdbd2cSJim Jagielski return theNewInstance; 130*b1cdbd2cSJim Jagielski} 131*b1cdbd2cSJim Jagielski 132*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 133*b1cdbd2cSJim Jagielski// DeallocSpotlightTesterMDImporterPluginType 134*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 135*b1cdbd2cSJim Jagielski// Utility function that deallocates the instance when 136*b1cdbd2cSJim Jagielski// the refCount goes to zero. 137*b1cdbd2cSJim Jagielski// In the current implementation importer interfaces are never deallocated 138*b1cdbd2cSJim Jagielski// but implement this as this might change in the future 139*b1cdbd2cSJim Jagielski// 140*b1cdbd2cSJim Jagielskivoid DeallocMetadataImporterPluginType(MetadataImporterPluginType *thisInstance) 141*b1cdbd2cSJim Jagielski{ 142*b1cdbd2cSJim Jagielski CFUUIDRef theFactoryID; 143*b1cdbd2cSJim Jagielski 144*b1cdbd2cSJim Jagielski theFactoryID = thisInstance->factoryID; 145*b1cdbd2cSJim Jagielski free(thisInstance); 146*b1cdbd2cSJim Jagielski if (theFactoryID){ 147*b1cdbd2cSJim Jagielski CFPlugInRemoveInstanceForFactory(theFactoryID); 148*b1cdbd2cSJim Jagielski CFRelease(theFactoryID); 149*b1cdbd2cSJim Jagielski } 150*b1cdbd2cSJim Jagielski} 151*b1cdbd2cSJim Jagielski 152*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 153*b1cdbd2cSJim Jagielski// MetadataImporterQueryInterface 154*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 155*b1cdbd2cSJim Jagielski// Implementation of the IUnknown QueryInterface function. 156*b1cdbd2cSJim Jagielski// 157*b1cdbd2cSJim JagielskiHRESULT MetadataImporterQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv) 158*b1cdbd2cSJim Jagielski{ 159*b1cdbd2cSJim Jagielski CFUUIDRef interfaceID; 160*b1cdbd2cSJim Jagielski 161*b1cdbd2cSJim Jagielski interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid); 162*b1cdbd2cSJim Jagielski 163*b1cdbd2cSJim Jagielski if (CFEqual(interfaceID,kMDImporterInterfaceID)){ 164*b1cdbd2cSJim Jagielski /* If the Right interface was requested, bump the ref count, 165*b1cdbd2cSJim Jagielski * set the ppv parameter equal to the instance, and 166*b1cdbd2cSJim Jagielski * return good status. 167*b1cdbd2cSJim Jagielski */ 168*b1cdbd2cSJim Jagielski ((MetadataImporterPluginType*)thisInstance)->conduitInterface->AddRef(thisInstance); 169*b1cdbd2cSJim Jagielski *ppv = thisInstance; 170*b1cdbd2cSJim Jagielski CFRelease(interfaceID); 171*b1cdbd2cSJim Jagielski return S_OK; 172*b1cdbd2cSJim Jagielski }else{ 173*b1cdbd2cSJim Jagielski if (CFEqual(interfaceID,IUnknownUUID)){ 174*b1cdbd2cSJim Jagielski /* If the IUnknown interface was requested, same as above. */ 175*b1cdbd2cSJim Jagielski ((MetadataImporterPluginType*)thisInstance )->conduitInterface->AddRef(thisInstance); 176*b1cdbd2cSJim Jagielski *ppv = thisInstance; 177*b1cdbd2cSJim Jagielski CFRelease(interfaceID); 178*b1cdbd2cSJim Jagielski return S_OK; 179*b1cdbd2cSJim Jagielski }else{ 180*b1cdbd2cSJim Jagielski /* Requested interface unknown, bail with error. */ 181*b1cdbd2cSJim Jagielski *ppv = NULL; 182*b1cdbd2cSJim Jagielski CFRelease(interfaceID); 183*b1cdbd2cSJim Jagielski return E_NOINTERFACE; 184*b1cdbd2cSJim Jagielski } 185*b1cdbd2cSJim Jagielski } 186*b1cdbd2cSJim Jagielski} 187*b1cdbd2cSJim Jagielski 188*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 189*b1cdbd2cSJim Jagielski// MetadataImporterPluginAddRef 190*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 191*b1cdbd2cSJim Jagielski// Implementation of reference counting for this type. Whenever an interface 192*b1cdbd2cSJim Jagielski// is requested, bump the refCount for the instance. NOTE: returning the 193*b1cdbd2cSJim Jagielski// refcount is a convention but is not required so don't rely on it. 194*b1cdbd2cSJim Jagielski// 195*b1cdbd2cSJim JagielskiULONG MetadataImporterPluginAddRef(void *thisInstance) 196*b1cdbd2cSJim Jagielski{ 197*b1cdbd2cSJim Jagielski ((MetadataImporterPluginType *)thisInstance )->refCount += 1; 198*b1cdbd2cSJim Jagielski return ((MetadataImporterPluginType*) thisInstance)->refCount; 199*b1cdbd2cSJim Jagielski} 200*b1cdbd2cSJim Jagielski 201*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 202*b1cdbd2cSJim Jagielski// SampleCMPluginRelease 203*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 204*b1cdbd2cSJim Jagielski// When an interface is released, decrement the refCount. 205*b1cdbd2cSJim Jagielski// If the refCount goes to zero, deallocate the instance. 206*b1cdbd2cSJim Jagielski// 207*b1cdbd2cSJim JagielskiULONG MetadataImporterPluginRelease(void *thisInstance) 208*b1cdbd2cSJim Jagielski{ 209*b1cdbd2cSJim Jagielski ((MetadataImporterPluginType*)thisInstance)->refCount -= 1; 210*b1cdbd2cSJim Jagielski if (((MetadataImporterPluginType*)thisInstance)->refCount == 0){ 211*b1cdbd2cSJim Jagielski DeallocMetadataImporterPluginType((MetadataImporterPluginType*)thisInstance ); 212*b1cdbd2cSJim Jagielski return 0; 213*b1cdbd2cSJim Jagielski }else{ 214*b1cdbd2cSJim Jagielski return ((MetadataImporterPluginType*) thisInstance )->refCount; 215*b1cdbd2cSJim Jagielski } 216*b1cdbd2cSJim Jagielski} 217*b1cdbd2cSJim Jagielski 218*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 219*b1cdbd2cSJim Jagielski// SpotlightTesterMDImporterPluginFactory 220*b1cdbd2cSJim Jagielski// ----------------------------------------------------------------------------- 221*b1cdbd2cSJim Jagielski// Implementation of the factory function for this type. 222*b1cdbd2cSJim Jagielski// 223*b1cdbd2cSJim Jagielskivoid *MetadataImporterPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID) 224*b1cdbd2cSJim Jagielski{ 225*b1cdbd2cSJim Jagielski MetadataImporterPluginType *result; 226*b1cdbd2cSJim Jagielski CFUUIDRef uuid; 227*b1cdbd2cSJim Jagielski 228*b1cdbd2cSJim Jagielski /* If correct type is being requested, allocate an 229*b1cdbd2cSJim Jagielski * instance of TestType and return the IUnknown interface. 230*b1cdbd2cSJim Jagielski */ 231*b1cdbd2cSJim Jagielski if (CFEqual(typeID,kMDImporterTypeID)){ 232*b1cdbd2cSJim Jagielski uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID)); 233*b1cdbd2cSJim Jagielski result = AllocMetadataImporterPluginType(uuid); 234*b1cdbd2cSJim Jagielski CFRelease(uuid); 235*b1cdbd2cSJim Jagielski return result; 236*b1cdbd2cSJim Jagielski } 237*b1cdbd2cSJim Jagielski /* If the requested type is incorrect, return NULL. */ 238*b1cdbd2cSJim Jagielski return NULL; 239*b1cdbd2cSJim Jagielski} 240*b1cdbd2cSJim Jagielski 241