• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2016 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 %    http://www.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. The five methods of passing images are:                             %
41 %                                                                             %
42 %     FILE   - same thing as filename so it should be a NOP                   %
43 %     IMAGE  - passes an image and image info structure                       %
44 %     BLOB   - passes binary blob containining the image                      %
45 %     STREAM - passes pointers to stream hooks in and does the hooking        %
46 %     ARRAY  - passes a pointer to a Win32 smart array and streams to it      %
47 %                                                                             %
48 %  Of all of these, the only one getting any real use at the moment is the    %
49 %  ARRAY handler. It is the primary way that images are shuttled back and     %
50 %  forth as blobs via COM since this is what VB and VBSCRIPT use internally   %
51 %  for this purpose.                                                          %
52 %
53 %
54 */
55 
56 /*
57   Include declarations.
58 */
59 #include "MagickCore/studio.h"
60 #include "MagickCore/blob.h"
61 #include "MagickCore/blob-private.h"
62 #include "MagickCore/constitute.h"
63 #include "MagickCore/delegate.h"
64 #include "MagickCore/exception.h"
65 #include "MagickCore/exception-private.h"
66 #include "MagickCore/image.h"
67 #include "MagickCore/image-private.h"
68 #include "MagickCore/list.h"
69 #include "MagickCore/MagickCore.h"
70 #include "MagickCore/memory_.h"
71 #include "MagickCore/string_.h"
72 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
73 #define WIN32_LEAN_AND_MEAN
74 #define VC_EXTRALEAN
75 #include <windows.h>
76 #include <ole2.h>
77 
78 /*
79   Forward declarations.
80 */
81 static MagickBooleanType
82   WriteXTRNImage(const ImageInfo *,Image *,ExceptionInfo *exception);
83 #endif
84 
85 /*
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 %                                                                             %
88 %                                                                             %
89 %                                                                             %
90 %   R e a d X T R N I m a g e                                                 %
91 %                                                                             %
92 %                                                                             %
93 %                                                                             %
94 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95 %
96 %  ReadXTRNImage() reads a XTRN image file and returns it.  It
97 %  allocates the memory necessary for the new Image structure and returns a
98 %  pointer to the new image.
99 %
100 %  The format of the ReadXTRNImage method is:
101 %
102 %      Image *ReadXTRNImage(const ImageInfo *image_info,
103 %        ExceptionInfo *exception)
104 %
105 %  A description of each parameter follows:
106 %
107 %    o image_info: Specifies a pointer to an ImageInfo structure.
108 %
109 %    o exception: return any errors or warnings in this structure.
110 %
111 */
112 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
113 #  pragma warning(disable : 4477)
ReadXTRNImage(const ImageInfo * image_info,ExceptionInfo * exception)114 static Image *ReadXTRNImage(const ImageInfo *image_info,
115   ExceptionInfo *exception)
116 {
117   Image
118     *image;
119 
120   ImageInfo
121     *clone_info;
122 
123   void
124     *param1,
125     *param2,
126     *param3;
127 
128   param1 = param2 = param3 = (void *) NULL;
129   image = (Image *) NULL;
130   clone_info=CloneImageInfo(image_info);
131   if (clone_info->filename == NULL)
132     {
133       clone_info=DestroyImageInfo(clone_info);
134       ThrowReaderException(FileOpenWarning,"No filename specified");
135     }
136   if (LocaleCompare(image_info->magick,"XTRNFILE") == 0)
137     {
138       image=ReadImage(clone_info,exception);
139       CatchException(exception);
140     }
141   else if (LocaleCompare(image_info->magick,"XTRNIMAGE") == 0)
142     {
143       Image
144         **image_ptr;
145 
146 #ifdef ALL_IMAGEINFO
147       ImageInfo
148         **image_info_ptr;
149 #endif
150 
151       (void) sscanf(clone_info->filename,"%lx,%lx",&param1,&param2);
152       image_ptr=(Image **) param2;
153       if (*image_ptr != (Image *) NULL)
154         image=CloneImage(*image_ptr,0,0,MagickFalse,exception);
155 #ifdef ALL_IMAGEINFO
156       image_info_ptr=(ImageInfo **) param1;
157       if (*image_info_ptr != (ImageInfo *) NULL)
158         image_info=*image_info_ptr;
159 #endif
160     }
161   else if (LocaleCompare(image_info->magick,"XTRNBLOB") == 0)
162     {
163       char
164         **blob_data;
165 
166       size_t
167         *blob_length;
168 
169       char
170         filename[MagickPathExtent];
171 
172       (void) sscanf(clone_info->filename,"%lx,%lx,%2048s",&param1,&param2,
173         filename);
174       blob_data=(char **) param1;
175       blob_length=(size_t *) param2;
176       image=BlobToImage(clone_info,*blob_data,*blob_length,exception);
177       CatchException(exception);
178     }
179   else if (LocaleCompare(image_info->magick,"XTRNARRAY") == 0)
180     {
181       char
182         *blob_data,
183         filename[MagickPathExtent];
184 
185       HRESULT
186         hr;
187 
188       long
189         lBoundl,
190         lBoundu;
191 
192       SAFEARRAY
193         *pSafeArray;
194 
195       size_t
196         blob_length;
197 
198       *filename='\0';
199       (void) sscanf(clone_info->filename,"%lx,%2048s",&param1,filename);
200       hr=S_OK;
201       pSafeArray=(SAFEARRAY *) param1;
202       if (pSafeArray)
203         {
204           hr = SafeArrayGetLBound(pSafeArray, 1, &lBoundl);
205           if (SUCCEEDED(hr))
206             {
207               hr = SafeArrayGetUBound(pSafeArray, 1, &lBoundu);
208               if (SUCCEEDED(hr))
209                 {
210                   blob_length = lBoundu - lBoundl + 1;
211                   hr = SafeArrayAccessData(pSafeArray,(void**) &blob_data);
212                   if(SUCCEEDED(hr))
213                     {
214                       *clone_info->filename='\0';
215                       *clone_info->magick='\0';
216                       if (*filename != '\0')
217                         (void) CopyMagickString(clone_info->filename,filename,
218                           MagickPathExtent);
219                       image=BlobToImage(clone_info,blob_data,blob_length,
220                         exception);
221                       hr=SafeArrayUnaccessData(pSafeArray);
222                       CatchException(exception);
223                     }
224                 }
225             }
226         }
227     }
228   clone_info=DestroyImageInfo(clone_info);
229   return(image);
230 }
231 #  pragma warning(default : 4477)
232 #endif
233 
234 /*
235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236 %                                                                             %
237 %                                                                             %
238 %                                                                             %
239 %   R e g i s t e r X T R N I m a g e                                         %
240 %                                                                             %
241 %                                                                             %
242 %                                                                             %
243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244 %
245 %  RegisterXTRNImage() adds attributes for the XTRN image format to
246 %  the list of supported formats.  The attributes include the image format
247 %  tag, a method to read and/or write the format, whether the format
248 %  supports the saving of more than one frame to the same file or blob,
249 %  whether the format supports native in-memory I/O, and a brief
250 %  description of the format.
251 %
252 %  The format of the RegisterXTRNImage method is:
253 %
254 %      size_t RegisterXTRNImage(void)
255 %
256 */
RegisterXTRNImage(void)257 ModuleExport size_t RegisterXTRNImage(void)
258 {
259   MagickInfo
260     *entry;
261 
262   entry=AcquireMagickInfo("XTRN","XTRNFILE","External transfer of a file");
263 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
264   entry->decoder=ReadXTRNImage;
265   entry->encoder=WriteXTRNImage;
266 #endif
267   entry->flags^=CoderAdjoinFlag;
268   entry->flags|=CoderStealthFlag;
269   RegisterMagickInfo(entry);
270   entry=AcquireMagickInfo("XTRN","XTRNIMAGE",
271     "External transfer of a image in memory");
272 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
273   entry->decoder=ReadXTRNImage;
274   entry->encoder=WriteXTRNImage;
275 #endif
276   entry->flags^=CoderAdjoinFlag;
277   entry->flags|=CoderStealthFlag;
278   RegisterMagickInfo(entry);
279   entry=AcquireMagickInfo("XTRN","XTRNBLOB",
280     "IExternal transfer of a blob in memory");
281 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
282   entry->decoder=ReadXTRNImage;
283   entry->encoder=WriteXTRNImage;
284 #endif
285   entry->flags^=CoderAdjoinFlag;
286   entry->flags|=CoderStealthFlag;
287   RegisterMagickInfo(entry);
288   entry=AcquireMagickInfo("XTRN","XTRNARRAY",
289     "External transfer via a smart array interface");
290 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
291   entry->decoder=ReadXTRNImage;
292   entry->encoder=WriteXTRNImage;
293 #endif
294   entry->flags^=CoderAdjoinFlag;
295   entry->flags|=CoderStealthFlag;
296   RegisterMagickInfo(entry);
297   return(MagickImageCoderSignature);
298 }
299 
300 /*
301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 %                                                                             %
303 %                                                                             %
304 %                                                                             %
305 %   U n r e g i s t e r X T R N I m a g e                                     %
306 %                                                                             %
307 %                                                                             %
308 %                                                                             %
309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310 %
311 %  UnregisterXTRNImage() removes format registrations made by the
312 %  XTRN module from the list of supported formats.
313 %
314 %  The format of the UnregisterXTRNImage method is:
315 %
316 %      UnregisterXTRNImage(void)
317 %
318 */
UnregisterXTRNImage(void)319 ModuleExport void UnregisterXTRNImage(void)
320 {
321   UnregisterMagickInfo("XTRNFILE");
322   UnregisterMagickInfo("XTRNIMAGE");
323   UnregisterMagickInfo("XTRNBLOB");
324   UnregisterMagickInfo("XTRNARRAY");
325 }
326 
327 /*
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 %                                                                             %
330 %                                                                             %
331 %                                                                             %
332 %   W r i t e X T R N I m a g e                                               %
333 %                                                                             %
334 %                                                                             %
335 %                                                                             %
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %
338 %  WriteXTRNImage() writes an image in the XTRN encoded image format.
339 %  We use GIF because it is the only format that is compressed without
340 %  requiring additional optional delegates (TIFF, ZIP, etc).
341 %
342 %  The format of the WriteXTRNImage method is:
343 %
344 %      MagickBooleanType WriteXTRNImage(const ImageInfo *image_info,
345 %        Image *image,ExceptionInfo *exception)
346 %
347 %  A description of each parameter follows.
348 %
349 %    o image_info: Specifies a pointer to an ImageInfo structure.
350 %
351 %    o image:  A pointer to a Image structure.
352 %
353 %    o exception: return any errors or warnings in this structure.
354 %
355 */
356 
357 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
SafeArrayFifo(const Image * image,const void * data,const size_t length)358 static size_t SafeArrayFifo(const Image *image,const void *data,
359   const size_t length)
360 {
361   SAFEARRAYBOUND NewArrayBounds[1];  /* 1 Dimension */
362   size_t tlen=length;
363   SAFEARRAY *pSafeArray = (SAFEARRAY *)image->client_data;
364   if (pSafeArray != NULL)
365   {
366     long lBoundl, lBoundu, lCount;
367     HRESULT hr = S_OK;
368     /* First see how big the buffer currently is */
369     hr = SafeArrayGetLBound(pSafeArray, 1, &lBoundl);
370     if (FAILED(hr))
371       return MagickFalse;
372     hr = SafeArrayGetUBound(pSafeArray, 1, &lBoundu);
373     if (FAILED(hr))
374       return MagickFalse;
375     lCount = lBoundu - lBoundl + 1;
376 
377     if (length>0)
378     {
379       unsigned char       *pReturnBuffer = NULL;
380       NewArrayBounds[0].lLbound = 0;   /* Start-Index 0 */
381       NewArrayBounds[0].cElements = (unsigned long) (length+lCount);  /* # Elemente */
382       hr = SafeArrayRedim(pSafeArray, NewArrayBounds);
383       if (FAILED(hr))
384         return 0;
385       hr = SafeArrayAccessData(pSafeArray, (void**)&pReturnBuffer);
386       if( FAILED(hr) )
387         return 0;
388       (void) memcpy(pReturnBuffer+lCount,(unsigned char *) data,length);
389       hr=SafeArrayUnaccessData(pSafeArray);
390       if(FAILED(hr))
391         return 0;
392     }
393     else
394     {
395       /* Adjust the length of the buffer to fit */
396     }
397   }
398   return(tlen);
399 }
400 #endif
401 
402 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
403 #  pragma warning(disable : 4477)
WriteXTRNImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)404 static MagickBooleanType WriteXTRNImage(const ImageInfo *image_info,
405   Image *image,ExceptionInfo *exception)
406 {
407   Image *
408     p;
409 
410   ImageInfo
411     *clone_info;
412 
413   int
414     scene;
415 
416   MagickBooleanType
417     status;
418 
419   void
420     *param1,
421     *param2,
422     *param3;
423 
424   param1 = param2 = param3 = (void *) NULL;
425   status=MagickTrue;
426   if (LocaleCompare(image_info->magick,"XTRNFILE") == 0)
427     {
428       clone_info=CloneImageInfo(image_info);
429       *clone_info->magick='\0';
430       status=WriteImage(clone_info,image,exception);
431       if (status == MagickFalse)
432         CatchImageException(image);
433       clone_info=DestroyImageInfo(clone_info);
434     }
435   else if (LocaleCompare(image_info->magick,"XTRNIMAGE") == 0)
436     {
437       Image
438         **image_ptr;
439 
440       ImageInfo
441         **image_info_ptr;
442 
443       clone_info=CloneImageInfo(image_info);
444       if (clone_info->filename[0])
445         {
446           (void) sscanf(clone_info->filename,"%lx,%lx",&param1,&param2);
447           image_info_ptr=(ImageInfo **) param1;
448           image_ptr=(Image **) param2;
449           if ((image_info_ptr != (ImageInfo **) NULL) &&
450               (image_ptr != (Image **) NULL))
451             {
452               *image_ptr=CloneImage(image,0,0,MagickFalse,exception);
453               *image_info_ptr=clone_info;
454             }
455         }
456     }
457   else if (LocaleCompare(image_info->magick,"XTRNBLOB") == 0)
458     {
459       char
460         **blob_data;
461 
462       size_t
463         *blob_length;
464 
465       char
466         filename[MagickPathExtent];
467 
468       clone_info=CloneImageInfo(image_info);
469       if (clone_info->filename[0])
470         {
471           (void) sscanf(clone_info->filename,"%lx,%lx,%2048s",
472             &param1,&param2,filename);
473 
474           blob_data=(char **) param1;
475           blob_length=(size_t *) param2;
476           scene = 0;
477           (void) CopyMagickString(clone_info->filename,filename,
478             MagickPathExtent);
479           for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
480           {
481             (void) CopyMagickString(p->filename,filename,MagickPathExtent);
482             p->scene=scene++;
483           }
484           SetImageInfo(clone_info,1,exception);
485           (void) CopyMagickString(image->magick,clone_info->magick,
486             MagickPathExtent);
487           if (*blob_length == 0)
488             *blob_length=8192;
489           *blob_data=(char *) ImageToBlob(clone_info,image,blob_length,
490             exception);
491           if (*blob_data == NULL)
492             status=MagickFalse;
493           if (status == MagickFalse)
494             CatchImageException(image);
495         }
496       clone_info=DestroyImageInfo(clone_info);
497     }
498   else if (LocaleCompare(image_info->magick,"XTRNARRAY") == 0)
499     {
500       char
501         filename[MagickPathExtent];
502 
503       size_t
504         blob_length;
505 
506       unsigned char
507         *blob_data;
508 
509       clone_info=CloneImageInfo(image_info);
510       if (*clone_info->filename != '\0')
511         {
512           (void) sscanf(clone_info->filename,"%lx,%2048s",&param1,filename);
513           image->client_data=param1;
514           scene=0;
515           (void) CopyMagickString(clone_info->filename,filename,
516             MagickPathExtent);
517           for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
518           {
519             (void) CopyMagickString(p->filename,filename,MagickPathExtent);
520             p->scene=scene++;
521           }
522           SetImageInfo(clone_info,1,exception);
523           (void) CopyMagickString(image->magick,clone_info->magick,
524             MagickPathExtent);
525           blob_data=ImageToBlob(clone_info,image,&blob_length,
526             exception);
527           if (blob_data == (unsigned char *) NULL)
528             status=MagickFalse;
529           else
530             SafeArrayFifo(image,blob_data,blob_length);
531           if (status == MagickFalse)
532             CatchImageException(image);
533         }
534       clone_info=DestroyImageInfo(clone_info);
535     }
536   return(MagickTrue);
537 }
538 #  pragma warning(default : 4477)
539 #endif
540