ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

olepicture.c
Go to the documentation of this file.
00001 /*
00002  * OLE Picture object
00003  *
00004  * Implementation of OLE IPicture and related interfaces
00005  *
00006  * Copyright 2000 Huw D M Davies for CodeWeavers.
00007  * Copyright 2001 Marcus Meissner
00008  * Copyright 2008 Kirill K. Smirnov
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  *
00024  * BUGS
00025  *
00026  * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well..
00027  * Lots of methods are just stubs.
00028  *
00029  *
00030  * NOTES (or things that msdn doesn't tell you)
00031  *
00032  * The width and height properties are returned in HIMETRIC units (0.01mm)
00033  * IPicture::Render also uses these to select a region of the src picture.
00034  * A bitmap's size is converted into these units by using the screen resolution
00035  * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
00036  *
00037  */
00038 
00039 #include "config.h"
00040 #include "wine/port.h"
00041 
00042 #ifdef HAVE_UNISTD_H
00043 # include <unistd.h>
00044 #endif
00045 #include <stdarg.h>
00046 #include <stdio.h>
00047 #include <string.h>
00048 
00049 #define COBJMACROS
00050 #define NONAMELESSUNION
00051 #define NONAMELESSSTRUCT
00052 
00053 #include "winerror.h"
00054 #include "windef.h"
00055 #include "winbase.h"
00056 #include "wingdi.h"
00057 #include "winuser.h"
00058 #include "ole2.h"
00059 #include "olectl.h"
00060 #include "oleauto.h"
00061 #include "connpt.h"
00062 #include "urlmon.h"
00063 #include "wincodec.h"
00064 #include "wine/debug.h"
00065 #include "wine/unicode.h"
00066 #include "wine/library.h"
00067 
00068 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00069 
00070 #include "pshpack1.h"
00071 
00072 /* Header for Aldus Placable Metafiles - a standard metafile follows */
00073 typedef struct _APM_HEADER
00074 {
00075     DWORD key;
00076     WORD handle;
00077     SHORT left;
00078     SHORT top;
00079     SHORT right;
00080     SHORT bottom;
00081     WORD inch;
00082     DWORD reserved;
00083     WORD checksum;
00084 } APM_HEADER;
00085 
00086 typedef struct {
00087     BYTE bWidth;
00088     BYTE bHeight;
00089     BYTE bColorCount;
00090     BYTE bReserved;
00091     WORD xHotspot;
00092     WORD yHotspot;
00093     DWORD dwDIBSize;
00094     DWORD dwDIBOffset;
00095 } CURSORICONFILEDIRENTRY;
00096 
00097 typedef struct
00098 {
00099     WORD                idReserved;
00100     WORD                idType;
00101     WORD                idCount;
00102     CURSORICONFILEDIRENTRY  idEntries[1];
00103 } CURSORICONFILEDIR;
00104 
00105 #include "poppack.h"
00106 
00107 /*************************************************************************
00108  *  Declaration of implementation class
00109  */
00110 
00111 typedef struct OLEPictureImpl {
00112 
00113   /*
00114    * IPicture handles IUnknown
00115    */
00116 
00117     const IPictureVtbl       *lpVtbl;
00118     const IDispatchVtbl      *lpvtblIDispatch;
00119     const IPersistStreamVtbl *lpvtblIPersistStream;
00120     const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
00121 
00122   /* Object reference count */
00123     LONG ref;
00124 
00125   /* We own the object and must destroy it ourselves */
00126     BOOL fOwn;
00127 
00128   /* Picture description */
00129     PICTDESC desc;
00130 
00131   /* These are the pixel size of a bitmap */
00132     DWORD origWidth;
00133     DWORD origHeight;
00134 
00135   /* And these are the size of the picture converted into HIMETRIC units */
00136     OLE_XSIZE_HIMETRIC himetricWidth;
00137     OLE_YSIZE_HIMETRIC himetricHeight;
00138 
00139     IConnectionPoint *pCP;
00140 
00141     BOOL keepOrigFormat;
00142     HDC hDCCur;
00143 
00144   /* Bitmap transparency mask */
00145     HBITMAP hbmMask;
00146     HBITMAP hbmXor;
00147     COLORREF rgbTrans;
00148 
00149   /* data */
00150     void* data;
00151     int datalen;
00152     BOOL bIsDirty;                  /* Set to TRUE if picture has changed */
00153     unsigned int loadtime_magic;    /* If a length header was found, saves value */
00154     unsigned int loadtime_format;   /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
00155 } OLEPictureImpl;
00156 
00157 /*
00158  * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
00159  */
00160 
00161 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
00162 {
00163     return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
00164 }
00165 
00166 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
00167 {
00168     return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
00169 }
00170 
00171 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
00172 {
00173     return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
00174 }
00175 
00176 /*
00177  * Predeclare VTables.  They get initialized at the end.
00178  */
00179 static const IPictureVtbl OLEPictureImpl_VTable;
00180 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
00181 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
00182 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
00183 
00184 /***********************************************************************
00185  * Implementation of the OLEPictureImpl class.
00186  */
00187 
00188 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
00189   BITMAP bm;
00190   HDC hdcRef;
00191 
00192   TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
00193   if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
00194     ERR("GetObject fails\n");
00195     return;
00196   }
00197   This->origWidth = bm.bmWidth;
00198   This->origHeight = bm.bmHeight;
00199   /* The width and height are stored in HIMETRIC units (0.01 mm),
00200      so we take our pixel width divide by pixels per inch and
00201      multiply by 25.4 * 100 */
00202   /* Should we use GetBitmapDimension if available? */
00203   hdcRef = CreateCompatibleDC(0);
00204   This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
00205   This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
00206   DeleteDC(hdcRef);
00207 }
00208 
00209 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
00210 {
00211     ICONINFO infoIcon;
00212 
00213     TRACE("icon handle %p\n", This->desc.u.icon.hicon);
00214     if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
00215         HDC hdcRef;
00216         BITMAP bm;
00217 
00218         TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
00219         if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
00220             ERR("GetObject fails on icon bitmap\n");
00221             return;
00222         }
00223 
00224         This->origWidth = bm.bmWidth;
00225         This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
00226         /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
00227         hdcRef = GetDC(0);
00228         This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
00229         This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
00230         ReleaseDC(0, hdcRef);
00231 
00232         DeleteObject(infoIcon.hbmMask);
00233         if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
00234     } else {
00235         ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
00236     }
00237 }
00238 
00239 /************************************************************************
00240  * OLEPictureImpl_Construct
00241  *
00242  * This method will construct a new instance of the OLEPictureImpl
00243  * class.
00244  *
00245  * The caller of this method must release the object when it's
00246  * done with it.
00247  */
00248 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
00249 {
00250   OLEPictureImpl* newObject = 0;
00251 
00252   if (pictDesc)
00253       TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
00254 
00255   /*
00256    * Allocate space for the object.
00257    */
00258   newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
00259 
00260   if (newObject==0)
00261     return newObject;
00262 
00263   /*
00264    * Initialize the virtual function table.
00265    */
00266   newObject->lpVtbl = &OLEPictureImpl_VTable;
00267   newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
00268   newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
00269   newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
00270 
00271   newObject->pCP = NULL;
00272   CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
00273   if (!newObject->pCP)
00274   {
00275     HeapFree(GetProcessHeap(), 0, newObject);
00276     return NULL;
00277   }
00278 
00279   /*
00280    * Start with one reference count. The caller of this function
00281    * must release the interface pointer when it is done.
00282    */
00283   newObject->ref    = 1;
00284   newObject->hDCCur = 0;
00285 
00286   newObject->fOwn   = fOwn;
00287 
00288   /* dunno about original value */
00289   newObject->keepOrigFormat = TRUE;
00290 
00291   newObject->hbmMask = NULL;
00292   newObject->hbmXor = NULL;
00293   newObject->loadtime_magic = 0xdeadbeef;
00294   newObject->loadtime_format = 0;
00295   newObject->bIsDirty = FALSE;
00296 
00297   if (pictDesc) {
00298       newObject->desc = *pictDesc;
00299 
00300       switch(pictDesc->picType) {
00301       case PICTYPE_BITMAP:
00302     OLEPictureImpl_SetBitmap(newObject);
00303     break;
00304 
00305       case PICTYPE_METAFILE:
00306     TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
00307     newObject->himetricWidth = pictDesc->u.wmf.xExt;
00308     newObject->himetricHeight = pictDesc->u.wmf.yExt;
00309     break;
00310 
00311       case PICTYPE_NONE:
00312     /* not sure what to do here */
00313     newObject->himetricWidth = newObject->himetricHeight = 0;
00314     break;
00315 
00316       case PICTYPE_ICON:
00317         OLEPictureImpl_SetIcon(newObject);
00318         break;
00319       case PICTYPE_ENHMETAFILE:
00320       default:
00321     FIXME("Unsupported type %d\n", pictDesc->picType);
00322     newObject->himetricWidth = newObject->himetricHeight = 0;
00323     break;
00324       }
00325   } else {
00326       newObject->desc.picType = PICTYPE_UNINITIALIZED;
00327   }
00328 
00329   TRACE("returning %p\n", newObject);
00330   return newObject;
00331 }
00332 
00333 /************************************************************************
00334  * OLEPictureImpl_Destroy
00335  *
00336  * This method is called by the Release method when the reference
00337  * count goes down to 0. It will free all resources used by
00338  * this object.  */
00339 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
00340 {
00341   TRACE("(%p)\n", Obj);
00342 
00343   if (Obj->pCP)
00344     IConnectionPoint_Release(Obj->pCP);
00345 
00346   if(Obj->fOwn) { /* We need to destroy the picture */
00347     switch(Obj->desc.picType) {
00348     case PICTYPE_BITMAP:
00349       DeleteObject(Obj->desc.u.bmp.hbitmap);
00350       if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
00351       if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
00352       break;
00353     case PICTYPE_METAFILE:
00354       DeleteMetaFile(Obj->desc.u.wmf.hmeta);
00355       break;
00356     case PICTYPE_ICON:
00357       DestroyIcon(Obj->desc.u.icon.hicon);
00358       break;
00359     case PICTYPE_ENHMETAFILE:
00360       DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
00361       break;
00362     case PICTYPE_NONE:
00363     case PICTYPE_UNINITIALIZED:
00364       /* Nothing to do */
00365       break;
00366     default:
00367       FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
00368       break;
00369     }
00370   }
00371   HeapFree(GetProcessHeap(), 0, Obj->data);
00372   HeapFree(GetProcessHeap(), 0, Obj);
00373 }
00374 
00375 
00376 /************************************************************************
00377  * OLEPictureImpl_AddRef (IUnknown)
00378  *
00379  * See Windows documentation for more details on IUnknown methods.
00380  */
00381 static ULONG WINAPI OLEPictureImpl_AddRef(
00382   IPicture* iface)
00383 {
00384   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00385   ULONG refCount = InterlockedIncrement(&This->ref);
00386 
00387   TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
00388 
00389   return refCount;
00390 }
00391 
00392 /************************************************************************
00393  * OLEPictureImpl_Release (IUnknown)
00394  *
00395  * See Windows documentation for more details on IUnknown methods.
00396  */
00397 static ULONG WINAPI OLEPictureImpl_Release(
00398       IPicture* iface)
00399 {
00400   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00401   ULONG refCount = InterlockedDecrement(&This->ref);
00402 
00403   TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
00404 
00405   /*
00406    * If the reference count goes down to 0, perform suicide.
00407    */
00408   if (!refCount) OLEPictureImpl_Destroy(This);
00409 
00410   return refCount;
00411 }
00412 
00413 /************************************************************************
00414  * OLEPictureImpl_QueryInterface (IUnknown)
00415  *
00416  * See Windows documentation for more details on IUnknown methods.
00417  */
00418 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
00419   IPicture*  iface,
00420   REFIID  riid,
00421   void**  ppvObject)
00422 {
00423   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00424   TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
00425 
00426   /*
00427    * Perform a sanity check on the parameters.
00428    */
00429   if ( (This==0) || (ppvObject==0) )
00430     return E_INVALIDARG;
00431 
00432   /*
00433    * Initialize the return parameter.
00434    */
00435   *ppvObject = 0;
00436 
00437   /*
00438    * Compare the riid with the interface IDs implemented by this object.
00439    */
00440   if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
00441     *ppvObject = This;
00442   else if (IsEqualIID(&IID_IDispatch, riid))
00443     *ppvObject = &This->lpvtblIDispatch;
00444   else if (IsEqualIID(&IID_IPictureDisp, riid))
00445     *ppvObject = &This->lpvtblIDispatch;
00446   else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
00447     *ppvObject = &This->lpvtblIPersistStream;
00448   else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
00449     *ppvObject = &This->lpvtblIConnectionPointContainer;
00450 
00451   /*
00452    * Check that we obtained an interface.
00453    */
00454   if ((*ppvObject)==0)
00455   {
00456     FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
00457     return E_NOINTERFACE;
00458   }
00459 
00460   /*
00461    * Query Interface always increases the reference count by one when it is
00462    * successful
00463    */
00464   OLEPictureImpl_AddRef((IPicture*)This);
00465 
00466   return S_OK;
00467 }
00468 
00469 /***********************************************************************
00470  *    OLEPicture_SendNotify (internal)
00471  *
00472  * Sends notification messages of changed properties to any interested
00473  * connections.
00474  */
00475 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
00476 {
00477   IEnumConnections *pEnum;
00478   CONNECTDATA CD;
00479 
00480   if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
00481       return;
00482   while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
00483     IPropertyNotifySink *sink;
00484 
00485     IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
00486     IPropertyNotifySink_OnChanged(sink, dispID);
00487     IPropertyNotifySink_Release(sink);
00488     IUnknown_Release(CD.pUnk);
00489   }
00490   IEnumConnections_Release(pEnum);
00491 }
00492 
00493 /************************************************************************
00494  * OLEPictureImpl_get_Handle
00495  */
00496 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
00497                         OLE_HANDLE *phandle)
00498 {
00499   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00500   TRACE("(%p)->(%p)\n", This, phandle);
00501 
00502   if(!phandle)
00503     return E_POINTER;
00504 
00505   switch(This->desc.picType) {
00506   case PICTYPE_NONE:
00507   case PICTYPE_UNINITIALIZED:
00508     *phandle = 0;
00509     break;
00510   case PICTYPE_BITMAP:
00511     *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
00512     break;
00513   case PICTYPE_METAFILE:
00514     *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
00515     break;
00516   case PICTYPE_ICON:
00517     *phandle = HandleToUlong(This->desc.u.icon.hicon);
00518     break;
00519   case PICTYPE_ENHMETAFILE:
00520     *phandle = HandleToUlong(This->desc.u.emf.hemf);
00521     break;
00522   default:
00523     FIXME("Unimplemented type %d\n", This->desc.picType);
00524     return E_NOTIMPL;
00525   }
00526   TRACE("returning handle %08x\n", *phandle);
00527   return S_OK;
00528 }
00529 
00530 /************************************************************************
00531  * OLEPictureImpl_get_hPal
00532  */
00533 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
00534                           OLE_HANDLE *phandle)
00535 {
00536   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00537   HRESULT hres;
00538   TRACE("(%p)->(%p)\n", This, phandle);
00539 
00540   if (!phandle)
00541     return E_POINTER;
00542 
00543   switch (This->desc.picType) {
00544     case (UINT)PICTYPE_UNINITIALIZED:
00545     case PICTYPE_NONE:
00546       *phandle = 0;
00547       hres = S_FALSE;
00548       break;
00549     case PICTYPE_BITMAP:
00550       *phandle = HandleToUlong(This->desc.u.bmp.hpal);
00551       hres = S_OK;
00552       break;
00553     case PICTYPE_METAFILE:
00554       hres = E_FAIL;
00555       break;
00556     case PICTYPE_ICON:
00557     case PICTYPE_ENHMETAFILE:
00558     default:
00559       FIXME("unimplemented for type %d. Returning 0 palette.\n",
00560            This->desc.picType);
00561       *phandle = 0;
00562       hres = S_OK;
00563   }
00564 
00565   TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
00566   return hres;
00567 }
00568 
00569 /************************************************************************
00570  * OLEPictureImpl_get_Type
00571  */
00572 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
00573                           short *ptype)
00574 {
00575   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00576   TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
00577 
00578   if(!ptype)
00579     return E_POINTER;
00580 
00581   *ptype = This->desc.picType;
00582   return S_OK;
00583 }
00584 
00585 /************************************************************************
00586  * OLEPictureImpl_get_Width
00587  */
00588 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
00589                            OLE_XSIZE_HIMETRIC *pwidth)
00590 {
00591   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00592   TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
00593   *pwidth = This->himetricWidth;
00594   return S_OK;
00595 }
00596 
00597 /************************************************************************
00598  * OLEPictureImpl_get_Height
00599  */
00600 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
00601                         OLE_YSIZE_HIMETRIC *pheight)
00602 {
00603   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00604   TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
00605   *pheight = This->himetricHeight;
00606   return S_OK;
00607 }
00608 
00609 /************************************************************************
00610  * OLEPictureImpl_Render
00611  */
00612 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
00613                         LONG x, LONG y, LONG cx, LONG cy,
00614                         OLE_XPOS_HIMETRIC xSrc,
00615                         OLE_YPOS_HIMETRIC ySrc,
00616                         OLE_XSIZE_HIMETRIC cxSrc,
00617                         OLE_YSIZE_HIMETRIC cySrc,
00618                         LPCRECT prcWBounds)
00619 {
00620   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00621   TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
00622     This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
00623   if(prcWBounds)
00624     TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
00625       prcWBounds->right, prcWBounds->bottom);
00626 
00627   if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
00628     return CTL_E_INVALIDPROPERTYVALUE;
00629   }
00630 
00631   /*
00632    * While the documentation suggests this to be here (or after rendering?)
00633    * it does cause an endless recursion in my sample app. -MM 20010804
00634   OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
00635    */
00636 
00637   switch(This->desc.picType) {
00638   case PICTYPE_UNINITIALIZED:
00639   case PICTYPE_NONE:
00640     /* nothing to do */
00641     return S_OK;
00642   case PICTYPE_BITMAP:
00643     {
00644       HBITMAP hbmpOld;
00645       HDC hdcBmp;
00646 
00647       /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
00648          NB y-axis gets flipped */
00649 
00650       hdcBmp = CreateCompatibleDC(0);
00651       SetMapMode(hdcBmp, MM_ANISOTROPIC);
00652       SetWindowOrgEx(hdcBmp, 0, 0, NULL);
00653       SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
00654       SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
00655       SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
00656 
00657       if (This->hbmMask) {
00658       HDC hdcMask = CreateCompatibleDC(0);
00659       HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
00660 
00661           hbmpOld = SelectObject(hdcBmp, This->hbmXor);
00662 
00663       SetMapMode(hdcMask, MM_ANISOTROPIC);
00664       SetWindowOrgEx(hdcMask, 0, 0, NULL);
00665       SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
00666       SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
00667       SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
00668       
00669       SetBkColor(hdc, RGB(255, 255, 255));    
00670       SetTextColor(hdc, RGB(0, 0, 0));        
00671       StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND); 
00672       StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
00673 
00674       SelectObject(hdcMask, hOldbm);
00675       DeleteDC(hdcMask);
00676       } else {
00677           hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
00678       StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
00679       }
00680 
00681       SelectObject(hdcBmp, hbmpOld);
00682       DeleteDC(hdcBmp);
00683     }
00684     break;
00685   case PICTYPE_ICON:
00686     FIXME("Not quite correct implementation of rendering icons...\n");
00687     DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL);
00688     break;
00689 
00690   case PICTYPE_METAFILE:
00691   {
00692     POINT prevOrg, prevWndOrg;
00693     SIZE prevExt, prevWndExt;
00694     int oldmode;
00695 
00696     /* Render the WMF to the appropriate location by setting the
00697        appropriate ratio between "device units" and "logical units" */
00698     oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
00699     /* For the "source rectangle" the y-axis must be inverted */
00700     SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
00701     SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
00702     /* For the "destination rectangle" no inversion is necessary */
00703     SetViewportOrgEx(hdc, x, y, &prevOrg);
00704     SetViewportExtEx(hdc, cx, cy, &prevExt);
00705 
00706     if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
00707         ERR("PlayMetaFile failed!\n");
00708 
00709     /* We're done, restore the DC to the previous settings for converting
00710        logical units to device units */
00711     SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
00712     SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
00713     SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
00714     SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
00715     SetMapMode(hdc, oldmode);
00716     break;
00717   }
00718 
00719   case PICTYPE_ENHMETAFILE:
00720   {
00721     RECT rc = { x, y, x + cx, y + cy };
00722     PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
00723     break;
00724   }
00725 
00726   default:
00727     FIXME("type %d not implemented\n", This->desc.picType);
00728     return E_NOTIMPL;
00729   }
00730   return S_OK;
00731 }
00732 
00733 /************************************************************************
00734  * OLEPictureImpl_set_hPal
00735  */
00736 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
00737                           OLE_HANDLE hpal)
00738 {
00739   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00740   FIXME("(%p)->(%08x): stub\n", This, hpal);
00741   OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
00742   return E_NOTIMPL;
00743 }
00744 
00745 /************************************************************************
00746  * OLEPictureImpl_get_CurDC
00747  */
00748 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
00749                            HDC *phdc)
00750 {
00751   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00752   TRACE("(%p), returning %p\n", This, This->hDCCur);
00753   if (phdc) *phdc = This->hDCCur;
00754   return S_OK;
00755 }
00756 
00757 /************************************************************************
00758  * OLEPictureImpl_SelectPicture
00759  */
00760 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
00761                            HDC hdcIn,
00762                            HDC *phdcOut,
00763                            OLE_HANDLE *phbmpOut)
00764 {
00765   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00766   TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
00767   if (This->desc.picType == PICTYPE_BITMAP) {
00768       SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
00769 
00770       if (phdcOut)
00771       *phdcOut = This->hDCCur;
00772       This->hDCCur = hdcIn;
00773       if (phbmpOut)
00774       *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
00775       return S_OK;
00776   } else {
00777       FIXME("Don't know how to select picture type %d\n",This->desc.picType);
00778       return E_FAIL;
00779   }
00780 }
00781 
00782 /************************************************************************
00783  * OLEPictureImpl_get_KeepOriginalFormat
00784  */
00785 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
00786                                 BOOL *pfKeep)
00787 {
00788   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00789   TRACE("(%p)->(%p)\n", This, pfKeep);
00790   if (!pfKeep)
00791       return E_POINTER;
00792   *pfKeep = This->keepOrigFormat;
00793   return S_OK;
00794 }
00795 
00796 /************************************************************************
00797  * OLEPictureImpl_put_KeepOriginalFormat
00798  */
00799 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
00800                                 BOOL keep)
00801 {
00802   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00803   TRACE("(%p)->(%d)\n", This, keep);
00804   This->keepOrigFormat = keep;
00805   /* FIXME: what DISPID notification here? */
00806   return S_OK;
00807 }
00808 
00809 /************************************************************************
00810  * OLEPictureImpl_PictureChanged
00811  */
00812 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
00813 {
00814   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00815   TRACE("(%p)->()\n", This);
00816   OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
00817   This->bIsDirty = TRUE;
00818   return S_OK;
00819 }
00820 
00821 /************************************************************************
00822  * OLEPictureImpl_SaveAsFile
00823  */
00824 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
00825                         IStream *pstream,
00826                         BOOL SaveMemCopy,
00827                         LONG *pcbSize)
00828 {
00829   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00830   FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
00831   return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
00832 }
00833 
00834 /************************************************************************
00835  * OLEPictureImpl_get_Attributes
00836  */
00837 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
00838                             DWORD *pdwAttr)
00839 {
00840   OLEPictureImpl *This = (OLEPictureImpl *)iface;
00841   TRACE("(%p)->(%p).\n", This, pdwAttr);
00842 
00843   if(!pdwAttr)
00844     return E_POINTER;
00845 
00846   *pdwAttr = 0;
00847   switch (This->desc.picType) {
00848   case PICTYPE_UNINITIALIZED:
00849   case PICTYPE_NONE: break;
00850   case PICTYPE_BITMAP:  if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break;   /* not 'truly' scalable, see MSDN. */
00851   case PICTYPE_ICON: *pdwAttr     = PICTURE_TRANSPARENT;break;
00852   case PICTYPE_ENHMETAFILE: /* fall through */
00853   case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
00854   default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
00855   }
00856   return S_OK;
00857 }
00858 
00859 
00860 /************************************************************************
00861  *    IConnectionPointContainer
00862  */
00863 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
00864   IConnectionPointContainer* iface,
00865   REFIID riid,
00866   VOID** ppvoid)
00867 {
00868   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
00869 
00870   return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
00871 }
00872 
00873 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
00874   IConnectionPointContainer* iface)
00875 {
00876   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
00877 
00878   return IPicture_AddRef((IPicture *)This);
00879 }
00880 
00881 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
00882   IConnectionPointContainer* iface)
00883 {
00884   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
00885 
00886   return IPicture_Release((IPicture *)This);
00887 }
00888 
00889 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
00890   IConnectionPointContainer* iface,
00891   IEnumConnectionPoints** ppEnum)
00892 {
00893   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
00894 
00895   FIXME("(%p,%p), stub!\n",This,ppEnum);
00896   return E_NOTIMPL;
00897 }
00898 
00899 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
00900   IConnectionPointContainer* iface,
00901   REFIID riid,
00902   IConnectionPoint **ppCP)
00903 {
00904   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
00905   TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
00906   if (!ppCP)
00907       return E_POINTER;
00908   *ppCP = NULL;
00909   if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
00910       return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
00911   FIXME("no connection point for %s\n",debugstr_guid(riid));
00912   return CONNECT_E_NOCONNECTION;
00913 }
00914 
00915 
00916 /************************************************************************
00917  *    IPersistStream
00918  */
00919 
00920 /************************************************************************
00921  * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
00922  *
00923  * See Windows documentation for more details on IUnknown methods.
00924  */
00925 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
00926   IPersistStream* iface,
00927   REFIID     riid,
00928   VOID**     ppvoid)
00929 {
00930   OLEPictureImpl *This = impl_from_IPersistStream(iface);
00931 
00932   return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
00933 }
00934 
00935 /************************************************************************
00936  * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
00937  *
00938  * See Windows documentation for more details on IUnknown methods.
00939  */
00940 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
00941   IPersistStream* iface)
00942 {
00943   OLEPictureImpl *This = impl_from_IPersistStream(iface);
00944 
00945   return IPicture_AddRef((IPicture *)This);
00946 }
00947 
00948 /************************************************************************
00949  * OLEPictureImpl_IPersistStream_Release (IUnknown)
00950  *
00951  * See Windows documentation for more details on IUnknown methods.
00952  */
00953 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
00954   IPersistStream* iface)
00955 {
00956   OLEPictureImpl *This = impl_from_IPersistStream(iface);
00957 
00958   return IPicture_Release((IPicture *)This);
00959 }
00960 
00961 /************************************************************************
00962  * OLEPictureImpl_IPersistStream_GetClassID
00963  */
00964 static HRESULT WINAPI OLEPictureImpl_GetClassID(
00965   IPersistStream* iface,CLSID* pClassID)
00966 {
00967   TRACE("(%p)\n", pClassID);
00968   *pClassID = CLSID_StdPicture;
00969   return S_OK;
00970 }
00971 
00972 /************************************************************************
00973  * OLEPictureImpl_IPersistStream_IsDirty
00974  */
00975 static HRESULT WINAPI OLEPictureImpl_IsDirty(
00976   IPersistStream* iface)
00977 {
00978   OLEPictureImpl *This = impl_from_IPersistStream(iface);
00979   FIXME("(%p),stub!\n",This);
00980   return E_NOTIMPL;
00981 }
00982 
00983 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
00984 {
00985     BITMAPFILEHEADER    *bfh = (BITMAPFILEHEADER*)xbuf;
00986     BITMAPINFO      *bi = (BITMAPINFO*)(bfh+1);
00987     HDC         hdcref;
00988 
00989     /* Does not matter whether this is a coreheader or not, we only use
00990      * components which are in both
00991      */
00992     hdcref = GetDC(0);
00993     This->desc.u.bmp.hbitmap = CreateDIBitmap(
00994     hdcref,
00995     &(bi->bmiHeader),
00996     CBM_INIT,
00997     xbuf+bfh->bfOffBits,
00998     bi,
00999        DIB_RGB_COLORS
01000     );
01001     ReleaseDC(0, hdcref);
01002     if (This->desc.u.bmp.hbitmap == 0)
01003         return E_FAIL;
01004     This->desc.picType = PICTYPE_BITMAP;
01005     OLEPictureImpl_SetBitmap(This);
01006     return S_OK;
01007 }
01008 
01009 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
01010 {
01011     HRESULT hr;
01012     BITMAPINFOHEADER bih;
01013     HDC hdcref;
01014     UINT width, height;
01015     UINT stride, buffersize;
01016     LPBYTE bits=NULL;
01017     WICRect rc;
01018     IWICBitmapSource *real_source;
01019     UINT x, y;
01020     COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
01021     BOOL has_alpha=FALSE;
01022 
01023     hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
01024     if (FAILED(hr)) return hr;
01025 
01026     hr = IWICBitmapSource_GetSize(real_source, &width, &height);
01027     if (FAILED(hr)) goto end;
01028 
01029     bih.biSize = sizeof(bih);
01030     bih.biWidth = width;
01031     bih.biHeight = -height;
01032     bih.biPlanes = 1;
01033     bih.biBitCount = 32;
01034     bih.biCompression = BI_RGB;
01035     bih.biSizeImage = 0;
01036     bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
01037     bih.biYPelsPerMeter = 4085;
01038     bih.biClrUsed = 0;
01039     bih.biClrImportant = 0;
01040 
01041     stride = 4 * width;
01042     buffersize = stride * height;
01043 
01044     bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
01045     if (!bits)
01046     {
01047         hr = E_OUTOFMEMORY;
01048         goto end;
01049     }
01050 
01051     rc.X = 0;
01052     rc.Y = 0;
01053     rc.Width = width;
01054     rc.Height = height;
01055     hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
01056     if (FAILED(hr))
01057         goto end;
01058 
01059     hdcref = GetDC(0);
01060     This->desc.u.bmp.hbitmap = CreateDIBitmap(
01061         hdcref,
01062         &bih,
01063         CBM_INIT,
01064         bits,
01065         (BITMAPINFO*)&bih,
01066         DIB_RGB_COLORS);
01067 
01068     if (This->desc.u.bmp.hbitmap == 0)
01069     {
01070         hr = E_FAIL;
01071         ReleaseDC(0, hdcref);
01072         goto end;
01073     }
01074 
01075     This->desc.picType = PICTYPE_BITMAP;
01076     OLEPictureImpl_SetBitmap(This);
01077 
01078     /* set transparent pixels to black, all others to white */
01079     for(y = 0; y < height; y++){
01080         for(x = 0; x < width; x++){
01081             DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
01082             if((*pixel & 0x80000000) == 0)
01083             {
01084                 has_alpha = TRUE;
01085                 *pixel = black;
01086             }
01087             else
01088                 *pixel = white;
01089         }
01090     }
01091 
01092     if (has_alpha)
01093     {
01094         HDC hdcBmp, hdcXor, hdcMask;
01095         HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
01096 
01097         This->hbmXor = CreateDIBitmap(
01098             hdcref,
01099             &bih,
01100             CBM_INIT,
01101             bits,
01102             (BITMAPINFO*)&bih,
01103             DIB_RGB_COLORS
01104         );
01105 
01106         This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
01107         hdcBmp = CreateCompatibleDC(NULL);
01108         hdcXor = CreateCompatibleDC(NULL);
01109         hdcMask = CreateCompatibleDC(NULL);
01110 
01111         hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
01112         hbmoldXor = SelectObject(hdcXor,This->hbmXor);
01113         hbmoldMask = SelectObject(hdcMask,This->hbmMask);
01114 
01115         SetBkColor(hdcXor,black);
01116         BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
01117         BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
01118 
01119         SelectObject(hdcBmp,hbmoldBmp);
01120         SelectObject(hdcXor,hbmoldXor);
01121         SelectObject(hdcMask,hbmoldMask);
01122 
01123         DeleteDC(hdcBmp);
01124         DeleteDC(hdcXor);
01125         DeleteDC(hdcMask);
01126     }
01127 
01128     ReleaseDC(0, hdcref);
01129 
01130 end:
01131     HeapFree(GetProcessHeap(), 0, bits);
01132     IWICBitmapSource_Release(real_source);
01133     return hr;
01134 }
01135 
01136 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
01137 {
01138     HRESULT hr;
01139     IWICImagingFactory *factory;
01140     IWICBitmapDecoder *decoder;
01141     IWICBitmapFrameDecode *framedecode;
01142     HRESULT initresult;
01143     IWICStream *stream;
01144 
01145     initresult = CoInitialize(NULL);
01146 
01147     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
01148         &IID_IWICImagingFactory, (void**)&factory);
01149     if (SUCCEEDED(hr)) /* created factory */
01150     {
01151         hr = IWICImagingFactory_CreateStream(factory, &stream);
01152         IWICImagingFactory_Release(factory);
01153     }
01154 
01155     if (SUCCEEDED(hr)) /* created stream */
01156     {
01157         hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
01158 
01159         if (SUCCEEDED(hr)) /* initialized stream */
01160         {
01161             hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
01162                 &IID_IWICBitmapDecoder, (void**)&decoder);
01163             if (SUCCEEDED(hr)) /* created decoder */
01164             {
01165                 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
01166 
01167                 if (SUCCEEDED(hr)) /* initialized decoder */
01168                     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
01169 
01170                 IWICBitmapDecoder_Release(decoder);
01171             }
01172         }
01173 
01174         IWICStream_Release(stream);
01175     }
01176 
01177     if (SUCCEEDED(hr)) /* got framedecode */
01178     {
01179         hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
01180         IWICBitmapFrameDecode_Release(framedecode);
01181     }
01182 
01183     if (SUCCEEDED(initresult)) CoUninitialize();
01184     return hr;
01185 }
01186 
01187 /*****************************************************
01188 *   start of Icon-specific code
01189 */
01190 
01191 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
01192 {
01193     HICON hicon;
01194     CURSORICONFILEDIR   *cifd = (CURSORICONFILEDIR*)xbuf;
01195     HDC hdcRef;
01196     int i;
01197 
01198     /*
01199     FIXME("icon.idReserved=%d\n",cifd->idReserved);
01200     FIXME("icon.idType=%d\n",cifd->idType);
01201     FIXME("icon.idCount=%d\n",cifd->idCount);
01202 
01203     for (i=0;i<cifd->idCount;i++) {
01204     FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
01205     FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
01206     FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
01207     FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
01208     FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
01209     FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
01210     FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
01211     FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
01212     }
01213     */
01214     i=0;
01215     /* If we have more than one icon, try to find the best.
01216      * this currently means '32 pixel wide'.
01217      */
01218     if (cifd->idCount!=1) {
01219     for (i=0;i<cifd->idCount;i++) {
01220         if (cifd->idEntries[i].bWidth == 32)
01221         break;
01222     }
01223     if (i==cifd->idCount) i=0;
01224     }
01225 
01226     hicon = CreateIconFromResourceEx(
01227         xbuf+cifd->idEntries[i].dwDIBOffset,
01228         cifd->idEntries[i].dwDIBSize,
01229         TRUE, /* is icon */
01230         0x00030000,
01231         cifd->idEntries[i].bWidth,
01232         cifd->idEntries[i].bHeight,
01233         0
01234     );
01235     if (!hicon) {
01236     ERR("CreateIcon failed.\n");
01237     return E_FAIL;
01238     } else {
01239     This->desc.picType = PICTYPE_ICON;
01240     This->desc.u.icon.hicon = hicon;
01241     This->origWidth = cifd->idEntries[i].bWidth;
01242     This->origHeight = cifd->idEntries[i].bHeight;
01243     hdcRef = CreateCompatibleDC(0);
01244     This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
01245     This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
01246     DeleteDC(hdcRef);
01247     return S_OK;
01248     }
01249 }
01250 
01251 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
01252                                               const BYTE *data, ULONG size)
01253 {
01254     HENHMETAFILE hemf;
01255     ENHMETAHEADER hdr;
01256 
01257     hemf = SetEnhMetaFileBits(size, data);
01258     if (!hemf) return E_FAIL;
01259 
01260     GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
01261 
01262     This->desc.picType = PICTYPE_ENHMETAFILE;
01263     This->desc.u.emf.hemf = hemf;
01264 
01265     This->origWidth = 0;
01266     This->origHeight = 0;
01267     This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
01268     This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
01269 
01270     return S_OK;
01271 }
01272 
01273 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
01274                                       const BYTE *data, ULONG size)
01275 {
01276     const APM_HEADER *header = (const APM_HEADER *)data;
01277     HMETAFILE hmf;
01278 
01279     if (size < sizeof(APM_HEADER))
01280         return E_FAIL;
01281     if (header->key != 0x9ac6cdd7)
01282         return E_FAIL;
01283 
01284     /* SetMetaFileBitsEx performs data check on its own */
01285     hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
01286     if (!hmf) return E_FAIL;
01287 
01288     This->desc.picType = PICTYPE_METAFILE;
01289     This->desc.u.wmf.hmeta = hmf;
01290     This->desc.u.wmf.xExt = 0;
01291     This->desc.u.wmf.yExt = 0;
01292 
01293     This->origWidth = 0;
01294     This->origHeight = 0;
01295     This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
01296     This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
01297     return S_OK;
01298 }
01299 
01300 /************************************************************************
01301  * BITMAP FORMAT FLAGS -
01302  *   Flags that differentiate between different types of bitmaps.
01303  */
01304 
01305 #define BITMAP_FORMAT_BMP   0x4d42 /* "BM" */
01306 #define BITMAP_FORMAT_JPEG  0xd8ff
01307 #define BITMAP_FORMAT_GIF   0x4947
01308 #define BITMAP_FORMAT_PNG   0x5089
01309 #define BITMAP_FORMAT_APM   0xcdd7
01310 
01311 /************************************************************************
01312  * OLEPictureImpl_IPersistStream_Load (IUnknown)
01313  *
01314  * Loads the binary data from the IStream. Starts at current position.
01315  * There appears to be an 2 DWORD header:
01316  *  DWORD magic;
01317  *  DWORD len;
01318  *
01319  * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
01320  */
01321 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
01322   HRESULT   hr = E_FAIL;
01323   BOOL      headerisdata = FALSE;
01324   BOOL      statfailed = FALSE;
01325   ULONG     xread, toread;
01326   ULONG     headerread;
01327   BYTE      *xbuf;
01328   DWORD     header[2];
01329   WORD      magic;
01330   STATSTG       statstg;
01331   OLEPictureImpl *This = impl_from_IPersistStream(iface);
01332   
01333   TRACE("(%p,%p)\n",This,pStm);
01334 
01335   /****************************************************************************************
01336    * Part 1: Load the data
01337    */
01338   /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
01339    * out whether we do.
01340    *
01341    * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
01342    * compound file. This may explain most, if not all, of the cases of "no
01343    * header", and the header validation should take this into account.
01344    * At least in Visual Basic 6, resource streams, valid headers are
01345    *    header[0] == "lt\0\0",
01346    *    header[1] == length_of_stream.
01347    *
01348    * Also handle streams where we do not have a working "Stat" method by
01349    * reading all data until the end of the stream.
01350    */
01351   hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
01352   if (hr) {
01353       TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
01354       statfailed = TRUE;
01355       /* we will read at least 8 byte ... just right below */
01356       statstg.cbSize.QuadPart = 8;
01357   }
01358 
01359   toread = 0;
01360   headerread = 0;
01361   headerisdata = FALSE;
01362   do {
01363       hr=IStream_Read(pStm,header,8,&xread);
01364       if (hr || xread!=8) {
01365           ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
01366           return (hr?hr:E_FAIL);
01367       }
01368       headerread += xread;
01369       xread = 0;
01370       
01371       if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
01372           if (toread != 0 && toread != header[1]) 
01373               FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
01374                   toread, header[1]);
01375           toread = header[1];
01376           if (toread == 0) break;
01377       } else {
01378           if (!memcmp(&(header[0]), "GIF8",     4) ||   /* GIF header */
01379               !memcmp(&(header[0]), "BM",       2) ||   /* BMP header */
01380               !memcmp(&(header[0]), "\xff\xd8", 2) ||   /* JPEG header */
01381               (header[0] == EMR_HEADER)            ||   /* EMF header */
01382               (header[1] > statstg.cbSize.QuadPart)||   /* invalid size */
01383               (header[1]==0)
01384           ) {/* Found start of bitmap data */
01385               headerisdata = TRUE;
01386               if (toread == 0) 
01387                   toread = statstg.cbSize.QuadPart-8;
01388               else toread -= 8;
01389               xread = 8;
01390           } else {
01391               FIXME("Unknown stream header magic: %08x\n", header[0]);
01392               toread = header[1];
01393           }
01394       }
01395   } while (!headerisdata);
01396 
01397   if (statfailed) { /* we don't know the size ... read all we get */
01398       int sizeinc = 4096;
01399       int origsize = sizeinc;
01400       ULONG nread = 42;
01401 
01402       TRACE("Reading all data from stream.\n");
01403       xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
01404       if (headerisdata)
01405           memcpy (xbuf, header, 8);
01406       while (1) {
01407           while (xread < origsize) {
01408               hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
01409               xread+=nread;
01410               if (hr || !nread)
01411                   break;
01412           }
01413           if (!nread || hr) /* done, or error */
01414               break;
01415           if (xread == origsize) {
01416               origsize += sizeinc;
01417               sizeinc = 2*sizeinc; /* exponential increase */
01418               xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
01419           }
01420       }
01421       if (hr)
01422           TRACE("hr in no-stat loader case is %08x\n", hr);
01423       TRACE("loaded %d bytes.\n", xread);
01424       This->datalen = xread;
01425       This->data    = xbuf;
01426   } else {
01427       This->datalen = toread+(headerisdata?8:0);
01428       xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
01429       if (!xbuf)
01430           return E_OUTOFMEMORY;
01431 
01432       if (headerisdata)
01433           memcpy (xbuf, header, 8);
01434 
01435       while (xread < This->datalen) {
01436           ULONG nread;
01437           hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
01438           xread+=nread;
01439           if (hr || !nread)
01440               break;
01441       }
01442       if (xread != This->datalen)
01443           ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
01444   }
01445   if (This->datalen == 0) { /* Marks the "NONE" picture */
01446       This->desc.picType = PICTYPE_NONE;
01447       return S_OK;
01448   }
01449 
01450 
01451   /****************************************************************************************
01452    * Part 2: Process the loaded data
01453    */
01454 
01455   magic = xbuf[0] + (xbuf[1]<<8);
01456   This->loadtime_format = magic;
01457 
01458   switch (magic) {
01459   case BITMAP_FORMAT_GIF: /* GIF */
01460     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
01461     break;
01462   case BITMAP_FORMAT_JPEG: /* JPEG */
01463     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
01464     break;
01465   case BITMAP_FORMAT_BMP: /* Bitmap */
01466     hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
01467     break;
01468   case BITMAP_FORMAT_PNG: /* PNG */
01469     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
01470     break;
01471   case BITMAP_FORMAT_APM: /* APM */
01472     hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
01473     break;
01474   case 0x0000: { /* ICON , first word is dwReserved */
01475     hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
01476     break;
01477   }
01478   default:
01479   {
01480     unsigned int i;
01481 
01482     /* let's see if it's a EMF */
01483     hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
01484     if (hr == S_OK) break;
01485 
01486     FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
01487     hr=E_FAIL;
01488     for (i=0;i<xread+8;i++) {
01489     if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
01490     else MESSAGE("%02x ",xbuf[i-8]);
01491         if (i % 10 == 9) MESSAGE("\n");
01492     }
01493     MESSAGE("\n");
01494     break;
01495   }
01496   }
01497   This->bIsDirty = FALSE;
01498 
01499   /* FIXME: this notify is not really documented */
01500   if (hr==S_OK)
01501       OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
01502   return hr;
01503 }
01504 
01505 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
01506 {
01507     int iSuccess = 0;
01508     HDC hDC;
01509     BITMAPINFO * pInfoBitmap;
01510     int iNumPaletteEntries;
01511     unsigned char * pPixelData;
01512     BITMAPFILEHEADER * pFileHeader;
01513     BITMAPINFO * pInfoHeader;
01514 
01515     pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
01516         sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
01517 
01518     /* Find out bitmap size and padded length */
01519     hDC = GetDC(0);
01520     pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
01521     GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
01522 
01523     /* Fetch bitmap palette & pixel data */
01524 
01525     pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
01526     GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
01527 
01528     /* Calculate the total length required for the BMP data */
01529     if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
01530     iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
01531     if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
01532     } else {
01533     if (pInfoBitmap->bmiHeader.biBitCount <= 8)
01534         iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
01535     else
01536             iNumPaletteEntries = 0;
01537     }
01538     *pLength =
01539         sizeof(BITMAPFILEHEADER) +
01540         sizeof(BITMAPINFOHEADER) +
01541         iNumPaletteEntries * sizeof(RGBQUAD) +
01542         pInfoBitmap->bmiHeader.biSizeImage;
01543     *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
01544 
01545     /* Fill the BITMAPFILEHEADER */
01546     pFileHeader = *ppBuffer;
01547     pFileHeader->bfType = BITMAP_FORMAT_BMP;
01548     pFileHeader->bfSize = *pLength;
01549     pFileHeader->bfOffBits =
01550         sizeof(BITMAPFILEHEADER) +
01551         sizeof(BITMAPINFOHEADER) +
01552         iNumPaletteEntries * sizeof(RGBQUAD);
01553 
01554     /* Fill the BITMAPINFOHEADER and the palette data */
01555     pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
01556     memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
01557     memcpy(
01558         (unsigned char *)(*ppBuffer) +
01559             sizeof(BITMAPFILEHEADER) +
01560             sizeof(BITMAPINFOHEADER) +
01561             iNumPaletteEntries * sizeof(RGBQUAD),
01562         pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
01563     iSuccess = 1;
01564 
01565     HeapFree(GetProcessHeap(), 0, pPixelData);
01566     HeapFree(GetProcessHeap(), 0, pInfoBitmap);
01567     return iSuccess;
01568 }
01569 
01570 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
01571 {
01572     ICONINFO infoIcon;
01573     int iSuccess = 0;
01574 
01575     *ppBuffer = NULL; *pLength = 0;
01576     if (GetIconInfo(hIcon, &infoIcon)) {
01577         HDC hDC;
01578         BITMAPINFO * pInfoBitmap;
01579         unsigned char * pIconData = NULL;
01580         unsigned int iDataSize = 0;
01581 
01582         pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
01583 
01584         /* Find out icon size */
01585         hDC = GetDC(0);
01586         pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
01587         GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
01588         if (1) {
01589             /* Auxiliary pointers */
01590             CURSORICONFILEDIR * pIconDir;
01591             CURSORICONFILEDIRENTRY * pIconEntry;
01592             BITMAPINFOHEADER * pIconBitmapHeader;
01593             unsigned int iOffsetPalette;
01594             unsigned int iOffsetColorData;
01595             unsigned int iOffsetMaskData;
01596 
01597             unsigned int iLengthScanLineMask;
01598             unsigned int iNumEntriesPalette;
01599 
01600             iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
01601 /*
01602             FIXME("DEBUG: bitmap size is %d x %d\n",
01603                 pInfoBitmap->bmiHeader.biWidth,
01604                 pInfoBitmap->bmiHeader.biHeight);
01605             FIXME("DEBUG: bitmap bpp is %d\n",
01606                 pInfoBitmap->bmiHeader.biBitCount);
01607             FIXME("DEBUG: bitmap nplanes is %d\n",
01608                 pInfoBitmap->bmiHeader.biPlanes);
01609             FIXME("DEBUG: bitmap biSizeImage is %u\n",
01610                 pInfoBitmap->bmiHeader.biSizeImage);
01611 */
01612             /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
01613             iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
01614             pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
01615 
01616             /* Fill out the CURSORICONFILEDIR */
01617             pIconDir = (CURSORICONFILEDIR *)pIconData;
01618             pIconDir->idType = 1;
01619             pIconDir->idCount = 1;
01620 
01621             /* Fill out the CURSORICONFILEDIRENTRY */
01622             pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
01623             pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
01624             pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
01625             pIconEntry->bColorCount =
01626                 (pInfoBitmap->bmiHeader.biBitCount < 8)
01627                 ? 1 << pInfoBitmap->bmiHeader.biBitCount
01628                 : 0;
01629             pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
01630             pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
01631             pIconEntry->dwDIBSize = 0;
01632             pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
01633 
01634             /* Fill out the BITMAPINFOHEADER */
01635             pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
01636             *pIconBitmapHeader = pInfoBitmap->bmiHeader;
01637 
01638             /*  Find out whether a palette exists for the bitmap */
01639             if (    (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
01640                 ||  (pInfoBitmap->bmiHeader.biBitCount == 24)
01641                 ||  (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
01642                 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
01643                 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; 
01644             } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
01645                 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
01646                 iNumEntriesPalette = 3;
01647             } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
01648                 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
01649             } else {
01650                 iNumEntriesPalette = 0;
01651             }
01652 
01653             /*  Add bitmap size and header size to icon data size. */
01654             iOffsetPalette = iDataSize;
01655             iDataSize += iNumEntriesPalette * sizeof(DWORD);
01656             iOffsetColorData = iDataSize;
01657             iDataSize += pIconBitmapHeader->biSizeImage;
01658             iOffsetMaskData = iDataSize;
01659             iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
01660             pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
01661             pIconBitmapHeader->biHeight *= 2;
01662             pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
01663             pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
01664             pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
01665             pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
01666 
01667             /* Get the actual bitmap data from the icon bitmap */
01668             GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
01669                 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
01670             if (iNumEntriesPalette > 0) {
01671                 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
01672                     iNumEntriesPalette * sizeof(RGBQUAD));
01673             }
01674 
01675             /* Reset all values so that GetDIBits call succeeds */
01676             memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
01677             memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
01678             pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
01679 /*
01680             if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
01681                 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
01682                     pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
01683 
01684                 printf("ERROR: unable to get bitmap mask (error %u)\n",
01685                     GetLastError());
01686 
01687             }
01688 */
01689             GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
01690             GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
01691 
01692             /* Write out everything produced so far to the stream */
01693             *ppBuffer = pIconData; *pLength = iDataSize;
01694             iSuccess = 1;
01695         } else {
01696 /*
01697             printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
01698                 GetLastError());
01699 */
01700         }
01701         /*
01702             Remarks (from MSDN entry on GetIconInfo):
01703 
01704             GetIconInfo creates bitmaps for the hbmMask and hbmColor
01705             members of ICONINFO. The calling application must manage
01706             these bitmaps and delete them when they are no longer
01707             necessary.
01708          */
01709         if (hDC) ReleaseDC(0, hDC);
01710         DeleteObject(infoIcon.hbmMask);
01711         if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
01712         HeapFree(GetProcessHeap(), 0, pInfoBitmap);
01713     } else {
01714         printf("ERROR: Unable to get icon information (error %u)\n",
01715             GetLastError());
01716     }
01717     return iSuccess;
01718 }
01719 
01720 static HRESULT WINAPI OLEPictureImpl_Save(
01721   IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
01722 {
01723     HRESULT hResult = E_NOTIMPL;
01724     void * pIconData;
01725     unsigned int iDataSize;
01726     ULONG dummy;
01727     int iSerializeResult = 0;
01728     OLEPictureImpl *This = impl_from_IPersistStream(iface);
01729 
01730     TRACE("%p %p %d\n", This, pStm, fClearDirty);
01731 
01732     switch (This->desc.picType) {
01733     case PICTYPE_ICON:
01734         if (This->bIsDirty || !This->data) {
01735             if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
01736                 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
01737                 hResult = E_FAIL;
01738                 break;
01739             }
01740             HeapFree(GetProcessHeap(), 0, This->data);
01741             This->data = pIconData;
01742             This->datalen = iDataSize;
01743         }
01744         if (This->loadtime_magic != 0xdeadbeef) {
01745             DWORD header[2];
01746 
01747             header[0] = This->loadtime_magic;
01748             header[1] = This->datalen;
01749             IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
01750         }
01751         IStream_Write(pStm, This->data, This->datalen, &dummy);
01752 
01753         hResult = S_OK;
01754         break;
01755     case PICTYPE_BITMAP:
01756         if (This->bIsDirty) {
01757             switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
01758             case BITMAP_FORMAT_BMP:
01759                 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
01760                 break;
01761             case BITMAP_FORMAT_JPEG:
01762                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
01763                 break;
01764             case BITMAP_FORMAT_GIF:
01765                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
01766                 break;
01767             case BITMAP_FORMAT_PNG:
01768                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
01769                 break;
01770             default:
01771                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
01772                 break;
01773             }
01774             if (iSerializeResult) {
01775                 /*
01776                 if (This->loadtime_magic != 0xdeadbeef) {
01777                 */
01778                 if (1) {
01779                     DWORD header[2];
01780 
01781                     header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
01782                     header[1] = iDataSize;
01783                     IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
01784                 }
01785                 IStream_Write(pStm, pIconData, iDataSize, &dummy);
01786 
01787                 HeapFree(GetProcessHeap(), 0, This->data);
01788                 This->data = pIconData;
01789                 This->datalen = iDataSize;
01790                 hResult = S_OK;
01791             }
01792         } else {
01793             /*
01794             if (This->loadtime_magic != 0xdeadbeef) {
01795             */
01796             if (1) {
01797                 DWORD header[2];
01798 
01799                 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
01800                 header[1] = This->datalen;
01801                 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
01802             }
01803             IStream_Write(pStm, This->data, This->datalen, &dummy);
01804             hResult = S_OK;
01805         }
01806         break;
01807     case PICTYPE_METAFILE:
01808         FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
01809         break;
01810     case PICTYPE_ENHMETAFILE:
01811         FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
01812         break;
01813     default:
01814         FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
01815         break;
01816     }
01817     if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
01818     return hResult;
01819 }
01820 
01821 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
01822   IPersistStream* iface,ULARGE_INTEGER*pcbSize)
01823 {
01824   OLEPictureImpl *This = impl_from_IPersistStream(iface);
01825   FIXME("(%p,%p),stub!\n",This,pcbSize);
01826   return E_NOTIMPL;
01827 }
01828 
01829 
01830 /************************************************************************
01831  *    IDispatch
01832  */
01833 
01834 /************************************************************************
01835  * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
01836  *
01837  * See Windows documentation for more details on IUnknown methods.
01838  */
01839 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
01840   IDispatch* iface,
01841   REFIID     riid,
01842   VOID**     ppvoid)
01843 {
01844   OLEPictureImpl *This = impl_from_IDispatch(iface);
01845 
01846   return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
01847 }
01848 
01849 /************************************************************************
01850  * OLEPictureImpl_IDispatch_AddRef (IUnknown)
01851  *
01852  * See Windows documentation for more details on IUnknown methods.
01853  */
01854 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
01855   IDispatch* iface)
01856 {
01857   OLEPictureImpl *This = impl_from_IDispatch(iface);
01858 
01859   return IPicture_AddRef((IPicture *)This);
01860 }
01861 
01862 /************************************************************************
01863  * OLEPictureImpl_IDispatch_Release (IUnknown)
01864  *
01865  * See Windows documentation for more details on IUnknown methods.
01866  */
01867 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
01868   IDispatch* iface)
01869 {
01870   OLEPictureImpl *This = impl_from_IDispatch(iface);
01871 
01872   return IPicture_Release((IPicture *)This);
01873 }
01874 
01875 /************************************************************************
01876  * OLEPictureImpl_GetTypeInfoCount (IDispatch)
01877  *
01878  * See Windows documentation for more details on IDispatch methods.
01879  */
01880 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
01881   IDispatch*    iface,
01882   unsigned int* pctinfo)
01883 {
01884   TRACE("(%p)\n", pctinfo);
01885 
01886   *pctinfo = 1;
01887 
01888   return S_OK;
01889 }
01890 
01891 /************************************************************************
01892  * OLEPictureImpl_GetTypeInfo (IDispatch)
01893  *
01894  * See Windows documentation for more details on IDispatch methods.
01895  */
01896 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
01897   IDispatch*  iface,
01898   UINT      iTInfo,
01899   LCID        lcid,
01900   ITypeInfo** ppTInfo)
01901 {
01902   static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
01903   ITypeLib *tl;
01904   HRESULT hres;
01905 
01906   TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
01907 
01908   if (iTInfo != 0)
01909     return E_FAIL;
01910 
01911   hres = LoadTypeLib(stdole2tlb, &tl);
01912   if (FAILED(hres))
01913   {
01914     ERR("Could not load stdole2.tlb\n");
01915     return hres;
01916   }
01917 
01918   hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
01919   if (FAILED(hres))
01920     ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
01921 
01922   return hres;
01923 }
01924 
01925 /************************************************************************
01926  * OLEPictureImpl_GetIDsOfNames (IDispatch)
01927  *
01928  * See Windows documentation for more details on IDispatch methods.
01929  */
01930 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
01931   IDispatch*  iface,
01932   REFIID      riid,
01933   LPOLESTR* rgszNames,
01934   UINT      cNames,
01935   LCID        lcid,
01936   DISPID*     rgDispId)
01937 {
01938   ITypeInfo * pTInfo;
01939   HRESULT hres;
01940 
01941   TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
01942         rgszNames, cNames, (int)lcid, rgDispId);
01943 
01944   if (cNames == 0)
01945   {
01946     return E_INVALIDARG;
01947   }
01948   else
01949   {
01950     /* retrieve type information */
01951     hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
01952 
01953     if (FAILED(hres))
01954     {
01955       ERR("GetTypeInfo failed.\n");
01956       return hres;
01957     }
01958 
01959     /* convert names to DISPIDs */
01960     hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
01961     ITypeInfo_Release(pTInfo);
01962 
01963     return hres;
01964   }
01965 }
01966 
01967 /************************************************************************
01968  * OLEPictureImpl_Invoke (IDispatch)
01969  *
01970  * See Windows documentation for more details on IDispatch methods.
01971  */
01972 static HRESULT WINAPI OLEPictureImpl_Invoke(
01973   IDispatch*  iface,
01974   DISPID      dispIdMember,
01975   REFIID      riid,
01976   LCID        lcid,
01977   WORD        wFlags,
01978   DISPPARAMS* pDispParams,
01979   VARIANT*    pVarResult,
01980   EXCEPINFO*  pExepInfo,
01981   UINT*     puArgErr)
01982 {
01983   OLEPictureImpl *This = impl_from_IDispatch(iface);
01984 
01985   /* validate parameters */
01986 
01987   if (!IsEqualIID(riid, &IID_NULL))
01988   {
01989     ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
01990     return DISP_E_UNKNOWNNAME;
01991   }
01992 
01993   if (!pDispParams)
01994   {
01995     ERR("null pDispParams not allowed\n");
01996     return DISP_E_PARAMNOTOPTIONAL;
01997   }
01998 
01999   if (wFlags & DISPATCH_PROPERTYGET)
02000   {
02001     if (pDispParams->cArgs != 0)
02002     {
02003       ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
02004       return DISP_E_BADPARAMCOUNT;
02005     }
02006     if (!pVarResult)
02007     {
02008       ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
02009       return DISP_E_PARAMNOTOPTIONAL;
02010     }
02011   }
02012   else if (wFlags & DISPATCH_PROPERTYPUT)
02013   {
02014     if (pDispParams->cArgs != 1)
02015     {
02016       ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
02017       return DISP_E_BADPARAMCOUNT;
02018     }
02019   }
02020 
02021   switch (dispIdMember)
02022   {
02023   case DISPID_PICT_HANDLE:
02024     if (wFlags & DISPATCH_PROPERTYGET)
02025     {
02026       TRACE("DISPID_PICT_HANDLE\n");
02027       V_VT(pVarResult) = VT_I4;
02028       return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
02029     }
02030     break;
02031   case DISPID_PICT_HPAL:
02032     if (wFlags & DISPATCH_PROPERTYGET)
02033     {
02034       TRACE("DISPID_PICT_HPAL\n");
02035       V_VT(pVarResult) = VT_I4;
02036       return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
02037     }
02038     else if (wFlags & DISPATCH_PROPERTYPUT)
02039     {
02040       VARIANTARG vararg;
02041       HRESULT hr;
02042       TRACE("DISPID_PICT_HPAL\n");
02043 
02044       VariantInit(&vararg);
02045       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
02046       if (FAILED(hr))
02047         return hr;
02048 
02049       hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
02050 
02051       VariantClear(&vararg);
02052       return hr;
02053     }
02054     break;
02055   case DISPID_PICT_TYPE:
02056     if (wFlags & DISPATCH_PROPERTYGET)
02057     {
02058       TRACE("DISPID_PICT_TYPE\n");
02059       V_VT(pVarResult) = VT_I2;
02060       return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
02061     }
02062     break;
02063   case DISPID_PICT_WIDTH:
02064     if (wFlags & DISPATCH_PROPERTYGET)
02065     {
02066       TRACE("DISPID_PICT_WIDTH\n");
02067       V_VT(pVarResult) = VT_I4;
02068       return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
02069     }
02070     break;
02071   case DISPID_PICT_HEIGHT:
02072     if (wFlags & DISPATCH_PROPERTYGET)
02073     {
02074       TRACE("DISPID_PICT_HEIGHT\n");
02075       V_VT(pVarResult) = VT_I4;
02076       return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
02077     }
02078     break;
02079   }
02080 
02081   ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
02082   return DISP_E_MEMBERNOTFOUND;
02083 }
02084 
02085 
02086 static const IPictureVtbl OLEPictureImpl_VTable =
02087 {
02088   OLEPictureImpl_QueryInterface,
02089   OLEPictureImpl_AddRef,
02090   OLEPictureImpl_Release,
02091   OLEPictureImpl_get_Handle,
02092   OLEPictureImpl_get_hPal,
02093   OLEPictureImpl_get_Type,
02094   OLEPictureImpl_get_Width,
02095   OLEPictureImpl_get_Height,
02096   OLEPictureImpl_Render,
02097   OLEPictureImpl_set_hPal,
02098   OLEPictureImpl_get_CurDC,
02099   OLEPictureImpl_SelectPicture,
02100   OLEPictureImpl_get_KeepOriginalFormat,
02101   OLEPictureImpl_put_KeepOriginalFormat,
02102   OLEPictureImpl_PictureChanged,
02103   OLEPictureImpl_SaveAsFile,
02104   OLEPictureImpl_get_Attributes
02105 };
02106 
02107 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
02108 {
02109   OLEPictureImpl_IDispatch_QueryInterface,
02110   OLEPictureImpl_IDispatch_AddRef,
02111   OLEPictureImpl_IDispatch_Release,
02112   OLEPictureImpl_GetTypeInfoCount,
02113   OLEPictureImpl_GetTypeInfo,
02114   OLEPictureImpl_GetIDsOfNames,
02115   OLEPictureImpl_Invoke
02116 };
02117 
02118 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
02119 {
02120   OLEPictureImpl_IPersistStream_QueryInterface,
02121   OLEPictureImpl_IPersistStream_AddRef,
02122   OLEPictureImpl_IPersistStream_Release,
02123   OLEPictureImpl_GetClassID,
02124   OLEPictureImpl_IsDirty,
02125   OLEPictureImpl_Load,
02126   OLEPictureImpl_Save,
02127   OLEPictureImpl_GetSizeMax
02128 };
02129 
02130 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
02131 {
02132   OLEPictureImpl_IConnectionPointContainer_QueryInterface,
02133   OLEPictureImpl_IConnectionPointContainer_AddRef,
02134   OLEPictureImpl_IConnectionPointContainer_Release,
02135   OLEPictureImpl_EnumConnectionPoints,
02136   OLEPictureImpl_FindConnectionPoint
02137 };
02138 
02139 /***********************************************************************
02140  * OleCreatePictureIndirect (OLEAUT32.419)
02141  */
02142 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
02143                     BOOL fOwn, LPVOID *ppvObj )
02144 {
02145   OLEPictureImpl* newPict = NULL;
02146   HRESULT      hr         = S_OK;
02147 
02148   TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
02149 
02150   /*
02151    * Sanity check
02152    */
02153   if (ppvObj==0)
02154     return E_POINTER;
02155 
02156   *ppvObj = NULL;
02157 
02158   /*
02159    * Try to construct a new instance of the class.
02160    */
02161   newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
02162 
02163   if (newPict == NULL)
02164     return E_OUTOFMEMORY;
02165 
02166   /*
02167    * Make sure it supports the interface required by the caller.
02168    */
02169   hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
02170 
02171   /*
02172    * Release the reference obtained in the constructor. If
02173    * the QueryInterface was unsuccessful, it will free the class.
02174    */
02175   IPicture_Release((IPicture*)newPict);
02176 
02177   return hr;
02178 }
02179 
02180 
02181 /***********************************************************************
02182  * OleLoadPicture (OLEAUT32.418)
02183  */
02184 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
02185                     REFIID riid, LPVOID *ppvObj )
02186 {
02187   LPPERSISTSTREAM ps;
02188   IPicture  *newpic;
02189   HRESULT hr;
02190 
02191   TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
02192     lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
02193 
02194   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
02195   if (hr)
02196     return hr;
02197   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
02198   if (hr) {
02199       ERR("Could not get IPersistStream iface from Ole Picture?\n");
02200       IPicture_Release(newpic);
02201       *ppvObj = NULL;
02202       return hr;
02203   }
02204   hr = IPersistStream_Load(ps,lpstream);
02205   IPersistStream_Release(ps);
02206   if (FAILED(hr))
02207   {
02208       ERR("IPersistStream_Load failed\n");
02209       IPicture_Release(newpic);
02210       *ppvObj = NULL;
02211       return hr;
02212   }
02213   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
02214   if (hr)
02215       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
02216   IPicture_Release(newpic);
02217   return hr;
02218 }
02219 
02220 /***********************************************************************
02221  * OleLoadPictureEx (OLEAUT32.401)
02222  */
02223 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
02224                     REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
02225 {
02226   LPPERSISTSTREAM ps;
02227   IPicture  *newpic;
02228   HRESULT hr;
02229 
02230   FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
02231     lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
02232 
02233   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
02234   if (hr)
02235     return hr;
02236   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
02237   if (hr) {
02238       ERR("Could not get IPersistStream iface from Ole Picture?\n");
02239       IPicture_Release(newpic);
02240       *ppvObj = NULL;
02241       return hr;
02242   }
02243   hr = IPersistStream_Load(ps,lpstream);
02244   IPersistStream_Release(ps);
02245   if (FAILED(hr))
02246   {
02247       ERR("IPersistStream_Load failed\n");
02248       IPicture_Release(newpic);
02249       *ppvObj = NULL;
02250       return hr;
02251   }
02252   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
02253   if (hr)
02254       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
02255   IPicture_Release(newpic);
02256   return hr;
02257 }
02258 
02259 /***********************************************************************
02260  * OleLoadPicturePath (OLEAUT32.424)
02261  */
02262 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
02263         DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
02264         LPVOID *ppvRet )
02265 {
02266   static const WCHAR file[] = { 'f','i','l','e',':',0 };
02267   IPicture *ipicture;
02268   HANDLE hFile;
02269   DWORD dwFileSize;
02270   HGLOBAL hGlobal = NULL;
02271   DWORD dwBytesRead = 0;
02272   IStream *stream;
02273   BOOL bRead;
02274   IPersistStream *pStream;
02275   HRESULT hRes;
02276   HRESULT init_res;
02277   WCHAR *file_candidate;
02278   WCHAR path_buf[MAX_PATH];
02279 
02280   TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
02281         debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
02282         debugstr_guid(riid), ppvRet);
02283 
02284   if (!szURLorPath || !ppvRet)
02285       return E_INVALIDARG;
02286 
02287   *ppvRet = NULL;
02288 
02289   /* Convert file URLs to DOS paths. */
02290   if (strncmpW(szURLorPath, file, 5) == 0) {
02291       DWORD size;
02292       hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
02293                                 sizeof(path_buf)/sizeof(WCHAR), &size, 0);
02294       if (FAILED(hRes))
02295           return hRes;
02296 
02297       file_candidate = path_buf;
02298   }
02299   else
02300       file_candidate = szURLorPath;
02301 
02302   /* Handle candidate DOS paths separately. */
02303   if (file_candidate[1] == ':') {
02304       hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING,
02305                           0, NULL);
02306       if (hFile == INVALID_HANDLE_VALUE)
02307           return E_UNEXPECTED;
02308 
02309       dwFileSize = GetFileSize(hFile, NULL);
02310       if (dwFileSize != INVALID_FILE_SIZE )
02311       {
02312       hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
02313       if ( hGlobal)
02314       {
02315           bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
02316           if (!bRead)
02317           {
02318           GlobalFree(hGlobal);
02319           hGlobal = 0;
02320           }
02321       }
02322       }
02323       CloseHandle(hFile);
02324       
02325       if (!hGlobal)
02326       return E_UNEXPECTED;
02327 
02328       hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
02329       if (FAILED(hRes)) 
02330       {
02331       GlobalFree(hGlobal);
02332       return hRes;
02333       }
02334   } else {
02335       IMoniker *pmnk;
02336       IBindCtx *pbc;
02337 
02338       hRes = CreateBindCtx(0, &pbc);
02339       if (SUCCEEDED(hRes)) 
02340       {
02341       hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
02342       if (SUCCEEDED(hRes))
02343       {          
02344           hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
02345           IMoniker_Release(pmnk);
02346       }
02347       IBindCtx_Release(pbc);
02348       }
02349       if (FAILED(hRes))
02350       return hRes;
02351   }
02352 
02353   init_res = CoInitialize(NULL);
02354 
02355   hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
02356                           &IID_IPicture, (LPVOID*)&ipicture);
02357   if (SUCCEEDED(hRes)) {
02358       hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
02359 
02360       if (SUCCEEDED(hRes)) {
02361           hRes = IPersistStream_Load(pStream, stream);
02362 
02363           if (SUCCEEDED(hRes)) {
02364               hRes = IPicture_QueryInterface(ipicture, riid, ppvRet);
02365 
02366               if (FAILED(hRes))
02367                   ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid));
02368           }
02369           IPersistStream_Release(pStream);
02370       }
02371       IPicture_Release(ipicture);
02372   }
02373 
02374   IStream_Release(stream);
02375 
02376   if (SUCCEEDED(init_res))
02377       CoUninitialize();
02378 
02379   return hRes;
02380 }
02381 
02382 /*******************************************************************************
02383  * StdPic ClassFactory
02384  */
02385 typedef struct
02386 {
02387     /* IUnknown fields */
02388     const IClassFactoryVtbl    *lpVtbl;
02389     LONG                        ref;
02390 } IClassFactoryImpl;
02391 
02392 static HRESULT WINAPI
02393 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
02394     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
02395 
02396     FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
02397     return E_NOINTERFACE;
02398 }
02399 
02400 static ULONG WINAPI
02401 SPCF_AddRef(LPCLASSFACTORY iface) {
02402     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
02403     return InterlockedIncrement(&This->ref);
02404 }
02405 
02406 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
02407     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
02408     /* static class, won't be  freed */
02409     return InterlockedDecrement(&This->ref);
02410 }
02411 
02412 static HRESULT WINAPI SPCF_CreateInstance(
02413     LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
02414 ) {
02415     /* Creates an uninitialized picture */
02416     return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
02417 
02418 }
02419 
02420 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
02421     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
02422     FIXME("(%p)->(%d),stub!\n",This,dolock);
02423     return S_OK;
02424 }
02425 
02426 static const IClassFactoryVtbl SPCF_Vtbl = {
02427     SPCF_QueryInterface,
02428     SPCF_AddRef,
02429     SPCF_Release,
02430     SPCF_CreateInstance,
02431     SPCF_LockServer
02432 };
02433 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
02434 
02435 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }

Generated on Wed May 23 2012 04:23:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.