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