Get rid of the no longer used ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
[wine/multimedia.git] / dlls / oleaut32 / olepicture.c
blob795a7be1783582fe5185826876f713773588591b
1 /*
2 * OLE Picture object
4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * BUGS
25 * Support PICTYPE_BITMAP and PICTYPE_ICON, altough only bitmaps very well..
26 * Lots of methods are just stubs.
29 * NOTES (or things that msdn doesn't tell you)
31 * The width and height properties are returned in HIMETRIC units (0.01mm)
32 * IPicture::Render also uses these to select a region of the src picture.
33 * A bitmap's size is converted into these units by using the screen resolution
34 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
38 #include "config.h"
39 #include "wine/port.h"
41 #ifdef HAVE_UNISTD_H
42 # include <unistd.h>
43 #endif
44 #include <stdarg.h>
45 #include <stdio.h>
46 #include <string.h>
48 /* Must be before wine includes, the header has things conflicting with
49 * WINE headers.
51 #ifdef HAVE_GIF_LIB_H
52 # include <gif_lib.h>
53 #ifndef SONAME_LIBUNGIF
54 #define SONAME_LIBUNGIF "libungif.so"
55 #endif
56 #endif
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
60 #include "winerror.h"
61 #include "windef.h"
62 #include "winbase.h"
63 #include "wingdi.h"
64 #include "winuser.h"
65 #include "ole2.h"
66 #include "olectl.h"
67 #include "oleauto.h"
68 #include "connpt.h"
69 #include "wine/debug.h"
71 #include "wine/wingdi16.h"
72 #include "cursoricon.h"
74 #ifdef HAVE_JPEGLIB_H
75 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
76 #define XMD_H
77 #define UINT8 JPEG_UINT8
78 #define UINT16 JPEG_UINT16
79 #undef FAR
80 # include <jpeglib.h>
81 #undef UINT16
82 #ifndef SONAME_LIBJPEG
83 #define SONAME_LIBJPEG "libjpeg.so"
84 #endif
85 #endif
87 WINE_DEFAULT_DEBUG_CHANNEL(ole);
89 /*************************************************************************
90 * Declaration of implementation class
93 typedef struct OLEPictureImpl {
96 * IPicture handles IUnknown
99 IPictureVtbl *lpvtbl1;
100 IDispatchVtbl *lpvtbl2;
101 IPersistStreamVtbl *lpvtbl3;
102 IConnectionPointContainerVtbl *lpvtbl4;
104 /* Object referenece count */
105 DWORD ref;
107 /* We own the object and must destroy it ourselves */
108 BOOL fOwn;
110 /* Picture description */
111 PICTDESC desc;
113 /* These are the pixel size of a bitmap */
114 DWORD origWidth;
115 DWORD origHeight;
117 /* And these are the size of the picture converted into HIMETRIC units */
118 OLE_XSIZE_HIMETRIC himetricWidth;
119 OLE_YSIZE_HIMETRIC himetricHeight;
121 IConnectionPoint *pCP;
123 BOOL keepOrigFormat;
124 HDC hDCCur;
126 /* Bitmap transparency mask */
127 HBITMAP hbmMask;
128 COLORREF rgbTrans;
130 /* data */
131 void* data;
132 int datalen;
133 } OLEPictureImpl;
136 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
138 #define ICOM_THIS_From_IDispatch(impl, name) \
139 impl *This = (impl*)(((char*)name)-sizeof(void*));
140 #define ICOM_THIS_From_IPersistStream(impl, name) \
141 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
142 #define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
143 impl *This = (impl*)(((char*)name)-3*sizeof(void*));
146 * Predeclare VTables. They get initialized at the end.
148 static IPictureVtbl OLEPictureImpl_VTable;
149 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
150 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
151 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
153 /***********************************************************************
154 * Implementation of the OLEPictureImpl class.
157 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
158 BITMAP bm;
159 HDC hdcRef;
161 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
162 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
163 ERR("GetObject fails\n");
164 return;
166 This->origWidth = bm.bmWidth;
167 This->origHeight = bm.bmHeight;
168 /* The width and height are stored in HIMETRIC units (0.01 mm),
169 so we take our pixel width divide by pixels per inch and
170 multiply by 25.4 * 100 */
171 /* Should we use GetBitmapDimension if available? */
172 hdcRef = CreateCompatibleDC(0);
173 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
174 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
175 DeleteDC(hdcRef);
178 /************************************************************************
179 * OLEPictureImpl_Construct
181 * This method will construct a new instance of the OLEPictureImpl
182 * class.
184 * The caller of this method must release the object when it's
185 * done with it.
187 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
189 OLEPictureImpl* newObject = 0;
191 if (pictDesc)
192 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
195 * Allocate space for the object.
197 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
199 if (newObject==0)
200 return newObject;
203 * Initialize the virtual function table.
205 newObject->lpvtbl1 = &OLEPictureImpl_VTable;
206 newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
207 newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
208 newObject->lpvtbl4 = &OLEPictureImpl_IConnectionPointContainer_VTable;
210 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
213 * Start with one reference count. The caller of this function
214 * must release the interface pointer when it is done.
216 newObject->ref = 1;
217 newObject->hDCCur = 0;
219 newObject->fOwn = fOwn;
221 /* dunno about original value */
222 newObject->keepOrigFormat = TRUE;
224 newObject->hbmMask = NULL;
226 if (pictDesc) {
227 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
228 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
230 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
233 switch(pictDesc->picType) {
234 case PICTYPE_BITMAP:
235 OLEPictureImpl_SetBitmap(newObject);
236 break;
238 case PICTYPE_METAFILE:
239 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
240 newObject->himetricWidth = pictDesc->u.wmf.xExt;
241 newObject->himetricHeight = pictDesc->u.wmf.yExt;
242 break;
244 case PICTYPE_NONE:
245 /* not sure what to do here */
246 newObject->himetricWidth = newObject->himetricHeight = 0;
247 break;
249 case PICTYPE_ICON:
250 case PICTYPE_ENHMETAFILE:
251 default:
252 FIXME("Unsupported type %d\n", pictDesc->picType);
253 newObject->himetricWidth = newObject->himetricHeight = 0;
254 break;
256 } else {
257 newObject->desc.picType = PICTYPE_UNINITIALIZED;
260 TRACE("returning %p\n", newObject);
261 return newObject;
264 /************************************************************************
265 * OLEPictureImpl_Destroy
267 * This method is called by the Release method when the reference
268 * count goes down to 0. It will free all resources used by
269 * this object. */
270 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
272 TRACE("(%p)\n", Obj);
274 if(Obj->fOwn) { /* We need to destroy the picture */
275 switch(Obj->desc.picType) {
276 case PICTYPE_BITMAP:
277 DeleteObject(Obj->desc.u.bmp.hbitmap);
278 break;
279 case PICTYPE_METAFILE:
280 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
281 break;
282 case PICTYPE_ICON:
283 DestroyIcon(Obj->desc.u.icon.hicon);
284 break;
285 case PICTYPE_ENHMETAFILE:
286 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
287 break;
288 default:
289 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
290 break;
293 if (Obj->data) HeapFree(GetProcessHeap(), 0, Obj->data);
294 HeapFree(GetProcessHeap(), 0, Obj);
297 static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
299 /************************************************************************
300 * OLEPictureImpl_QueryInterface (IUnknown)
302 * See Windows documentation for more details on IUnknown methods.
304 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
305 IPicture* iface,
306 REFIID riid,
307 void** ppvObject)
309 ICOM_THIS(OLEPictureImpl, iface);
310 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
313 * Perform a sanity check on the parameters.
315 if ( (This==0) || (ppvObject==0) )
316 return E_INVALIDARG;
319 * Initialize the return parameter.
321 *ppvObject = 0;
324 * Compare the riid with the interface IDs implemented by this object.
326 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
328 *ppvObject = (IPicture*)This;
330 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
332 *ppvObject = (IPicture*)This;
334 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
336 *ppvObject = (IDispatch*)&(This->lpvtbl2);
338 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
340 *ppvObject = (IDispatch*)&(This->lpvtbl2);
342 else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
344 *ppvObject = (IPersistStream*)&(This->lpvtbl3);
346 else if (memcmp(&IID_IConnectionPointContainer, riid, sizeof(IID_IConnectionPointContainer)) == 0)
348 *ppvObject = (IConnectionPointContainer*)&(This->lpvtbl4);
351 * Check that we obtained an interface.
353 if ((*ppvObject)==0)
355 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
356 return E_NOINTERFACE;
360 * Query Interface always increases the reference count by one when it is
361 * successful
363 OLEPictureImpl_AddRef((IPicture*)This);
365 return S_OK;
367 /***********************************************************************
368 * OLEPicture_SendNotify (internal)
370 * Sends notification messages of changed properties to any interested
371 * connections.
373 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
375 IEnumConnections *pEnum;
376 CONNECTDATA CD;
378 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
379 return;
380 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
381 IPropertyNotifySink *sink;
383 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
384 IPropertyNotifySink_OnChanged(sink, dispID);
385 IPropertyNotifySink_Release(sink);
386 IUnknown_Release(CD.pUnk);
388 IEnumConnections_Release(pEnum);
389 return;
392 /************************************************************************
393 * OLEPictureImpl_AddRef (IUnknown)
395 * See Windows documentation for more details on IUnknown methods.
397 static ULONG WINAPI OLEPictureImpl_AddRef(
398 IPicture* iface)
400 ICOM_THIS(OLEPictureImpl, iface);
401 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
402 This->ref++;
404 return This->ref;
407 /************************************************************************
408 * OLEPictureImpl_Release (IUnknown)
410 * See Windows documentation for more details on IUnknown methods.
412 static ULONG WINAPI OLEPictureImpl_Release(
413 IPicture* iface)
415 ICOM_THIS(OLEPictureImpl, iface);
416 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
419 * Decrease the reference count on this object.
421 This->ref--;
424 * If the reference count goes down to 0, perform suicide.
426 if (This->ref==0)
428 OLEPictureImpl_Destroy(This);
430 return 0;
433 return This->ref;
437 /************************************************************************
438 * OLEPictureImpl_get_Handle
440 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
441 OLE_HANDLE *phandle)
443 ICOM_THIS(OLEPictureImpl, iface);
444 TRACE("(%p)->(%p)\n", This, phandle);
445 switch(This->desc.picType) {
446 case PICTYPE_BITMAP:
447 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
448 break;
449 case PICTYPE_METAFILE:
450 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
451 break;
452 case PICTYPE_ICON:
453 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
454 break;
455 case PICTYPE_ENHMETAFILE:
456 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
457 break;
458 default:
459 FIXME("Unimplemented type %d\n", This->desc.picType);
460 return E_NOTIMPL;
462 TRACE("returning handle %08x\n", *phandle);
463 return S_OK;
466 /************************************************************************
467 * OLEPictureImpl_get_hPal
469 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
470 OLE_HANDLE *phandle)
472 ICOM_THIS(OLEPictureImpl, iface);
473 FIXME("(%p)->(%p): stub\n", This, phandle);
474 return E_NOTIMPL;
477 /************************************************************************
478 * OLEPictureImpl_get_Type
480 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
481 short *ptype)
483 ICOM_THIS(OLEPictureImpl, iface);
484 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
485 *ptype = This->desc.picType;
486 return S_OK;
489 /************************************************************************
490 * OLEPictureImpl_get_Width
492 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
493 OLE_XSIZE_HIMETRIC *pwidth)
495 ICOM_THIS(OLEPictureImpl, iface);
496 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
497 *pwidth = This->himetricWidth;
498 return S_OK;
501 /************************************************************************
502 * OLEPictureImpl_get_Height
504 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
505 OLE_YSIZE_HIMETRIC *pheight)
507 ICOM_THIS(OLEPictureImpl, iface);
508 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
509 *pheight = This->himetricHeight;
510 return S_OK;
513 /************************************************************************
514 * OLEPictureImpl_Render
516 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
517 long x, long y, long cx, long cy,
518 OLE_XPOS_HIMETRIC xSrc,
519 OLE_YPOS_HIMETRIC ySrc,
520 OLE_XSIZE_HIMETRIC cxSrc,
521 OLE_YSIZE_HIMETRIC cySrc,
522 LPCRECT prcWBounds)
524 ICOM_THIS(OLEPictureImpl, iface);
525 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
526 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
527 if(prcWBounds)
528 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
529 prcWBounds->right, prcWBounds->bottom);
532 * While the documentation suggests this to be here (or after rendering?)
533 * it does cause an endless recursion in my sample app. -MM 20010804
534 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
537 switch(This->desc.picType) {
538 case PICTYPE_BITMAP:
540 HBITMAP hbmpOld;
541 HDC hdcBmp;
543 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
544 NB y-axis gets flipped */
546 hdcBmp = CreateCompatibleDC(0);
547 SetMapMode(hdcBmp, MM_ANISOTROPIC);
548 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
549 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
550 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
551 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
553 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
555 if (This->hbmMask) {
556 HDC hdcMask = CreateCompatibleDC(0);
557 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
559 SetMapMode(hdcMask, MM_ANISOTROPIC);
560 SetWindowOrgEx(hdcMask, 0, 0, NULL);
561 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
562 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
563 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
565 SetBkColor(hdc, RGB(255, 255, 255));
566 SetTextColor(hdc, RGB(0, 0, 0));
567 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
568 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
570 SelectObject(hdcMask, hOldbm);
571 DeleteDC(hdcMask);
572 } else
573 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
575 SelectObject(hdcBmp, hbmpOld);
576 DeleteDC(hdcBmp);
578 break;
579 case PICTYPE_ICON:
580 FIXME("Not quite correct implementation of rendering icons...\n");
581 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
582 break;
584 case PICTYPE_METAFILE:
585 case PICTYPE_ENHMETAFILE:
586 default:
587 FIXME("type %d not implemented\n", This->desc.picType);
588 return E_NOTIMPL;
590 return S_OK;
593 /************************************************************************
594 * OLEPictureImpl_set_hPal
596 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
597 OLE_HANDLE hpal)
599 ICOM_THIS(OLEPictureImpl, iface);
600 FIXME("(%p)->(%08x): stub\n", This, hpal);
601 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
602 return E_NOTIMPL;
605 /************************************************************************
606 * OLEPictureImpl_get_CurDC
608 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
609 HDC *phdc)
611 ICOM_THIS(OLEPictureImpl, iface);
612 TRACE("(%p), returning %p\n", This, This->hDCCur);
613 if (phdc) *phdc = This->hDCCur;
614 return S_OK;
617 /************************************************************************
618 * OLEPictureImpl_SelectPicture
620 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
621 HDC hdcIn,
622 HDC *phdcOut,
623 OLE_HANDLE *phbmpOut)
625 ICOM_THIS(OLEPictureImpl, iface);
626 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
627 if (This->desc.picType == PICTYPE_BITMAP) {
628 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
630 if (phdcOut)
631 *phdcOut = This->hDCCur;
632 This->hDCCur = hdcIn;
633 if (phbmpOut)
634 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
635 return S_OK;
636 } else {
637 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
638 return E_FAIL;
642 /************************************************************************
643 * OLEPictureImpl_get_KeepOriginalFormat
645 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
646 BOOL *pfKeep)
648 ICOM_THIS(OLEPictureImpl, iface);
649 TRACE("(%p)->(%p)\n", This, pfKeep);
650 if (!pfKeep)
651 return E_POINTER;
652 *pfKeep = This->keepOrigFormat;
653 return S_OK;
656 /************************************************************************
657 * OLEPictureImpl_put_KeepOriginalFormat
659 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
660 BOOL keep)
662 ICOM_THIS(OLEPictureImpl, iface);
663 TRACE("(%p)->(%d)\n", This, keep);
664 This->keepOrigFormat = keep;
665 /* FIXME: what DISPID notification here? */
666 return S_OK;
669 /************************************************************************
670 * OLEPictureImpl_PictureChanged
672 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
674 ICOM_THIS(OLEPictureImpl, iface);
675 TRACE("(%p)->()\n", This);
676 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
677 return S_OK;
680 /************************************************************************
681 * OLEPictureImpl_SaveAsFile
683 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
684 IStream *pstream,
685 BOOL SaveMemCopy,
686 LONG *pcbSize)
688 ICOM_THIS(OLEPictureImpl, iface);
689 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
690 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
693 /************************************************************************
694 * OLEPictureImpl_get_Attributes
696 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
697 DWORD *pdwAttr)
699 ICOM_THIS(OLEPictureImpl, iface);
700 TRACE("(%p)->(%p).\n", This, pdwAttr);
701 *pdwAttr = 0;
702 switch (This->desc.picType) {
703 case PICTYPE_BITMAP: break; /* not 'truely' scalable, see MSDN. */
704 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
705 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
706 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
708 return S_OK;
712 /************************************************************************
713 * IConnectionPointContainer
716 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
717 IConnectionPointContainer* iface,
718 REFIID riid,
719 VOID** ppvoid
721 ICOM_THIS_From_IConnectionPointContainer(IPicture,iface);
723 return IPicture_QueryInterface(This,riid,ppvoid);
726 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
727 IConnectionPointContainer* iface)
729 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
731 return IPicture_AddRef(This);
734 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
735 IConnectionPointContainer* iface)
737 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
739 return IPicture_Release(This);
742 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
743 IConnectionPointContainer* iface,
744 IEnumConnectionPoints** ppEnum
746 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
748 FIXME("(%p,%p), stub!\n",This,ppEnum);
749 return E_NOTIMPL;
752 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
753 IConnectionPointContainer* iface,
754 REFIID riid,
755 IConnectionPoint **ppCP
757 ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl, iface);
758 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
759 if (!ppCP)
760 return E_POINTER;
761 *ppCP = NULL;
762 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
763 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
764 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid));
765 return 0x80040200;
767 /************************************************************************
768 * IPersistStream
770 /************************************************************************
771 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
773 * See Windows documentation for more details on IUnknown methods.
775 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
776 IPersistStream* iface,
777 REFIID riid,
778 VOID** ppvoid)
780 ICOM_THIS_From_IPersistStream(IPicture, iface);
782 return IPicture_QueryInterface(This, riid, ppvoid);
785 /************************************************************************
786 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
788 * See Windows documentation for more details on IUnknown methods.
790 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
791 IPersistStream* iface)
793 ICOM_THIS_From_IPersistStream(IPicture, iface);
795 return IPicture_AddRef(This);
798 /************************************************************************
799 * OLEPictureImpl_IPersistStream_Release (IUnknown)
801 * See Windows documentation for more details on IUnknown methods.
803 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
804 IPersistStream* iface)
806 ICOM_THIS_From_IPersistStream(IPicture, iface);
808 return IPicture_Release(This);
811 /************************************************************************
812 * OLEPictureImpl_IPersistStream_GetClassID
814 static HRESULT WINAPI OLEPictureImpl_GetClassID(
815 IPersistStream* iface,CLSID* pClassID)
817 ICOM_THIS_From_IPersistStream(IPicture, iface);
818 FIXME("(%p),stub!\n",This);
819 return E_NOTIMPL;
822 /************************************************************************
823 * OLEPictureImpl_IPersistStream_IsDirty
825 static HRESULT WINAPI OLEPictureImpl_IsDirty(
826 IPersistStream* iface)
828 ICOM_THIS_From_IPersistStream(IPicture, iface);
829 FIXME("(%p),stub!\n",This);
830 return E_NOTIMPL;
833 #ifdef HAVE_JPEGLIB_H
835 static void *libjpeg_handle;
836 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
837 MAKE_FUNCPTR(jpeg_std_error);
838 MAKE_FUNCPTR(jpeg_CreateDecompress);
839 MAKE_FUNCPTR(jpeg_read_header);
840 MAKE_FUNCPTR(jpeg_start_decompress);
841 MAKE_FUNCPTR(jpeg_read_scanlines);
842 MAKE_FUNCPTR(jpeg_finish_decompress);
843 MAKE_FUNCPTR(jpeg_destroy_decompress);
844 #undef MAKE_FUNCPTR
846 static void *load_libjpeg(void)
848 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
850 #define LOAD_FUNCPTR(f) \
851 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
852 libjpeg_handle = NULL; \
853 return NULL; \
856 LOAD_FUNCPTR(jpeg_std_error);
857 LOAD_FUNCPTR(jpeg_CreateDecompress);
858 LOAD_FUNCPTR(jpeg_read_header);
859 LOAD_FUNCPTR(jpeg_start_decompress);
860 LOAD_FUNCPTR(jpeg_read_scanlines);
861 LOAD_FUNCPTR(jpeg_finish_decompress);
862 LOAD_FUNCPTR(jpeg_destroy_decompress);
863 #undef LOAD_FUNCPTR
865 return libjpeg_handle;
868 /* for the jpeg decompressor source manager. */
869 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
871 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
872 ERR("(), should not get here.\n");
873 return FALSE;
876 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
877 TRACE("Skipping %ld bytes...\n", num_bytes);
878 cinfo->src->next_input_byte += num_bytes;
879 cinfo->src->bytes_in_buffer -= num_bytes;
882 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
883 ERR("(desired=%d), should not get here.\n",desired);
884 return FALSE;
886 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
887 #endif /* HAVE_JPEGLIB_H */
889 #ifdef HAVE_GIF_LIB_H
891 static void *libungif_handle;
892 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
893 MAKE_FUNCPTR(DGifOpen);
894 MAKE_FUNCPTR(DGifSlurp);
895 MAKE_FUNCPTR(DGifCloseFile);
896 #undef MAKE_FUNCPTR
898 struct gifdata {
899 unsigned char *data;
900 unsigned int curoff;
901 unsigned int len;
904 static void *load_libungif(void)
906 if((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) {
908 #define LOAD_FUNCPTR(f) \
909 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
910 libungif_handle = NULL; \
911 return NULL; \
914 LOAD_FUNCPTR(DGifOpen);
915 LOAD_FUNCPTR(DGifSlurp);
916 LOAD_FUNCPTR(DGifCloseFile);
917 #undef LOAD_FUNCPTR
919 return libungif_handle;
922 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
923 struct gifdata *gd = (struct gifdata*)gif->UserData;
925 if (len+gd->curoff > gd->len) {
926 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
927 len = gd->len - gd->curoff;
929 memcpy(data, gd->data+gd->curoff, len);
930 gd->curoff += len;
931 return len;
934 #endif /* HAVE_GIF_LIB_H */
936 /************************************************************************
937 * OLEPictureImpl_IPersistStream_Load (IUnknown)
939 * Loads the binary data from the IStream. Starts at current position.
940 * There appears to be an 2 DWORD header:
941 * DWORD magic;
942 * DWORD len;
944 * Currently implemented: BITMAP, ICON, JPEG, GIF
946 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
947 HRESULT hr = E_FAIL;
948 ULONG xread;
949 BYTE *xbuf;
950 DWORD header[2];
951 WORD magic;
952 STATSTG statstg;
953 ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
955 TRACE("(%p,%p)\n",This,pStm);
957 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
958 * out whether we do.
960 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
961 * compound file. This may explain most, if not all, of the cases of "no header",
962 * and the header validation should take this into account. At least in Visual Basic 6,
963 * resource streams, valid headers are
964 * header[0] == "lt\0\0",
965 * header[1] == length_of_stream.
967 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
968 if (hr)
969 FIXME("Stat failed with hres %lx\n",hr);
970 hr=IStream_Read(pStm,header,8,&xread);
971 if (hr || xread!=8) {
972 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
973 return hr;
975 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
976 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
977 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
978 header[1] > statstg.cbSize.QuadPart || (header[1]==0)) {/* Incorrect header, assume none. */
979 xread = 8;
980 xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,statstg.cbSize.QuadPart);
981 memcpy(xbuf,&header,8);
982 This->datalen = statstg.cbSize.QuadPart;
983 while (xread < This->datalen) {
984 ULONG nread;
985 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
986 xread+=nread;
987 if (hr || !nread)
988 break;
990 if (xread != This->datalen)
991 FIXME("Could only read %ld of %d bytes in no-header case?\n",xread,This->datalen);
992 } else {
993 xread = 0;
994 xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
995 This->datalen = header[1];
996 while (xread < header[1]) {
997 ULONG nread;
998 hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
999 xread+=nread;
1000 if (hr || !nread)
1001 break;
1003 if (xread != header[1])
1004 FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
1006 magic = xbuf[0] + (xbuf[1]<<8);
1007 switch (magic) {
1008 case 0x4947: { /* GIF */
1009 #ifdef HAVE_GIF_LIB_H
1010 struct gifdata gd;
1011 GifFileType *gif;
1012 BITMAPINFO *bmi;
1013 HDC hdcref;
1014 LPBYTE bytes;
1015 int i,j,ret;
1016 GifImageDesc *gid;
1017 SavedImage *si;
1018 ColorMapObject *cm;
1019 int transparent = -1;
1020 ExtensionBlock *eb;
1021 int padding;
1023 if(!libungif_handle) {
1024 if(!load_libungif()) {
1025 FIXME("Failed reading GIF because unable to find %s\n", SONAME_LIBUNGIF);
1026 return E_FAIL;
1030 gd.data = xbuf;
1031 gd.curoff = 0;
1032 gd.len = xread;
1033 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1034 ret = pDGifSlurp(gif);
1035 if (ret == GIF_ERROR) {
1036 FIXME("Failed reading GIF using libgif.\n");
1037 return E_FAIL;
1039 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1040 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1041 TRACE("imgcnt %d\n", gif->ImageCount);
1042 if (gif->ImageCount<1) {
1043 FIXME("GIF stream does not have images inside?\n");
1044 return E_FAIL;
1046 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1047 gif->Image.Width, gif->Image.Height,
1048 gif->Image.Left, gif->Image.Top,
1049 gif->Image.Interlace
1051 /* */
1052 padding = (gif->SWidth+3) & ~3;
1053 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(1<<gif->SColorResolution)*sizeof(RGBQUAD));
1054 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1055 si = gif->SavedImages+0;
1056 gid = &(si->ImageDesc);
1057 cm = gid->ColorMap;
1058 if (!cm) cm = gif->SColorMap;
1060 /* look for the transparent color extension */
1061 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1062 eb = si->ExtensionBlocks + i;
1063 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1064 if ((eb->Bytes[0] & 1) == 1) {
1065 transparent = eb->Bytes[3];
1070 for (i=0;i<(1<<gif->SColorResolution);i++) {
1071 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1072 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1073 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1074 if (i == transparent) {
1075 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1076 bmi->bmiColors[i].rgbGreen,
1077 bmi->bmiColors[i].rgbBlue);
1081 /* Map to in picture coordinates */
1082 for (i=0;i<gid->Height;i++)
1083 for (j=0;j<gid->Width;j++)
1084 bytes[(gid->Top+i)*(padding)+gid->Left+j]=si->RasterBits[i*gid->Width+j];
1086 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1087 bmi->bmiHeader.biWidth = gif->SWidth;
1088 bmi->bmiHeader.biHeight = -gif->SHeight;
1089 bmi->bmiHeader.biPlanes = 1;
1090 bmi->bmiHeader.biBitCount = 8;
1091 bmi->bmiHeader.biCompression = BI_RGB;
1092 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1093 bmi->bmiHeader.biXPelsPerMeter = 0;
1094 bmi->bmiHeader.biYPelsPerMeter = 0;
1095 bmi->bmiHeader.biClrUsed = 1 << gif->SColorResolution;
1096 bmi->bmiHeader.biClrImportant = 0;
1098 hdcref = GetDC(0);
1099 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1100 hdcref,
1101 &bmi->bmiHeader,
1102 CBM_INIT,
1103 bytes,
1104 bmi,
1105 DIB_RGB_COLORS
1108 if (transparent > -1) {
1109 /* Create the Mask */
1110 HDC hdc = CreateCompatibleDC(0);
1111 HDC hdcMask = CreateCompatibleDC(0);
1112 HBITMAP hOldbitmap;
1113 HBITMAP hOldbitmapmask;
1115 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1117 hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap);
1118 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1119 SetBkColor(hdc, This->rgbTrans);
1120 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1122 /* We no longer need the original bitmap, so we apply the first
1123 transformation with the mask to speed up the rendering */
1124 SetBkColor(hdc, RGB(0,0,0));
1125 SetTextColor(hdc, RGB(255,255,255));
1126 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1127 hdcMask, 0, 0, SRCAND);
1129 SelectObject(hdc, hOldbitmap);
1130 SelectObject(hdcMask, hOldbitmapmask);
1131 DeleteDC(hdcMask);
1132 DeleteDC(hdc);
1135 DeleteDC(hdcref);
1136 This->desc.picType = PICTYPE_BITMAP;
1137 OLEPictureImpl_SetBitmap(This);
1138 pDGifCloseFile(gif);
1139 HeapFree(GetProcessHeap(),0,bytes);
1140 return S_OK;
1141 #else
1142 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1143 return E_FAIL;
1144 #endif
1145 break;
1147 case 0xd8ff: { /* JPEG */
1148 #ifdef HAVE_JPEGLIB_H
1149 struct jpeg_decompress_struct jd;
1150 struct jpeg_error_mgr jerr;
1151 int ret;
1152 JDIMENSION x;
1153 JSAMPROW samprow,oldsamprow;
1154 BITMAPINFOHEADER bmi;
1155 LPBYTE bits;
1156 HDC hdcref;
1157 struct jpeg_source_mgr xjsm;
1158 LPBYTE oldbits;
1159 int i;
1161 if(!libjpeg_handle) {
1162 if(!load_libjpeg()) {
1163 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1164 return E_FAIL;
1168 /* This is basically so we can use in-memory data for jpeg decompression.
1169 * We need to have all the functions.
1171 xjsm.next_input_byte = xbuf;
1172 xjsm.bytes_in_buffer = xread;
1173 xjsm.init_source = _jpeg_init_source;
1174 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1175 xjsm.skip_input_data = _jpeg_skip_input_data;
1176 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1177 xjsm.term_source = _jpeg_term_source;
1179 jd.err = pjpeg_std_error(&jerr);
1180 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1181 * jpeg_create_decompress(&jd); */
1182 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1183 jd.src = &xjsm;
1184 ret=pjpeg_read_header(&jd,TRUE);
1185 jd.out_color_space = JCS_RGB;
1186 pjpeg_start_decompress(&jd);
1187 if (ret != JPEG_HEADER_OK) {
1188 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1189 HeapFree(GetProcessHeap(),0,xbuf);
1190 return E_FAIL;
1193 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1194 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1195 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1197 oldbits = bits;
1198 oldsamprow = samprow;
1199 while ( jd.output_scanline<jd.output_height ) {
1200 x = pjpeg_read_scanlines(&jd,&samprow,1);
1201 if (x != 1) {
1202 FIXME("failed to read current scanline?\n");
1203 break;
1205 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1206 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1207 *(bits++) = *(samprow+2);
1208 *(bits++) = *(samprow+1);
1209 *(bits++) = *(samprow);
1211 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1212 samprow = oldsamprow;
1214 bits = oldbits;
1216 bmi.biSize = sizeof(bmi);
1217 bmi.biWidth = jd.output_width;
1218 bmi.biHeight = -jd.output_height;
1219 bmi.biPlanes = 1;
1220 bmi.biBitCount = jd.output_components<<3;
1221 bmi.biCompression = BI_RGB;
1222 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1223 bmi.biXPelsPerMeter = 0;
1224 bmi.biYPelsPerMeter = 0;
1225 bmi.biClrUsed = 0;
1226 bmi.biClrImportant = 0;
1228 HeapFree(GetProcessHeap(),0,samprow);
1229 pjpeg_finish_decompress(&jd);
1230 pjpeg_destroy_decompress(&jd);
1231 hdcref = GetDC(0);
1232 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1233 hdcref,
1234 &bmi,
1235 CBM_INIT,
1236 bits,
1237 (BITMAPINFO*)&bmi,
1238 DIB_RGB_COLORS
1240 DeleteDC(hdcref);
1241 This->desc.picType = PICTYPE_BITMAP;
1242 OLEPictureImpl_SetBitmap(This);
1243 hr = S_OK;
1244 HeapFree(GetProcessHeap(),0,bits);
1245 #else
1246 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1247 hr = E_FAIL;
1248 #endif
1249 break;
1251 case 0x4d42: { /* Bitmap */
1252 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1253 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1254 HDC hdcref;
1256 /* Does not matter whether this is a coreheader or not, we only use
1257 * components which are in both
1259 hdcref = GetDC(0);
1260 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1261 hdcref,
1262 &(bi->bmiHeader),
1263 CBM_INIT,
1264 xbuf+bfh->bfOffBits,
1266 (bi->bmiHeader.biBitCount<=8)?DIB_PAL_COLORS:DIB_RGB_COLORS
1268 DeleteDC(hdcref);
1269 This->desc.picType = PICTYPE_BITMAP;
1270 OLEPictureImpl_SetBitmap(This);
1271 hr = S_OK;
1272 break;
1274 case 0x0000: { /* ICON , first word is dwReserved */
1275 HICON hicon;
1276 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1277 HDC hdcRef;
1278 int i;
1281 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1282 FIXME("icon.idType=%d\n",cifd->idType);
1283 FIXME("icon.idCount=%d\n",cifd->idCount);
1285 for (i=0;i<cifd->idCount;i++) {
1286 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1287 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1288 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1289 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1290 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1291 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1292 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1293 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1296 i=0;
1297 /* If we have more than one icon, try to find the best.
1298 * this currently means '32 pixel wide'.
1300 if (cifd->idCount!=1) {
1301 for (i=0;i<cifd->idCount;i++) {
1302 if (cifd->idEntries[i].bWidth == 32)
1303 break;
1305 if (i==cifd->idCount) i=0;
1308 hicon = CreateIconFromResourceEx(
1309 xbuf+cifd->idEntries[i].dwDIBOffset,
1310 cifd->idEntries[i].dwDIBSize,
1311 TRUE, /* is icon */
1312 0x00030000,
1313 cifd->idEntries[i].bWidth,
1314 cifd->idEntries[i].bHeight,
1317 if (!hicon) {
1318 FIXME("CreateIcon failed.\n");
1319 hr = E_FAIL;
1320 } else {
1321 This->desc.picType = PICTYPE_ICON;
1322 This->desc.u.icon.hicon = hicon;
1323 This->origWidth = cifd->idEntries[i].bWidth;
1324 This->origHeight = cifd->idEntries[i].bHeight;
1325 hdcRef = CreateCompatibleDC(0);
1326 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1327 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1328 DeleteDC(hdcRef);
1329 hr = S_OK;
1331 break;
1333 default:
1335 int i;
1336 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1337 hr=E_FAIL;
1338 for (i=0;i<xread+8;i++) {
1339 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1340 else MESSAGE("%02x ",xbuf[i-8]);
1341 if (i % 10 == 9) MESSAGE("\n");
1343 MESSAGE("\n");
1344 break;
1348 /* FIXME: this notify is not really documented */
1349 if (hr==S_OK)
1350 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1351 return hr;
1354 static HRESULT WINAPI OLEPictureImpl_Save(
1355 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1357 ICOM_THIS_From_IPersistStream(IPicture, iface);
1358 FIXME("(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
1359 return E_NOTIMPL;
1362 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1363 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1365 ICOM_THIS_From_IPersistStream(IPicture, iface);
1366 FIXME("(%p,%p),stub!\n",This,pcbSize);
1367 return E_NOTIMPL;
1370 /************************************************************************
1371 * IDispatch
1373 /************************************************************************
1374 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1376 * See Windows documentation for more details on IUnknown methods.
1378 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1379 IDispatch* iface,
1380 REFIID riid,
1381 VOID** ppvoid)
1383 ICOM_THIS_From_IDispatch(IPicture, iface);
1385 return IPicture_QueryInterface(This, riid, ppvoid);
1388 /************************************************************************
1389 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1391 * See Windows documentation for more details on IUnknown methods.
1393 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1394 IDispatch* iface)
1396 ICOM_THIS_From_IDispatch(IPicture, iface);
1398 return IPicture_AddRef(This);
1401 /************************************************************************
1402 * OLEPictureImpl_IDispatch_Release (IUnknown)
1404 * See Windows documentation for more details on IUnknown methods.
1406 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1407 IDispatch* iface)
1409 ICOM_THIS_From_IDispatch(IPicture, iface);
1411 return IPicture_Release(This);
1414 /************************************************************************
1415 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1417 * See Windows documentation for more details on IDispatch methods.
1419 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1420 IDispatch* iface,
1421 unsigned int* pctinfo)
1423 FIXME("():Stub\n");
1425 return E_NOTIMPL;
1428 /************************************************************************
1429 * OLEPictureImpl_GetTypeInfo (IDispatch)
1431 * See Windows documentation for more details on IDispatch methods.
1433 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1434 IDispatch* iface,
1435 UINT iTInfo,
1436 LCID lcid,
1437 ITypeInfo** ppTInfo)
1439 FIXME("():Stub\n");
1441 return E_NOTIMPL;
1444 /************************************************************************
1445 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1447 * See Windows documentation for more details on IDispatch methods.
1449 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1450 IDispatch* iface,
1451 REFIID riid,
1452 LPOLESTR* rgszNames,
1453 UINT cNames,
1454 LCID lcid,
1455 DISPID* rgDispId)
1457 FIXME("():Stub\n");
1459 return E_NOTIMPL;
1462 /************************************************************************
1463 * OLEPictureImpl_Invoke (IDispatch)
1465 * See Windows documentation for more details on IDispatch methods.
1467 static HRESULT WINAPI OLEPictureImpl_Invoke(
1468 IDispatch* iface,
1469 DISPID dispIdMember,
1470 REFIID riid,
1471 LCID lcid,
1472 WORD wFlags,
1473 DISPPARAMS* pDispParams,
1474 VARIANT* pVarResult,
1475 EXCEPINFO* pExepInfo,
1476 UINT* puArgErr)
1478 FIXME("(dispid: %ld):Stub\n",dispIdMember);
1480 VariantInit(pVarResult);
1481 V_VT(pVarResult) = VT_BOOL;
1482 V_UNION(pVarResult,boolVal) = FALSE;
1483 return S_OK;
1487 static IPictureVtbl OLEPictureImpl_VTable =
1489 OLEPictureImpl_QueryInterface,
1490 OLEPictureImpl_AddRef,
1491 OLEPictureImpl_Release,
1492 OLEPictureImpl_get_Handle,
1493 OLEPictureImpl_get_hPal,
1494 OLEPictureImpl_get_Type,
1495 OLEPictureImpl_get_Width,
1496 OLEPictureImpl_get_Height,
1497 OLEPictureImpl_Render,
1498 OLEPictureImpl_set_hPal,
1499 OLEPictureImpl_get_CurDC,
1500 OLEPictureImpl_SelectPicture,
1501 OLEPictureImpl_get_KeepOriginalFormat,
1502 OLEPictureImpl_put_KeepOriginalFormat,
1503 OLEPictureImpl_PictureChanged,
1504 OLEPictureImpl_SaveAsFile,
1505 OLEPictureImpl_get_Attributes
1508 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
1510 OLEPictureImpl_IDispatch_QueryInterface,
1511 OLEPictureImpl_IDispatch_AddRef,
1512 OLEPictureImpl_IDispatch_Release,
1513 OLEPictureImpl_GetTypeInfoCount,
1514 OLEPictureImpl_GetTypeInfo,
1515 OLEPictureImpl_GetIDsOfNames,
1516 OLEPictureImpl_Invoke
1519 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
1521 OLEPictureImpl_IPersistStream_QueryInterface,
1522 OLEPictureImpl_IPersistStream_AddRef,
1523 OLEPictureImpl_IPersistStream_Release,
1524 OLEPictureImpl_GetClassID,
1525 OLEPictureImpl_IsDirty,
1526 OLEPictureImpl_Load,
1527 OLEPictureImpl_Save,
1528 OLEPictureImpl_GetSizeMax
1531 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
1533 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
1534 OLEPictureImpl_IConnectionPointContainer_AddRef,
1535 OLEPictureImpl_IConnectionPointContainer_Release,
1536 OLEPictureImpl_EnumConnectionPoints,
1537 OLEPictureImpl_FindConnectionPoint
1540 /***********************************************************************
1541 * OleCreatePictureIndirect (OLEAUT32.419)
1543 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
1544 BOOL fOwn, LPVOID *ppvObj )
1546 OLEPictureImpl* newPict = NULL;
1547 HRESULT hr = S_OK;
1549 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
1552 * Sanity check
1554 if (ppvObj==0)
1555 return E_POINTER;
1557 *ppvObj = NULL;
1560 * Try to construct a new instance of the class.
1562 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
1564 if (newPict == NULL)
1565 return E_OUTOFMEMORY;
1568 * Make sure it supports the interface required by the caller.
1570 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
1573 * Release the reference obtained in the constructor. If
1574 * the QueryInterface was unsuccessful, it will free the class.
1576 IPicture_Release((IPicture*)newPict);
1578 return hr;
1582 /***********************************************************************
1583 * OleLoadPicture (OLEAUT32.418)
1585 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1586 REFIID riid, LPVOID *ppvObj )
1588 LPPERSISTSTREAM ps;
1589 IPicture *newpic;
1590 HRESULT hr;
1592 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
1593 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
1595 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
1596 if (hr)
1597 return hr;
1598 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
1599 if (hr) {
1600 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1601 IPicture_Release(newpic);
1602 *ppvObj = NULL;
1603 return hr;
1605 IPersistStream_Load(ps,lpstream);
1606 IPersistStream_Release(ps);
1607 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
1608 if (hr)
1609 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
1610 IPicture_Release(newpic);
1611 return hr;
1614 /***********************************************************************
1615 * OleLoadPictureEx (OLEAUT32.401)
1617 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1618 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
1620 LPPERSISTSTREAM ps;
1621 IPicture *newpic;
1622 HRESULT hr;
1624 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
1625 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
1627 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
1628 if (hr)
1629 return hr;
1630 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
1631 if (hr) {
1632 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1633 IPicture_Release(newpic);
1634 *ppvObj = NULL;
1635 return hr;
1637 IPersistStream_Load(ps,lpstream);
1638 IPersistStream_Release(ps);
1639 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
1640 if (hr)
1641 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
1642 IPicture_Release(newpic);
1643 return hr;
1646 /*******************************************************************************
1647 * StdPic ClassFactory
1649 typedef struct
1651 /* IUnknown fields */
1652 IClassFactoryVtbl *lpVtbl;
1653 DWORD ref;
1654 } IClassFactoryImpl;
1656 static HRESULT WINAPI
1657 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
1658 ICOM_THIS(IClassFactoryImpl,iface);
1660 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1661 return E_NOINTERFACE;
1664 static ULONG WINAPI
1665 SPCF_AddRef(LPCLASSFACTORY iface) {
1666 ICOM_THIS(IClassFactoryImpl,iface);
1667 return ++(This->ref);
1670 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
1671 ICOM_THIS(IClassFactoryImpl,iface);
1672 /* static class, won't be freed */
1673 return --(This->ref);
1676 static HRESULT WINAPI SPCF_CreateInstance(
1677 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
1679 PICTDESC pd;
1681 FIXME("(%p,%p,%s,%p), creating stdpic with PICTYPE_NONE.\n",iface,pOuter,debugstr_guid(riid),ppobj);
1682 pd.cbSizeofstruct = sizeof(pd);
1683 pd.picType = PICTYPE_NONE;
1684 return OleCreatePictureIndirect(&pd,riid,TRUE,ppobj);
1688 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
1689 ICOM_THIS(IClassFactoryImpl,iface);
1690 FIXME("(%p)->(%d),stub!\n",This,dolock);
1691 return S_OK;
1694 static IClassFactoryVtbl SPCF_Vtbl = {
1695 SPCF_QueryInterface,
1696 SPCF_AddRef,
1697 SPCF_Release,
1698 SPCF_CreateInstance,
1699 SPCF_LockServer
1701 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
1703 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }