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",¶m1,¶m2); 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",¶m1,¶m2, 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",¶m1,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",¶m1,¶m2); 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 ¶m1,¶m2,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",¶m1,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