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