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