Allow resizing windows without thickframe style.
[wine/testsucceed.git] / dlls / oleaut32 / olepicture.c
blobdcb98c82dc912ae6f7cd5c3a35131c3185a3c8e2
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 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
961 if (hr)
962 FIXME("Stat failed with hres %lx\n",hr);
963 hr=IStream_Read(pStm,header,8,&xread);
964 if (hr || xread!=8) {
965 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
966 return hr;
968 if (header[1] > statstg.cbSize.QuadPart || (header[1]==0)) {/* Incorrect header, assume none. */
969 xread = 8;
970 xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,statstg.cbSize.QuadPart);
971 memcpy(xbuf,&header,8);
972 This->datalen = statstg.cbSize.QuadPart;
973 while (xread < This->datalen) {
974 ULONG nread;
975 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
976 xread+=nread;
977 if (hr || !nread)
978 break;
980 if (xread != This->datalen)
981 FIXME("Could only read %ld of %d bytes in no-header case?\n",xread,This->datalen);
982 } else {
983 xread = 0;
984 xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
985 This->datalen = header[1];
986 while (xread < header[1]) {
987 ULONG nread;
988 hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
989 xread+=nread;
990 if (hr || !nread)
991 break;
993 if (xread != header[1])
994 FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
996 magic = xbuf[0] + (xbuf[1]<<8);
997 switch (magic) {
998 case 0x4947: { /* GIF */
999 #ifdef HAVE_GIF_LIB_H
1000 struct gifdata gd;
1001 GifFileType *gif;
1002 BITMAPINFO *bmi;
1003 HDC hdcref;
1004 LPBYTE bytes;
1005 int i,j,ret;
1006 GifImageDesc *gid;
1007 SavedImage *si;
1008 ColorMapObject *cm;
1009 int transparent = -1;
1010 ExtensionBlock *eb;
1011 int padding;
1013 if(!libungif_handle) {
1014 if(!load_libungif()) {
1015 FIXME("Failed reading GIF because unable to find %s\n", SONAME_LIBUNGIF);
1016 return E_FAIL;
1020 gd.data = xbuf;
1021 gd.curoff = 0;
1022 gd.len = xread;
1023 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1024 ret = pDGifSlurp(gif);
1025 if (ret == GIF_ERROR) {
1026 FIXME("Failed reading GIF using libgif.\n");
1027 return E_FAIL;
1029 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1030 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1031 TRACE("imgcnt %d\n", gif->ImageCount);
1032 if (gif->ImageCount<1) {
1033 FIXME("GIF stream does not have images inside?\n");
1034 return E_FAIL;
1036 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1037 gif->Image.Width, gif->Image.Height,
1038 gif->Image.Left, gif->Image.Top,
1039 gif->Image.Interlace
1041 /* */
1042 padding = (gif->SWidth+3) & ~3;
1043 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(1<<gif->SColorResolution)*sizeof(RGBQUAD));
1044 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1045 si = gif->SavedImages+0;
1046 gid = &(si->ImageDesc);
1047 cm = gid->ColorMap;
1048 if (!cm) cm = gif->SColorMap;
1050 /* look for the transparent color extension */
1051 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1052 eb = si->ExtensionBlocks + i;
1053 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1054 if ((eb->Bytes[0] & 1) == 1) {
1055 transparent = eb->Bytes[3];
1060 for (i=0;i<(1<<gif->SColorResolution);i++) {
1061 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1062 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1063 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1064 if (i == transparent) {
1065 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1066 bmi->bmiColors[i].rgbGreen,
1067 bmi->bmiColors[i].rgbBlue);
1071 /* Map to in picture coordinates */
1072 for (i=0;i<gid->Height;i++)
1073 for (j=0;j<gid->Width;j++)
1074 bytes[(gid->Top+i)*(padding)+gid->Left+j]=si->RasterBits[i*gid->Width+j];
1076 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1077 bmi->bmiHeader.biWidth = gif->SWidth;
1078 bmi->bmiHeader.biHeight = -gif->SHeight;
1079 bmi->bmiHeader.biPlanes = 1;
1080 bmi->bmiHeader.biBitCount = 8;
1081 bmi->bmiHeader.biCompression = BI_RGB;
1082 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1083 bmi->bmiHeader.biXPelsPerMeter = 0;
1084 bmi->bmiHeader.biYPelsPerMeter = 0;
1085 bmi->bmiHeader.biClrUsed = 1 << gif->SColorResolution;
1086 bmi->bmiHeader.biClrImportant = 0;
1088 hdcref = GetDC(0);
1089 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1090 hdcref,
1091 &bmi->bmiHeader,
1092 CBM_INIT,
1093 bytes,
1094 bmi,
1095 DIB_RGB_COLORS
1098 if (transparent > -1) {
1099 /* Create the Mask */
1100 HDC hdc = CreateCompatibleDC(0);
1101 HDC hdcMask = CreateCompatibleDC(0);
1102 HBITMAP hOldbitmap;
1103 HBITMAP hOldbitmapmask;
1105 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1107 hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap);
1108 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1109 SetBkColor(hdc, This->rgbTrans);
1110 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1112 /* We no longer need the original bitmap, so we apply the first
1113 transformation with the mask to speed up the rendering */
1114 SetBkColor(hdc, RGB(0,0,0));
1115 SetTextColor(hdc, RGB(255,255,255));
1116 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1117 hdcMask, 0, 0, SRCAND);
1119 SelectObject(hdc, hOldbitmap);
1120 SelectObject(hdcMask, hOldbitmapmask);
1121 DeleteDC(hdcMask);
1122 DeleteDC(hdc);
1125 DeleteDC(hdcref);
1126 This->desc.picType = PICTYPE_BITMAP;
1127 OLEPictureImpl_SetBitmap(This);
1128 pDGifCloseFile(gif);
1129 HeapFree(GetProcessHeap(),0,bytes);
1130 return S_OK;
1131 #else
1132 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1133 return E_FAIL;
1134 #endif
1135 break;
1137 case 0xd8ff: { /* JPEG */
1138 #ifdef HAVE_JPEGLIB_H
1139 struct jpeg_decompress_struct jd;
1140 struct jpeg_error_mgr jerr;
1141 int ret;
1142 JDIMENSION x;
1143 JSAMPROW samprow,oldsamprow;
1144 BITMAPINFOHEADER bmi;
1145 LPBYTE bits;
1146 HDC hdcref;
1147 struct jpeg_source_mgr xjsm;
1148 LPBYTE oldbits;
1149 int i;
1151 if(!libjpeg_handle) {
1152 if(!load_libjpeg()) {
1153 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1154 return E_FAIL;
1158 /* This is basically so we can use in-memory data for jpeg decompression.
1159 * We need to have all the functions.
1161 xjsm.next_input_byte = xbuf;
1162 xjsm.bytes_in_buffer = xread;
1163 xjsm.init_source = _jpeg_init_source;
1164 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1165 xjsm.skip_input_data = _jpeg_skip_input_data;
1166 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1167 xjsm.term_source = _jpeg_term_source;
1169 jd.err = pjpeg_std_error(&jerr);
1170 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1171 * jpeg_create_decompress(&jd); */
1172 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1173 jd.src = &xjsm;
1174 ret=pjpeg_read_header(&jd,TRUE);
1175 jd.out_color_space = JCS_RGB;
1176 pjpeg_start_decompress(&jd);
1177 if (ret != JPEG_HEADER_OK) {
1178 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1179 HeapFree(GetProcessHeap(),0,xbuf);
1180 return E_FAIL;
1183 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1184 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1185 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1187 oldbits = bits;
1188 oldsamprow = samprow;
1189 while ( jd.output_scanline<jd.output_height ) {
1190 x = pjpeg_read_scanlines(&jd,&samprow,1);
1191 if (x != 1) {
1192 FIXME("failed to read current scanline?\n");
1193 break;
1195 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1196 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1197 *(bits++) = *(samprow+2);
1198 *(bits++) = *(samprow+1);
1199 *(bits++) = *(samprow);
1201 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1202 samprow = oldsamprow;
1204 bits = oldbits;
1206 bmi.biSize = sizeof(bmi);
1207 bmi.biWidth = jd.output_width;
1208 bmi.biHeight = -jd.output_height;
1209 bmi.biPlanes = 1;
1210 bmi.biBitCount = jd.output_components<<3;
1211 bmi.biCompression = BI_RGB;
1212 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1213 bmi.biXPelsPerMeter = 0;
1214 bmi.biYPelsPerMeter = 0;
1215 bmi.biClrUsed = 0;
1216 bmi.biClrImportant = 0;
1218 HeapFree(GetProcessHeap(),0,samprow);
1219 pjpeg_finish_decompress(&jd);
1220 pjpeg_destroy_decompress(&jd);
1221 hdcref = GetDC(0);
1222 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1223 hdcref,
1224 &bmi,
1225 CBM_INIT,
1226 bits,
1227 (BITMAPINFO*)&bmi,
1228 DIB_RGB_COLORS
1230 DeleteDC(hdcref);
1231 This->desc.picType = PICTYPE_BITMAP;
1232 OLEPictureImpl_SetBitmap(This);
1233 hr = S_OK;
1234 HeapFree(GetProcessHeap(),0,bits);
1235 #else
1236 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1237 hr = E_FAIL;
1238 #endif
1239 break;
1241 case 0x4d42: { /* Bitmap */
1242 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1243 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1244 HDC hdcref;
1246 /* Does not matter whether this is a coreheader or not, we only use
1247 * components which are in both
1249 hdcref = GetDC(0);
1250 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1251 hdcref,
1252 &(bi->bmiHeader),
1253 CBM_INIT,
1254 xbuf+bfh->bfOffBits,
1256 (bi->bmiHeader.biBitCount<=8)?DIB_PAL_COLORS:DIB_RGB_COLORS
1258 DeleteDC(hdcref);
1259 This->desc.picType = PICTYPE_BITMAP;
1260 OLEPictureImpl_SetBitmap(This);
1261 hr = S_OK;
1262 break;
1264 case 0x0000: { /* ICON , first word is dwReserved */
1265 HICON hicon;
1266 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1267 int i;
1270 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1271 FIXME("icon.idType=%d\n",cifd->idType);
1272 FIXME("icon.idCount=%d\n",cifd->idCount);
1274 for (i=0;i<cifd->idCount;i++) {
1275 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1276 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1277 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1278 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1279 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1280 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1281 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1282 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1285 i=0;
1286 /* If we have more than one icon, try to find the best.
1287 * this currently means '32 pixel wide'.
1289 if (cifd->idCount!=1) {
1290 for (i=0;i<cifd->idCount;i++) {
1291 if (cifd->idEntries[i].bWidth == 32)
1292 break;
1294 if (i==cifd->idCount) i=0;
1297 hicon = CreateIconFromResourceEx(
1298 xbuf+cifd->idEntries[i].dwDIBOffset,
1299 cifd->idEntries[i].dwDIBSize,
1300 TRUE, /* is icon */
1301 0x00030000,
1302 cifd->idEntries[i].bWidth,
1303 cifd->idEntries[i].bHeight,
1306 if (!hicon) {
1307 FIXME("CreateIcon failed.\n");
1308 hr = E_FAIL;
1309 } else {
1310 This->desc.picType = PICTYPE_ICON;
1311 This->desc.u.icon.hicon = hicon;
1312 This->himetricWidth = cifd->idEntries[i].bWidth;
1313 This->himetricHeight = cifd->idEntries[i].bHeight;
1314 hr = S_OK;
1316 break;
1318 default:
1320 int i;
1321 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1322 hr=E_FAIL;
1323 for (i=0;i<xread+8;i++) {
1324 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1325 else MESSAGE("%02x ",xbuf[i-8]);
1326 if (i % 10 == 9) MESSAGE("\n");
1328 MESSAGE("\n");
1329 break;
1333 /* FIXME: this notify is not really documented */
1334 if (hr==S_OK)
1335 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1336 return hr;
1339 static HRESULT WINAPI OLEPictureImpl_Save(
1340 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1342 ICOM_THIS_From_IPersistStream(IPicture, iface);
1343 FIXME("(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
1344 return E_NOTIMPL;
1347 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1348 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1350 ICOM_THIS_From_IPersistStream(IPicture, iface);
1351 FIXME("(%p,%p),stub!\n",This,pcbSize);
1352 return E_NOTIMPL;
1355 /************************************************************************
1356 * IDispatch
1358 /************************************************************************
1359 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1361 * See Windows documentation for more details on IUnknown methods.
1363 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1364 IDispatch* iface,
1365 REFIID riid,
1366 VOID** ppvoid)
1368 ICOM_THIS_From_IDispatch(IPicture, iface);
1370 return IPicture_QueryInterface(This, riid, ppvoid);
1373 /************************************************************************
1374 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1376 * See Windows documentation for more details on IUnknown methods.
1378 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1379 IDispatch* iface)
1381 ICOM_THIS_From_IDispatch(IPicture, iface);
1383 return IPicture_AddRef(This);
1386 /************************************************************************
1387 * OLEPictureImpl_IDispatch_Release (IUnknown)
1389 * See Windows documentation for more details on IUnknown methods.
1391 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1392 IDispatch* iface)
1394 ICOM_THIS_From_IDispatch(IPicture, iface);
1396 return IPicture_Release(This);
1399 /************************************************************************
1400 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1402 * See Windows documentation for more details on IDispatch methods.
1404 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1405 IDispatch* iface,
1406 unsigned int* pctinfo)
1408 FIXME("():Stub\n");
1410 return E_NOTIMPL;
1413 /************************************************************************
1414 * OLEPictureImpl_GetTypeInfo (IDispatch)
1416 * See Windows documentation for more details on IDispatch methods.
1418 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1419 IDispatch* iface,
1420 UINT iTInfo,
1421 LCID lcid,
1422 ITypeInfo** ppTInfo)
1424 FIXME("():Stub\n");
1426 return E_NOTIMPL;
1429 /************************************************************************
1430 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1432 * See Windows documentation for more details on IDispatch methods.
1434 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1435 IDispatch* iface,
1436 REFIID riid,
1437 LPOLESTR* rgszNames,
1438 UINT cNames,
1439 LCID lcid,
1440 DISPID* rgDispId)
1442 FIXME("():Stub\n");
1444 return E_NOTIMPL;
1447 /************************************************************************
1448 * OLEPictureImpl_Invoke (IDispatch)
1450 * See Windows documentation for more details on IDispatch methods.
1452 static HRESULT WINAPI OLEPictureImpl_Invoke(
1453 IDispatch* iface,
1454 DISPID dispIdMember,
1455 REFIID riid,
1456 LCID lcid,
1457 WORD wFlags,
1458 DISPPARAMS* pDispParams,
1459 VARIANT* pVarResult,
1460 EXCEPINFO* pExepInfo,
1461 UINT* puArgErr)
1463 FIXME("(dispid: %ld):Stub\n",dispIdMember);
1465 VariantInit(pVarResult);
1466 V_VT(pVarResult) = VT_BOOL;
1467 V_UNION(pVarResult,boolVal) = FALSE;
1468 return S_OK;
1472 static IPictureVtbl OLEPictureImpl_VTable =
1474 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1475 OLEPictureImpl_QueryInterface,
1476 OLEPictureImpl_AddRef,
1477 OLEPictureImpl_Release,
1478 OLEPictureImpl_get_Handle,
1479 OLEPictureImpl_get_hPal,
1480 OLEPictureImpl_get_Type,
1481 OLEPictureImpl_get_Width,
1482 OLEPictureImpl_get_Height,
1483 OLEPictureImpl_Render,
1484 OLEPictureImpl_set_hPal,
1485 OLEPictureImpl_get_CurDC,
1486 OLEPictureImpl_SelectPicture,
1487 OLEPictureImpl_get_KeepOriginalFormat,
1488 OLEPictureImpl_put_KeepOriginalFormat,
1489 OLEPictureImpl_PictureChanged,
1490 OLEPictureImpl_SaveAsFile,
1491 OLEPictureImpl_get_Attributes
1494 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
1496 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1497 OLEPictureImpl_IDispatch_QueryInterface,
1498 OLEPictureImpl_IDispatch_AddRef,
1499 OLEPictureImpl_IDispatch_Release,
1500 OLEPictureImpl_GetTypeInfoCount,
1501 OLEPictureImpl_GetTypeInfo,
1502 OLEPictureImpl_GetIDsOfNames,
1503 OLEPictureImpl_Invoke
1506 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
1508 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1509 OLEPictureImpl_IPersistStream_QueryInterface,
1510 OLEPictureImpl_IPersistStream_AddRef,
1511 OLEPictureImpl_IPersistStream_Release,
1512 OLEPictureImpl_GetClassID,
1513 OLEPictureImpl_IsDirty,
1514 OLEPictureImpl_Load,
1515 OLEPictureImpl_Save,
1516 OLEPictureImpl_GetSizeMax
1519 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
1521 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1522 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
1523 OLEPictureImpl_IConnectionPointContainer_AddRef,
1524 OLEPictureImpl_IConnectionPointContainer_Release,
1525 OLEPictureImpl_EnumConnectionPoints,
1526 OLEPictureImpl_FindConnectionPoint
1529 /***********************************************************************
1530 * OleCreatePictureIndirect (OLEAUT32.419)
1532 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
1533 BOOL fOwn, LPVOID *ppvObj )
1535 OLEPictureImpl* newPict = NULL;
1536 HRESULT hr = S_OK;
1538 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
1541 * Sanity check
1543 if (ppvObj==0)
1544 return E_POINTER;
1546 *ppvObj = NULL;
1549 * Try to construct a new instance of the class.
1551 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
1553 if (newPict == NULL)
1554 return E_OUTOFMEMORY;
1557 * Make sure it supports the interface required by the caller.
1559 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
1562 * Release the reference obtained in the constructor. If
1563 * the QueryInterface was unsuccessful, it will free the class.
1565 IPicture_Release((IPicture*)newPict);
1567 return hr;
1571 /***********************************************************************
1572 * OleLoadPicture (OLEAUT32.418)
1574 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1575 REFIID riid, LPVOID *ppvObj )
1577 LPPERSISTSTREAM ps;
1578 IPicture *newpic;
1579 HRESULT hr;
1581 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
1582 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
1584 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
1585 if (hr)
1586 return hr;
1587 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
1588 if (hr) {
1589 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1590 IPicture_Release(newpic);
1591 *ppvObj = NULL;
1592 return hr;
1594 IPersistStream_Load(ps,lpstream);
1595 IPersistStream_Release(ps);
1596 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
1597 if (hr)
1598 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
1599 IPicture_Release(newpic);
1600 return hr;
1603 /***********************************************************************
1604 * OleLoadPictureEx (OLEAUT32.401)
1606 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1607 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
1609 LPPERSISTSTREAM ps;
1610 IPicture *newpic;
1611 HRESULT hr;
1613 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
1614 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
1616 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
1617 if (hr)
1618 return hr;
1619 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
1620 if (hr) {
1621 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1622 IPicture_Release(newpic);
1623 *ppvObj = NULL;
1624 return hr;
1626 IPersistStream_Load(ps,lpstream);
1627 IPersistStream_Release(ps);
1628 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
1629 if (hr)
1630 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
1631 IPicture_Release(newpic);
1632 return hr;
1635 /*******************************************************************************
1636 * StdPic ClassFactory
1638 typedef struct
1640 /* IUnknown fields */
1641 IClassFactoryVtbl *lpVtbl;
1642 DWORD ref;
1643 } IClassFactoryImpl;
1645 static HRESULT WINAPI
1646 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
1647 ICOM_THIS(IClassFactoryImpl,iface);
1649 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1650 return E_NOINTERFACE;
1653 static ULONG WINAPI
1654 SPCF_AddRef(LPCLASSFACTORY iface) {
1655 ICOM_THIS(IClassFactoryImpl,iface);
1656 return ++(This->ref);
1659 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
1660 ICOM_THIS(IClassFactoryImpl,iface);
1661 /* static class, won't be freed */
1662 return --(This->ref);
1665 static HRESULT WINAPI SPCF_CreateInstance(
1666 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
1668 PICTDESC pd;
1670 FIXME("(%p,%p,%s,%p), creating stdpic with PICTYPE_NONE.\n",iface,pOuter,debugstr_guid(riid),ppobj);
1671 pd.cbSizeofstruct = sizeof(pd);
1672 pd.picType = PICTYPE_NONE;
1673 return OleCreatePictureIndirect(&pd,riid,TRUE,ppobj);
1677 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
1678 ICOM_THIS(IClassFactoryImpl,iface);
1679 FIXME("(%p)->(%d),stub!\n",This,dolock);
1680 return S_OK;
1683 static IClassFactoryVtbl SPCF_Vtbl = {
1684 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1685 SPCF_QueryInterface,
1686 SPCF_AddRef,
1687 SPCF_Release,
1688 SPCF_CreateInstance,
1689 SPCF_LockServer
1691 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
1693 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }