1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                        X   X  TTTTT  RRRR   N   N                           %
7 %                         X X     T    R   R  NN  N                           %
8 %                          X      T    RRRR   N N N                           %
9 %                         X X     T    R R    N  NN                           %
10 %                        X   X    T    R  R   N   N                           %
11 %                                                                             %
12 %                                                                             %
13 %                    ImageMagickObject BLOB Interface.                        %
14 %                                                                             %
15 %                              Software Design                                %
16 %                             William Radcliffe                               %
17 %                                 May 2001                                    %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://imagemagick.org/script/license.php                               %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %  This coder is a kind of backdoor used by the COM object that allows it to  %
38 %  pass blobs back and forth using the coder interface. It simply encodes and %
39 %  decodes the filename as a comma delimited string and extracts the info it  %
40 %  needs.                                                                     %
41 %
42 %
43 */
44 
45 /*
46   Include declarations.
47 */
48 #include "MagickCore/studio.h"
49 #include "MagickCore/blob.h"
50 #include "MagickCore/blob-private.h"
51 #include "MagickCore/constitute.h"
52 #include "MagickCore/delegate.h"
53 #include "MagickCore/exception.h"
54 #include "MagickCore/exception-private.h"
55 #include "MagickCore/image.h"
56 #include "MagickCore/image-private.h"
57 #include "MagickCore/list.h"
58 #include "MagickCore/magick.h"
59 #include "MagickCore/magick-private.h"
60 #include "MagickCore/memory_.h"
61 #include "MagickCore/module.h"
62 #include "MagickCore/static.h"
63 #include "MagickCore/string_.h"
64 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__)
65 #define WIN32_LEAN_AND_MEAN
66 #define VC_EXTRALEAN
67 #include <windows.h>
68 #include <ole2.h>
69 
70 /*
71   Forward declarations.
72 */
73 static MagickBooleanType
74   WriteXTRNImage(const ImageInfo *,Image *,ExceptionInfo *exception);
75 #endif
76 
77 /*
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 %                                                                             %
80 %                                                                             %
81 %                                                                             %
82 %   R e a d X T R N I m a g e                                                 %
83 %                                                                             %
84 %                                                                             %
85 %                                                                             %
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 %
88 %  ReadXTRNImage() reads a XTRN image file and returns it.  It
89 %  allocates the memory necessary for the new Image structure and returns a
90 %  pointer to the new image.
91 %
92 %  The format of the ReadXTRNImage method is:
93 %
94 %      Image *ReadXTRNImage(const ImageInfo *image_info,
95 %        ExceptionInfo *exception)
96 %
97 %  A description of each parameter follows:
98 %
99 %    o image_info: Specifies a pointer to an ImageInfo structure.
100 %
101 %    o exception: return any errors or warnings in this structure.
102 %
103 */
104 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__)
ReadXTRNImage(const ImageInfo * image_info,ExceptionInfo * exception)105 static Image *ReadXTRNImage(const ImageInfo *image_info,
106   ExceptionInfo *exception)
107 {
108   char
109     *blob_data,
110     filename[MagickPathExtent];
111 
112   HRESULT
113     hr;
114 
115   Image
116     *image;
117 
118   ImageInfo
119     *clone_info;
120 
121   long
122     lBoundl,
123     lBoundu;
124 
125   SAFEARRAY
126     *pSafeArray;
127 
128   size_t
129     blob_length;
130 
131   void
132     *param1;
133 
134   param1=(void *) NULL;
135   image=(Image *) NULL;
136   clone_info=CloneImageInfo(image_info);
137   if (clone_info->filename == NULL)
138     {
139       clone_info=DestroyImageInfo(clone_info);
140       ThrowReaderException(FileOpenWarning,"No filename specified");
141     }
142   *filename='\0';
143   (void) sscanf(clone_info->filename,"%p,%2048s",&param1,filename);
144   hr=S_OK;
145   pSafeArray=(SAFEARRAY *) param1;
146   if (pSafeArray)
147     {
148       hr=SafeArrayGetLBound(pSafeArray,1,&lBoundl);
149       if (SUCCEEDED(hr))
150         {
151           hr=SafeArrayGetUBound(pSafeArray,1,&lBoundu);
152           if (SUCCEEDED(hr))
153             {
154               blob_length=lBoundu-lBoundl+1;
155               hr=SafeArrayAccessData(pSafeArray,(void**) &blob_data);
156               if (SUCCEEDED(hr))
157                 {
158                   *clone_info->filename='\0';
159                   *clone_info->magick='\0';
160                   if (*filename != '\0')
161                     (void) CopyMagickString(clone_info->filename,filename,
162                       MagickPathExtent);
163                   image=BlobToImage(clone_info,blob_data,blob_length,
164                     exception);
165                   hr=SafeArrayUnaccessData(pSafeArray);
166                   CatchException(exception);
167                 }
168             }
169         }
170     }
171   clone_info=DestroyImageInfo(clone_info);
172   return(image);
173 }
174 #endif
175 
176 /*
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 %                                                                             %
179 %                                                                             %
180 %                                                                             %
181 %   R e g i s t e r X T R N I m a g e                                         %
182 %                                                                             %
183 %                                                                             %
184 %                                                                             %
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186 %
187 %  RegisterXTRNImage() adds attributes for the XTRN image format to
188 %  the list of supported formats.  The attributes include the image format
189 %  tag, a method to read and/or write the format, whether the format
190 %  supports the saving of more than one frame to the same file or blob,
191 %  whether the format supports native in-memory I/O, and a brief
192 %  description of the format.
193 %
194 %  The format of the RegisterXTRNImage method is:
195 %
196 %      size_t RegisterXTRNImage(void)
197 %
198 */
RegisterXTRNImage(void)199 ModuleExport size_t RegisterXTRNImage(void)
200 {
201   MagickInfo
202     *entry;
203 
204   entry=AcquireMagickInfo("XTRN","XTRNARRAY",
205     "External transfer via a smart array interface");
206 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__)
207   entry->decoder=ReadXTRNImage;
208   entry->encoder=WriteXTRNImage;
209 #endif
210   entry->flags^=CoderAdjoinFlag;
211   entry->flags|=CoderStealthFlag;
212   RegisterMagickInfo(entry);
213   return(MagickImageCoderSignature);
214 }
215 
216 /*
217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218 %                                                                             %
219 %                                                                             %
220 %                                                                             %
221 %   U n r e g i s t e r X T R N I m a g e                                     %
222 %                                                                             %
223 %                                                                             %
224 %                                                                             %
225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226 %
227 %  UnregisterXTRNImage() removes format registrations made by the
228 %  XTRN module from the list of supported formats.
229 %
230 %  The format of the UnregisterXTRNImage method is:
231 %
232 %      UnregisterXTRNImage(void)
233 %
234 */
UnregisterXTRNImage(void)235 ModuleExport void UnregisterXTRNImage(void)
236 {
237   UnregisterMagickInfo("XTRNARRAY");
238 }
239 
240 /*
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %   W r i t e X T R N I m a g e                                               %
246 %                                                                             %
247 %                                                                             %
248 %                                                                             %
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 %
251 %  WriteXTRNImage() writes an image in the XTRN encoded image format.
252 %  We use GIF because it is the only format that is compressed without
253 %  requiring additional optional delegates (TIFF, ZIP, etc).
254 %
255 %  The format of the WriteXTRNImage method is:
256 %
257 %      MagickBooleanType WriteXTRNImage(const ImageInfo *image_info,
258 %        Image *image,ExceptionInfo *exception)
259 %
260 %  A description of each parameter follows.
261 %
262 %    o image_info: Specifies a pointer to an ImageInfo structure.
263 %
264 %    o image:  A pointer to a Image structure.
265 %
266 %    o exception: return any errors or warnings in this structure.
267 %
268 */
269 
270 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__)
SafeArrayFifo(const Image * image,const void * data,const size_t length)271 static size_t SafeArrayFifo(const Image *image,const void *data,
272   const size_t length)
273 {
274   SAFEARRAYBOUND NewArrayBounds[1];  /* 1 Dimension */
275   size_t tlen=length;
276   SAFEARRAY *pSafeArray = (SAFEARRAY *)image->client_data;
277   if (pSafeArray != NULL)
278   {
279     long lBoundl, lBoundu, lCount;
280     HRESULT hr = S_OK;
281     /* First see how big the buffer currently is */
282     hr = SafeArrayGetLBound(pSafeArray, 1, &lBoundl);
283     if (FAILED(hr))
284       return MagickFalse;
285     hr = SafeArrayGetUBound(pSafeArray, 1, &lBoundu);
286     if (FAILED(hr))
287       return MagickFalse;
288     lCount = lBoundu - lBoundl + 1;
289 
290     if (length>0)
291     {
292       unsigned char       *pReturnBuffer = NULL;
293       NewArrayBounds[0].lLbound = 0;   /* Start-Index 0 */
294       NewArrayBounds[0].cElements = (unsigned long) (length+lCount);  /* # Elemente */
295       hr = SafeArrayRedim(pSafeArray, NewArrayBounds);
296       if (FAILED(hr))
297         return 0;
298       hr = SafeArrayAccessData(pSafeArray, (void**)&pReturnBuffer);
299       if( FAILED(hr) )
300         return 0;
301       (void) memcpy(pReturnBuffer+lCount,(unsigned char *) data,length);
302       hr=SafeArrayUnaccessData(pSafeArray);
303       if(FAILED(hr))
304         return 0;
305     }
306     else
307     {
308       /* Adjust the length of the buffer to fit */
309     }
310   }
311   return(tlen);
312 }
313 
WriteXTRNImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)314 static MagickBooleanType WriteXTRNImage(const ImageInfo *image_info,
315   Image *image,ExceptionInfo *exception)
316 {
317   char
318     filename[MagickPathExtent];
319 
320   Image
321     *p;
322 
323   ImageInfo
324     *clone_info;
325 
326   int
327     scene;
328 
329   MagickBooleanType
330     status;
331 
332   size_t
333     blob_length;
334 
335   unsigned char
336     *blob_data;
337 
338   void
339     *param1;
340 
341   param1 = (void *) NULL;
342   status=MagickTrue;
343   clone_info=CloneImageInfo(image_info);
344   if (*clone_info->filename != '\0')
345     {
346       (void) sscanf(clone_info->filename,"%p,%2048s",&param1,filename);
347       image->client_data=param1;
348       scene=0;
349       (void) CopyMagickString(clone_info->filename,filename,
350         MagickPathExtent);
351       for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
352       {
353         (void) CopyMagickString(p->filename,filename,MagickPathExtent);
354         p->scene=scene++;
355       }
356       SetImageInfo(clone_info,1,exception);
357       (void) CopyMagickString(image->magick,clone_info->magick,
358         MagickPathExtent);
359       blob_data=ImageToBlob(clone_info,image,&blob_length,
360         exception);
361       if (blob_data == (unsigned char *) NULL)
362         status=MagickFalse;
363       else
364         SafeArrayFifo(image,blob_data,blob_length);
365       if (status == MagickFalse)
366         CatchImageException(image);
367     }
368   clone_info=DestroyImageInfo(clone_info);
369   return(MagickTrue);
370 }
371 #endif
372