1 //==============================================================================
2 //
3 //	DO NO MODIFY THE CONTENT OF THIS FILE
4 //
5 //	This file contains the generic CFPlug-in code necessary for your generator
6 //	To complete your generator implement the function in GenerateThumbnailForURL/GeneratePreviewForURL.c
7 //
8 //==============================================================================
9 
10 #include <CoreFoundation/CoreFoundation.h>
11 #include <CoreFoundation/CFPlugInCOM.h>
12 #include <CoreServices/CoreServices.h>
13 #include <QuickLook/QuickLook.h>
14 
15 // -----------------------------------------------------------------------------
16 //	constants
17 // -----------------------------------------------------------------------------
18 
19 // Don't modify this line
20 #define PLUGIN_ID "FDF02409-6B04-4738-973D-1AADB4FC34D8"
21 
22 //
23 // Below is the generic glue code for all plug-ins.
24 //
25 // You should not have to modify this code aside from changing
26 // names if you decide to change the names defined in the Info.plist
27 //
28 
29 
30 // -----------------------------------------------------------------------------
31 //	typedefs
32 // -----------------------------------------------------------------------------
33 
34 // The thumbnail generation function to be implemented in GenerateThumbnailForURL.c
35 OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize);
36 void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail);
37 
38 // The preview generation function to be implemented in GeneratePreviewForURL.c
39 OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options);
40 void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview);
41 
42 // The layout for an instance of QuickLookGeneratorPlugIn
43 typedef struct __QuickLookGeneratorPluginType
44 {
45     void        *conduitInterface;
46     CFUUIDRef    factoryID;
47     UInt32       refCount;
48 } QuickLookGeneratorPluginType;
49 
50 // -----------------------------------------------------------------------------
51 //	prototypes
52 // -----------------------------------------------------------------------------
53 //	Forward declaration for the IUnknown implementation.
54 //
55 
56 QuickLookGeneratorPluginType  *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID);
57 void                         DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance);
58 HRESULT                      QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv);
59 void                        *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID);
60 ULONG                        QuickLookGeneratorPluginAddRef(void *thisInstance);
61 ULONG                        QuickLookGeneratorPluginRelease(void *thisInstance);
62 
63 // -----------------------------------------------------------------------------
64 //	myInterfaceFtbl	definition
65 // -----------------------------------------------------------------------------
66 //	The QLGeneratorInterfaceStruct function table.
67 //
68 static QLGeneratorInterfaceStruct myInterfaceFtbl = {
69     NULL,
70     QuickLookGeneratorQueryInterface,
71     QuickLookGeneratorPluginAddRef,
72     QuickLookGeneratorPluginRelease,
73     NULL,
74     NULL,
75     NULL,
76     NULL
77 };
78 
79 
80 // -----------------------------------------------------------------------------
81 //	AllocQuickLookGeneratorPluginType
82 // -----------------------------------------------------------------------------
83 //	Utility function that allocates a new instance.
84 //      You can do some initial setup for the generator here if you wish
85 //      like allocating globals etc...
86 //
AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID)87 QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID)
88 {
89     QuickLookGeneratorPluginType *theNewInstance;
90 
91     theNewInstance = (QuickLookGeneratorPluginType *)malloc(sizeof(QuickLookGeneratorPluginType));
92     memset(theNewInstance,0,sizeof(QuickLookGeneratorPluginType));
93 
94     /* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */
95     theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct));
96     memcpy(theNewInstance->conduitInterface,&myInterfaceFtbl,sizeof(QLGeneratorInterfaceStruct));
97 
98     /*  Retain and keep an open instance refcount for each factory. */
99     theNewInstance->factoryID = CFRetain(inFactoryID);
100     CFPlugInAddInstanceForFactory(inFactoryID);
101 
102     /* This function returns the IUnknown interface so set the refCount to one. */
103     theNewInstance->refCount = 1;
104     return theNewInstance;
105 }
106 
107 // -----------------------------------------------------------------------------
108 //	DeallocQuickLookGeneratorPluginType
109 // -----------------------------------------------------------------------------
110 //	Utility function that deallocates the instance when
111 //	the refCount goes to zero.
112 //      In the current implementation generator interfaces are never deallocated
113 //      but implement this as this might change in the future
114 //
DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType * thisInstance)115 void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance)
116 {
117     CFUUIDRef theFactoryID;
118 
119     theFactoryID = thisInstance->factoryID;
120     /* Free the conduitInterface table up */
121     free(thisInstance->conduitInterface);
122 
123     /* Free the instance structure */
124     free(thisInstance);
125     if (theFactoryID){
126         CFPlugInRemoveInstanceForFactory(theFactoryID);
127         CFRelease(theFactoryID);
128     }
129 }
130 
131 // -----------------------------------------------------------------------------
132 //	QuickLookGeneratorQueryInterface
133 // -----------------------------------------------------------------------------
134 //	Implementation of the IUnknown QueryInterface function.
135 //
QuickLookGeneratorQueryInterface(void * thisInstance,REFIID iid,LPVOID * ppv)136 HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv)
137 {
138     CFUUIDRef interfaceID;
139 
140     interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid);
141 
142     if (CFEqual(interfaceID,kQLGeneratorCallbacksInterfaceID)){
143         /* If the Right interface was requested, bump the ref count,
144          * set the ppv parameter equal to the instance, and
145          * return good status.
146          */
147         ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL;
148         ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration;
149         ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL;
150         ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration;
151         ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance);
152         *ppv = thisInstance;
153         CFRelease(interfaceID);
154         return S_OK;
155     }else{
156         /* Requested interface unknown, bail with error. */
157         *ppv = NULL;
158         CFRelease(interfaceID);
159         return E_NOINTERFACE;
160     }
161 }
162 
163 // -----------------------------------------------------------------------------
164 // QuickLookGeneratorPluginAddRef
165 // -----------------------------------------------------------------------------
166 //	Implementation of reference counting for this type. Whenever an interface
167 //	is requested, bump the refCount for the instance. NOTE: returning the
168 //	refcount is a convention but is not required so don't rely on it.
169 //
QuickLookGeneratorPluginAddRef(void * thisInstance)170 ULONG QuickLookGeneratorPluginAddRef(void *thisInstance)
171 {
172     ((QuickLookGeneratorPluginType *)thisInstance )->refCount += 1;
173     return ((QuickLookGeneratorPluginType*) thisInstance)->refCount;
174 }
175 
176 // -----------------------------------------------------------------------------
177 // QuickLookGeneratorPluginRelease
178 // -----------------------------------------------------------------------------
179 //	When an interface is released, decrement the refCount.
180 //	If the refCount goes to zero, deallocate the instance.
181 //
QuickLookGeneratorPluginRelease(void * thisInstance)182 ULONG QuickLookGeneratorPluginRelease(void *thisInstance)
183 {
184     ((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1;
185     if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0){
186         DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance );
187         return 0;
188     }else{
189         return ((QuickLookGeneratorPluginType*) thisInstance )->refCount;
190     }
191 }
192 
193 // -----------------------------------------------------------------------------
194 //  QuickLookGeneratorPluginFactory
195 // -----------------------------------------------------------------------------
QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID)196 void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID)
197 {
198     QuickLookGeneratorPluginType *result;
199     CFUUIDRef                 uuid;
200 
201     /* If correct type is being requested, allocate an
202      * instance of kQLGeneratorTypeID and return the IUnknown interface.
203      */
204     if (CFEqual(typeID,kQLGeneratorTypeID)){
205         uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID));
206         result = AllocQuickLookGeneratorPluginType(uuid);
207         CFRelease(uuid);
208         return result;
209     }
210     /* If the requested type is incorrect, return NULL. */
211     return NULL;
212 }
213 
214