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