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