Added the DFCS_{HOT,TRANSPARENT} definitions.
[wine/gsoc_dplay.git] / dlls / oleaut32 / olepicture.c
blobc7bea43d01268b82267ae665623a3f9a9dd96263
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"
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include "winerror.h"
44 #include "winbase.h"
45 #include "wingdi.h"
46 #include "winuser.h"
47 #include "ole2.h"
48 #include "olectl.h"
49 #include "oleauto.h"
50 #include "wine/obj_picture.h"
51 #include "wine/obj_connection.h"
52 #include "connpt.h"
53 #include "wine/debug.h"
55 #include "wine/wingdi16.h"
56 #include "cursoricon.h"
58 #ifdef HAVE_LIBJPEG
59 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
60 #define XMD_H
61 #define UINT16 JPEG_UINT16
62 #ifdef HAVE_JPEGLIB_H
63 # include <jpeglib.h>
64 #endif
65 #undef UINT16
66 #endif
68 WINE_DEFAULT_DEBUG_CHANNEL(ole);
70 /*************************************************************************
71 * Declaration of implementation class
74 typedef struct OLEPictureImpl {
77 * IPicture handles IUnknown
80 ICOM_VTABLE(IPicture) *lpvtbl1;
81 ICOM_VTABLE(IDispatch) *lpvtbl2;
82 ICOM_VTABLE(IPersistStream) *lpvtbl3;
83 ICOM_VTABLE(IConnectionPointContainer) *lpvtbl4;
85 /* Object referenece count */
86 DWORD ref;
88 /* We own the object and must destroy it ourselves */
89 BOOL fOwn;
91 /* Picture description */
92 PICTDESC desc;
94 /* These are the pixel size of a bitmap */
95 DWORD origWidth;
96 DWORD origHeight;
98 /* And these are the size of the picture converted into HIMETRIC units */
99 OLE_XSIZE_HIMETRIC himetricWidth;
100 OLE_YSIZE_HIMETRIC himetricHeight;
102 IConnectionPoint *pCP;
104 BOOL keepOrigFormat;
105 HDC hDCCur;
106 } OLEPictureImpl;
109 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
111 #define ICOM_THIS_From_IDispatch(impl, name) \
112 impl *This = (impl*)(((char*)name)-sizeof(void*));
113 #define ICOM_THIS_From_IPersistStream(impl, name) \
114 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
115 #define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
116 impl *This = (impl*)(((char*)name)-3*sizeof(void*));
119 * Predeclare VTables. They get initialized at the end.
121 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable;
122 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable;
123 static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable;
124 static ICOM_VTABLE(IConnectionPointContainer) OLEPictureImpl_IConnectionPointContainer_VTable;
126 /***********************************************************************
127 * Implementation of the OLEPictureImpl class.
130 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
131 BITMAP bm;
132 HDC hdcRef;
134 TRACE("bitmap handle %08x\n", This->desc.u.bmp.hbitmap);
135 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
136 ERR("GetObject fails\n");
137 return;
139 This->origWidth = bm.bmWidth;
140 This->origHeight = bm.bmHeight;
141 /* The width and height are stored in HIMETRIC units (0.01 mm),
142 so we take our pixel width divide by pixels per inch and
143 multiply by 25.4 * 100 */
144 /* Should we use GetBitmapDimension if available? */
145 hdcRef = CreateCompatibleDC(0);
146 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
147 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
148 DeleteDC(hdcRef);
151 /************************************************************************
152 * OLEPictureImpl_Construct
154 * This method will construct a new instance of the OLEPictureImpl
155 * class.
157 * The caller of this method must release the object when it's
158 * done with it.
160 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
162 OLEPictureImpl* newObject = 0;
164 if (pictDesc)
165 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
168 * Allocate space for the object.
170 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEPictureImpl));
172 if (newObject==0)
173 return newObject;
176 * Initialize the virtual function table.
178 newObject->lpvtbl1 = &OLEPictureImpl_VTable;
179 newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
180 newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
181 newObject->lpvtbl4 = &OLEPictureImpl_IConnectionPointContainer_VTable;
183 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
186 * Start with one reference count. The caller of this function
187 * must release the interface pointer when it is done.
189 newObject->ref = 1;
190 newObject->hDCCur = 0;
192 newObject->fOwn = fOwn;
194 /* dunno about original value */
195 newObject->keepOrigFormat = TRUE;
197 if (pictDesc) {
198 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
199 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
201 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
204 switch(pictDesc->picType) {
205 case PICTYPE_BITMAP:
206 OLEPictureImpl_SetBitmap(newObject);
207 break;
209 case PICTYPE_METAFILE:
210 TRACE("metafile handle %08x\n", pictDesc->u.wmf.hmeta);
211 newObject->himetricWidth = pictDesc->u.wmf.xExt;
212 newObject->himetricHeight = pictDesc->u.wmf.yExt;
213 break;
215 case PICTYPE_ICON:
216 case PICTYPE_ENHMETAFILE:
217 default:
218 FIXME("Unsupported type %d\n", pictDesc->picType);
219 newObject->himetricWidth = newObject->himetricHeight = 0;
220 break;
222 } else {
223 newObject->desc.picType = PICTYPE_UNINITIALIZED;
226 TRACE("returning %p\n", newObject);
227 return newObject;
230 /************************************************************************
231 * OLEPictureImpl_Destroy
233 * This method is called by the Release method when the reference
234 * count goes down to 0. It will free all resources used by
235 * this object. */
236 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
238 TRACE("(%p)\n", Obj);
240 if(Obj->fOwn) { /* We need to destroy the picture */
241 switch(Obj->desc.picType) {
242 case PICTYPE_BITMAP:
243 DeleteObject(Obj->desc.u.bmp.hbitmap);
244 break;
245 case PICTYPE_METAFILE:
246 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
247 break;
248 case PICTYPE_ICON:
249 DestroyIcon(Obj->desc.u.icon.hicon);
250 break;
251 case PICTYPE_ENHMETAFILE:
252 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
253 break;
254 default:
255 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
256 break;
259 HeapFree(GetProcessHeap(), 0, Obj);
262 static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
264 /************************************************************************
265 * OLEPictureImpl_QueryInterface (IUnknown)
267 * See Windows documentation for more details on IUnknown methods.
269 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
270 IPicture* iface,
271 REFIID riid,
272 void** ppvObject)
274 ICOM_THIS(OLEPictureImpl, iface);
275 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
278 * Perform a sanity check on the parameters.
280 if ( (This==0) || (ppvObject==0) )
281 return E_INVALIDARG;
284 * Initialize the return parameter.
286 *ppvObject = 0;
289 * Compare the riid with the interface IDs implemented by this object.
291 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
293 *ppvObject = (IPicture*)This;
295 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
297 *ppvObject = (IPicture*)This;
299 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
301 *ppvObject = (IDispatch*)&(This->lpvtbl2);
303 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
305 *ppvObject = (IDispatch*)&(This->lpvtbl2);
307 else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
309 *ppvObject = (IPersistStream*)&(This->lpvtbl3);
311 else if (memcmp(&IID_IConnectionPointContainer, riid, sizeof(IID_IConnectionPointContainer)) == 0)
313 *ppvObject = (IConnectionPointContainer*)&(This->lpvtbl4);
316 * Check that we obtained an interface.
318 if ((*ppvObject)==0)
320 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
321 return E_NOINTERFACE;
325 * Query Interface always increases the reference count by one when it is
326 * successful
328 OLEPictureImpl_AddRef((IPicture*)This);
330 return S_OK;;
332 /***********************************************************************
333 * OLEPicture_SendNotify (internal)
335 * Sends notification messages of changed properties to any interested
336 * connections.
338 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
340 IEnumConnections *pEnum;
341 CONNECTDATA CD;
343 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
344 return;
345 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
346 IPropertyNotifySink *sink;
348 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
349 IPropertyNotifySink_OnChanged(sink, dispID);
350 IPropertyNotifySink_Release(sink);
351 IUnknown_Release(CD.pUnk);
353 IEnumConnections_Release(pEnum);
354 return;
357 /************************************************************************
358 * OLEPictureImpl_AddRef (IUnknown)
360 * See Windows documentation for more details on IUnknown methods.
362 static ULONG WINAPI OLEPictureImpl_AddRef(
363 IPicture* iface)
365 ICOM_THIS(OLEPictureImpl, iface);
366 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
367 This->ref++;
369 return This->ref;
372 /************************************************************************
373 * OLEPictureImpl_Release (IUnknown)
375 * See Windows documentation for more details on IUnknown methods.
377 static ULONG WINAPI OLEPictureImpl_Release(
378 IPicture* iface)
380 ICOM_THIS(OLEPictureImpl, iface);
381 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
384 * Decrease the reference count on this object.
386 This->ref--;
389 * If the reference count goes down to 0, perform suicide.
391 if (This->ref==0)
393 OLEPictureImpl_Destroy(This);
395 return 0;
398 return This->ref;
402 /************************************************************************
403 * OLEPictureImpl_get_Handle
405 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
406 OLE_HANDLE *phandle)
408 ICOM_THIS(OLEPictureImpl, iface);
409 TRACE("(%p)->(%p)\n", This, phandle);
410 switch(This->desc.picType) {
411 case PICTYPE_BITMAP:
412 *phandle = This->desc.u.bmp.hbitmap;
413 break;
414 case PICTYPE_METAFILE:
415 *phandle = This->desc.u.wmf.hmeta;
416 break;
417 case PICTYPE_ICON:
418 *phandle = This->desc.u.icon.hicon;
419 break;
420 case PICTYPE_ENHMETAFILE:
421 *phandle = This->desc.u.emf.hemf;
422 break;
423 default:
424 FIXME("Unimplemented type %d\n", This->desc.picType);
425 return E_NOTIMPL;
427 TRACE("returning handle %08x\n", *phandle);
428 return S_OK;
431 /************************************************************************
432 * OLEPictureImpl_get_hPal
434 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
435 OLE_HANDLE *phandle)
437 ICOM_THIS(OLEPictureImpl, iface);
438 FIXME("(%p)->(%p): stub\n", This, phandle);
439 return E_NOTIMPL;
442 /************************************************************************
443 * OLEPictureImpl_get_Type
445 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
446 short *ptype)
448 ICOM_THIS(OLEPictureImpl, iface);
449 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
450 *ptype = This->desc.picType;
451 return S_OK;
454 /************************************************************************
455 * OLEPictureImpl_get_Width
457 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
458 OLE_XSIZE_HIMETRIC *pwidth)
460 ICOM_THIS(OLEPictureImpl, iface);
461 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
462 *pwidth = This->himetricWidth;
463 return S_OK;
466 /************************************************************************
467 * OLEPictureImpl_get_Height
469 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
470 OLE_YSIZE_HIMETRIC *pheight)
472 ICOM_THIS(OLEPictureImpl, iface);
473 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
474 *pheight = This->himetricHeight;
475 return S_OK;
478 /************************************************************************
479 * OLEPictureImpl_Render
481 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
482 long x, long y, long cx, long cy,
483 OLE_XPOS_HIMETRIC xSrc,
484 OLE_YPOS_HIMETRIC ySrc,
485 OLE_XSIZE_HIMETRIC cxSrc,
486 OLE_YSIZE_HIMETRIC cySrc,
487 LPCRECT prcWBounds)
489 ICOM_THIS(OLEPictureImpl, iface);
490 TRACE("(%p)->(%08x, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
491 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
492 if(prcWBounds)
493 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
494 prcWBounds->right, prcWBounds->bottom);
497 * While the documentation suggests this to be here (or after rendering?)
498 * it does cause an endless recursion in my sample app. -MM 20010804
499 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
502 switch(This->desc.picType) {
503 case PICTYPE_BITMAP:
505 HBITMAP hbmpOld;
506 HDC hdcBmp;
508 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
509 NB y-axis gets flipped */
511 hdcBmp = CreateCompatibleDC(0);
512 SetMapMode(hdcBmp, MM_ANISOTROPIC);
513 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
514 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
515 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
516 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
518 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
520 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
522 SelectObject(hdcBmp, hbmpOld);
523 DeleteDC(hdcBmp);
525 break;
526 case PICTYPE_ICON:
527 FIXME("Not quite correct implementation of rendering icons...\n");
528 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
529 break;
531 case PICTYPE_METAFILE:
532 case PICTYPE_ENHMETAFILE:
533 default:
534 FIXME("type %d not implemented\n", This->desc.picType);
535 return E_NOTIMPL;
537 return S_OK;
540 /************************************************************************
541 * OLEPictureImpl_set_hPal
543 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
544 OLE_HANDLE hpal)
546 ICOM_THIS(OLEPictureImpl, iface);
547 FIXME("(%p)->(%08x): stub\n", This, hpal);
548 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
549 return E_NOTIMPL;
552 /************************************************************************
553 * OLEPictureImpl_get_CurDC
555 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
556 HDC *phdc)
558 ICOM_THIS(OLEPictureImpl, iface);
559 TRACE("(%p), returning %x\n", This, This->hDCCur);
560 if (phdc) *phdc = This->hDCCur;
561 return S_OK;
564 /************************************************************************
565 * OLEPictureImpl_SelectPicture
567 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
568 HDC hdcIn,
569 HDC *phdcOut,
570 OLE_HANDLE *phbmpOut)
572 ICOM_THIS(OLEPictureImpl, iface);
573 TRACE("(%p)->(%08x, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
574 if (This->desc.picType == PICTYPE_BITMAP) {
575 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
577 if (phdcOut)
578 *phdcOut = This->hDCCur;
579 This->hDCCur = hdcIn;
580 if (phbmpOut)
581 *phbmpOut = This->desc.u.bmp.hbitmap;
582 return S_OK;
583 } else {
584 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
585 return E_FAIL;
589 /************************************************************************
590 * OLEPictureImpl_get_KeepOriginalFormat
592 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
593 BOOL *pfKeep)
595 ICOM_THIS(OLEPictureImpl, iface);
596 TRACE("(%p)->(%p)\n", This, pfKeep);
597 if (!pfKeep)
598 return E_POINTER;
599 *pfKeep = This->keepOrigFormat;
600 return S_OK;
603 /************************************************************************
604 * OLEPictureImpl_put_KeepOriginalFormat
606 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
607 BOOL keep)
609 ICOM_THIS(OLEPictureImpl, iface);
610 TRACE("(%p)->(%d)\n", This, keep);
611 This->keepOrigFormat = keep;
612 /* FIXME: what DISPID notification here? */
613 return S_OK;
616 /************************************************************************
617 * OLEPictureImpl_PictureChanged
619 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
621 ICOM_THIS(OLEPictureImpl, iface);
622 TRACE("(%p)->()\n", This);
623 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
624 return S_OK;
627 /************************************************************************
628 * OLEPictureImpl_SaveAsFile
630 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
631 IStream *pstream,
632 BOOL SaveMemCopy,
633 LONG *pcbSize)
635 ICOM_THIS(OLEPictureImpl, iface);
636 FIXME("(%p)->(%p, %d, %p): stub\n", This, pstream, SaveMemCopy, pcbSize);
637 return E_NOTIMPL;
640 /************************************************************************
641 * OLEPictureImpl_get_Attributes
643 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
644 DWORD *pdwAttr)
646 ICOM_THIS(OLEPictureImpl, iface);
647 TRACE("(%p)->(%p).\n", This, pdwAttr);
648 *pdwAttr = 0;
649 switch (This->desc.picType) {
650 case PICTYPE_BITMAP: break; /* not 'truely' scalable, see MSDN. */
651 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
652 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
653 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
655 return S_OK;
659 /************************************************************************
660 * IConnectionPointContainer
663 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
664 IConnectionPointContainer* iface,
665 REFIID riid,
666 VOID** ppvoid
668 ICOM_THIS_From_IConnectionPointContainer(IPicture,iface);
670 return IPicture_QueryInterface(This,riid,ppvoid);
673 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
674 IConnectionPointContainer* iface)
676 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
678 return IPicture_AddRef(This);
681 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
682 IConnectionPointContainer* iface)
684 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
686 return IPicture_Release(This);
689 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
690 IConnectionPointContainer* iface,
691 IEnumConnectionPoints** ppEnum
693 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
695 FIXME("(%p,%p), stub!\n",This,ppEnum);
696 return E_NOTIMPL;
699 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
700 IConnectionPointContainer* iface,
701 REFIID riid,
702 IConnectionPoint **ppCP
704 ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl, iface);
705 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
706 if (!ppCP)
707 return E_POINTER;
708 *ppCP = NULL;
709 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
710 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
711 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid));
712 return 0x80040200;
714 /************************************************************************
715 * IPersistStream
717 /************************************************************************
718 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
720 * See Windows documentation for more details on IUnknown methods.
722 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
723 IPersistStream* iface,
724 REFIID riid,
725 VOID** ppvoid)
727 ICOM_THIS_From_IPersistStream(IPicture, iface);
729 return IPicture_QueryInterface(This, riid, ppvoid);
732 /************************************************************************
733 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
735 * See Windows documentation for more details on IUnknown methods.
737 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
738 IPersistStream* iface)
740 ICOM_THIS_From_IPersistStream(IPicture, iface);
742 return IPicture_AddRef(This);
745 /************************************************************************
746 * OLEPictureImpl_IPersistStream_Release (IUnknown)
748 * See Windows documentation for more details on IUnknown methods.
750 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
751 IPersistStream* iface)
753 ICOM_THIS_From_IPersistStream(IPicture, iface);
755 return IPicture_Release(This);
758 /************************************************************************
759 * OLEPictureImpl_IPersistStream_GetClassID
761 static HRESULT WINAPI OLEPictureImpl_GetClassID(
762 IPersistStream* iface,CLSID* pClassID)
764 ICOM_THIS_From_IPersistStream(IPicture, iface);
765 FIXME("(%p),stub!\n",This);
766 return E_NOTIMPL;
769 /************************************************************************
770 * OLEPictureImpl_IPersistStream_IsDirty
772 static HRESULT WINAPI OLEPictureImpl_IsDirty(
773 IPersistStream* iface)
775 ICOM_THIS_From_IPersistStream(IPicture, iface);
776 FIXME("(%p),stub!\n",This);
777 return E_NOTIMPL;
780 #ifdef HAVE_LIBJPEG
781 /* for the jpeg decompressor source manager. */
782 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
784 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
785 ERR("(), should not get here.\n");
786 return FALSE;
789 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
790 ERR("(%ld), should not get here.\n",num_bytes);
793 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
794 ERR("(desired=%d), should not get here.\n",desired);
795 return FALSE;
797 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
798 #endif /* HAVE_LIBJPEG */
800 /************************************************************************
801 * OLEPictureImpl_IPersistStream_Load (IUnknown)
803 * Loads the binary data from the IStream. Starts at current position.
804 * There appears to be an 2 DWORD header:
805 * DWORD magic;
806 * DWORD len;
808 * Currently implemented: BITMAP, ICON, JPEG.
810 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
811 HRESULT hr = E_FAIL;
812 ULONG xread;
813 BYTE *xbuf;
814 DWORD header[2];
815 WORD magic;
816 ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
818 TRACE("(%p,%p)\n",This,pStm);
820 hr=IStream_Read(pStm,header,8,&xread);
821 if (hr || xread!=8) {
822 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
823 return hr;
825 xread = 0;
826 xbuf = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
827 while (xread < header[1]) {
828 ULONG nread;
829 hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
830 xread+=nread;
831 if (hr || !nread)
832 break;
834 if (xread != header[1])
835 FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
837 magic = xbuf[0] + (xbuf[1]<<8);
838 switch (magic) {
839 case 0xd8ff: { /* JPEG */
840 #ifdef HAVE_LIBJPEG
841 struct jpeg_decompress_struct jd;
842 struct jpeg_error_mgr jerr;
843 int ret;
844 JDIMENSION x;
845 JSAMPROW samprow;
846 BITMAPINFOHEADER bmi;
847 LPBYTE bits;
848 HDC hdcref;
849 struct jpeg_source_mgr xjsm;
851 /* This is basically so we can use in-memory data for jpeg decompression.
852 * We need to have all the functions.
854 xjsm.next_input_byte = xbuf;
855 xjsm.bytes_in_buffer = xread;
856 xjsm.init_source = _jpeg_init_source;
857 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
858 xjsm.skip_input_data = _jpeg_skip_input_data;
859 xjsm.resync_to_restart = _jpeg_resync_to_restart;
860 xjsm.term_source = _jpeg_term_source;
862 jd.err = jpeg_std_error(&jerr);
863 jpeg_create_decompress(&jd);
864 jd.src = &xjsm;
865 ret=jpeg_read_header(&jd,TRUE);
866 jpeg_start_decompress(&jd);
867 if (ret != JPEG_HEADER_OK) {
868 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
869 HeapFree(GetProcessHeap(),0,xbuf);
870 return E_FAIL;
872 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(jd.output_height+1)*jd.output_width*jd.output_components);
873 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
874 while ( jd.output_scanline<jd.output_height ) {
875 x = jpeg_read_scanlines(&jd,&samprow,1);
876 if (x != 1) {
877 FIXME("failed to read current scanline?\n");
878 break;
880 memcpy( bits+jd.output_scanline*jd.output_width*jd.output_components,
881 samprow,
882 jd.output_width*jd.output_components
885 bmi.biSize = sizeof(bmi);
886 bmi.biWidth = jd.output_width;
887 bmi.biHeight = -jd.output_height;
888 bmi.biPlanes = 1;
889 bmi.biBitCount = jd.output_components<<3;
890 bmi.biCompression = BI_RGB;
891 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
892 bmi.biXPelsPerMeter = 0;
893 bmi.biYPelsPerMeter = 0;
894 bmi.biClrUsed = 0;
895 bmi.biClrImportant = 0;
897 HeapFree(GetProcessHeap(),0,samprow);
898 jpeg_finish_decompress(&jd);
899 jpeg_destroy_decompress(&jd);
900 hdcref = GetDC(0);
901 This->desc.u.bmp.hbitmap=CreateDIBitmap(
902 hdcref,
903 &bmi,
904 CBM_INIT,
905 bits,
906 (BITMAPINFO*)&bmi,
907 DIB_RGB_COLORS
909 DeleteDC(hdcref);
910 This->desc.picType = PICTYPE_BITMAP;
911 OLEPictureImpl_SetBitmap(This);
912 hr = S_OK;
913 HeapFree(GetProcessHeap(),0,bits);
914 #else
915 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
916 hr = E_FAIL;
917 #endif
918 break;
920 case 0x4d42: { /* Bitmap */
921 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
922 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
923 HDC hdcref;
925 /* Does not matter whether this is a coreheader or not, we only use
926 * components which are in both
928 hdcref = GetDC(0);
929 This->desc.u.bmp.hbitmap = CreateDIBitmap(
930 hdcref,
931 &(bi->bmiHeader),
932 CBM_INIT,
933 xbuf+bfh->bfOffBits,
935 (bi->bmiHeader.biBitCount<=8)?DIB_PAL_COLORS:DIB_RGB_COLORS
937 DeleteDC(hdcref);
938 This->desc.picType = PICTYPE_BITMAP;
939 OLEPictureImpl_SetBitmap(This);
940 hr = S_OK;
941 break;
943 case 0x0000: { /* ICON , first word is dwReserved */
944 HICON hicon;
945 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
946 int i;
949 FIXME("icon.idReserved=%d\n",cifd->idReserved);
950 FIXME("icon.idType=%d\n",cifd->idType);
951 FIXME("icon.idCount=%d\n",cifd->idCount);
953 for (i=0;i<cifd->idCount;i++) {
954 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
955 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
956 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
957 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
958 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
959 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
960 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
961 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
964 i=0;
965 /* If we have more than one icon, try to find the best.
966 * this currently means '32 pixel wide'.
968 if (cifd->idCount!=1) {
969 for (i=0;i<cifd->idCount;i++) {
970 if (cifd->idEntries[i].bWidth == 32)
971 break;
973 if (i==cifd->idCount) i=0;
976 hicon = CreateIconFromResourceEx(
977 xbuf+cifd->idEntries[i].dwDIBOffset,
978 cifd->idEntries[i].dwDIBSize,
979 TRUE, /* is icon */
980 0x00030000,
981 cifd->idEntries[i].bWidth,
982 cifd->idEntries[i].bHeight,
985 if (!hicon) {
986 FIXME("CreateIcon failed.\n");
987 hr = E_FAIL;
988 } else {
989 This->desc.picType = PICTYPE_ICON;
990 This->desc.u.icon.hicon = hicon;
991 hr = S_OK;
993 break;
995 default:
996 FIXME("Unknown magic %04x\n",magic);
997 hr=E_FAIL;
998 break;
1000 HeapFree(GetProcessHeap(),0,xbuf);
1002 /* FIXME: this notify is not really documented */
1003 if (hr==S_OK)
1004 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1005 return hr;
1008 static HRESULT WINAPI OLEPictureImpl_Save(
1009 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1011 ICOM_THIS_From_IPersistStream(IPicture, iface);
1012 FIXME("(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
1013 return E_NOTIMPL;
1016 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1017 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1019 ICOM_THIS_From_IPersistStream(IPicture, iface);
1020 FIXME("(%p,%p),stub!\n",This,pcbSize);
1021 return E_NOTIMPL;
1024 /************************************************************************
1025 * IDispatch
1027 /************************************************************************
1028 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1030 * See Windows documentation for more details on IUnknown methods.
1032 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1033 IDispatch* iface,
1034 REFIID riid,
1035 VOID** ppvoid)
1037 ICOM_THIS_From_IDispatch(IPicture, iface);
1039 return IPicture_QueryInterface(This, riid, ppvoid);
1042 /************************************************************************
1043 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1045 * See Windows documentation for more details on IUnknown methods.
1047 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1048 IDispatch* iface)
1050 ICOM_THIS_From_IDispatch(IPicture, iface);
1052 return IPicture_AddRef(This);
1055 /************************************************************************
1056 * OLEPictureImpl_IDispatch_Release (IUnknown)
1058 * See Windows documentation for more details on IUnknown methods.
1060 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1061 IDispatch* iface)
1063 ICOM_THIS_From_IDispatch(IPicture, iface);
1065 return IPicture_Release(This);
1068 /************************************************************************
1069 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1071 * See Windows documentation for more details on IDispatch methods.
1073 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1074 IDispatch* iface,
1075 unsigned int* pctinfo)
1077 FIXME("():Stub\n");
1079 return E_NOTIMPL;
1082 /************************************************************************
1083 * OLEPictureImpl_GetTypeInfo (IDispatch)
1085 * See Windows documentation for more details on IDispatch methods.
1087 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1088 IDispatch* iface,
1089 UINT iTInfo,
1090 LCID lcid,
1091 ITypeInfo** ppTInfo)
1093 FIXME("():Stub\n");
1095 return E_NOTIMPL;
1098 /************************************************************************
1099 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1101 * See Windows documentation for more details on IDispatch methods.
1103 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1104 IDispatch* iface,
1105 REFIID riid,
1106 LPOLESTR* rgszNames,
1107 UINT cNames,
1108 LCID lcid,
1109 DISPID* rgDispId)
1111 FIXME("():Stub\n");
1113 return E_NOTIMPL;
1116 /************************************************************************
1117 * OLEPictureImpl_Invoke (IDispatch)
1119 * See Windows documentation for more details on IDispatch methods.
1121 static HRESULT WINAPI OLEPictureImpl_Invoke(
1122 IDispatch* iface,
1123 DISPID dispIdMember,
1124 REFIID riid,
1125 LCID lcid,
1126 WORD wFlags,
1127 DISPPARAMS* pDispParams,
1128 VARIANT* pVarResult,
1129 EXCEPINFO* pExepInfo,
1130 UINT* puArgErr)
1132 FIXME("(dispid: %ld):Stub\n",dispIdMember);
1134 VariantInit(pVarResult);
1135 V_VT(pVarResult) = VT_BOOL;
1136 V_UNION(pVarResult,boolVal) = FALSE;
1137 return S_OK;
1141 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable =
1143 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1144 OLEPictureImpl_QueryInterface,
1145 OLEPictureImpl_AddRef,
1146 OLEPictureImpl_Release,
1147 OLEPictureImpl_get_Handle,
1148 OLEPictureImpl_get_hPal,
1149 OLEPictureImpl_get_Type,
1150 OLEPictureImpl_get_Width,
1151 OLEPictureImpl_get_Height,
1152 OLEPictureImpl_Render,
1153 OLEPictureImpl_set_hPal,
1154 OLEPictureImpl_get_CurDC,
1155 OLEPictureImpl_SelectPicture,
1156 OLEPictureImpl_get_KeepOriginalFormat,
1157 OLEPictureImpl_put_KeepOriginalFormat,
1158 OLEPictureImpl_PictureChanged,
1159 OLEPictureImpl_SaveAsFile,
1160 OLEPictureImpl_get_Attributes
1163 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable =
1165 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1166 OLEPictureImpl_IDispatch_QueryInterface,
1167 OLEPictureImpl_IDispatch_AddRef,
1168 OLEPictureImpl_IDispatch_Release,
1169 OLEPictureImpl_GetTypeInfoCount,
1170 OLEPictureImpl_GetTypeInfo,
1171 OLEPictureImpl_GetIDsOfNames,
1172 OLEPictureImpl_Invoke
1175 static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable =
1177 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1178 OLEPictureImpl_IPersistStream_QueryInterface,
1179 OLEPictureImpl_IPersistStream_AddRef,
1180 OLEPictureImpl_IPersistStream_Release,
1181 OLEPictureImpl_GetClassID,
1182 OLEPictureImpl_IsDirty,
1183 OLEPictureImpl_Load,
1184 OLEPictureImpl_Save,
1185 OLEPictureImpl_GetSizeMax
1188 static ICOM_VTABLE(IConnectionPointContainer) OLEPictureImpl_IConnectionPointContainer_VTable =
1190 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1191 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
1192 OLEPictureImpl_IConnectionPointContainer_AddRef,
1193 OLEPictureImpl_IConnectionPointContainer_Release,
1194 OLEPictureImpl_EnumConnectionPoints,
1195 OLEPictureImpl_FindConnectionPoint
1198 /***********************************************************************
1199 * OleCreatePictureIndirect (OLEAUT32.419)
1201 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
1202 BOOL fOwn, LPVOID *ppvObj )
1204 OLEPictureImpl* newPict = NULL;
1205 HRESULT hr = S_OK;
1207 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
1210 * Sanity check
1212 if (ppvObj==0)
1213 return E_POINTER;
1215 *ppvObj = NULL;
1218 * Try to construct a new instance of the class.
1220 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
1222 if (newPict == NULL)
1223 return E_OUTOFMEMORY;
1226 * Make sure it supports the interface required by the caller.
1228 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
1231 * Release the reference obtained in the constructor. If
1232 * the QueryInterface was unsuccessful, it will free the class.
1234 IPicture_Release((IPicture*)newPict);
1236 return hr;
1240 /***********************************************************************
1241 * OleLoadPicture (OLEAUT32.418)
1243 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1244 REFIID riid, LPVOID *ppvObj )
1246 LPPERSISTSTREAM ps;
1247 IPicture *newpic;
1248 HRESULT hr;
1250 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
1251 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
1253 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
1254 if (hr)
1255 return hr;
1256 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
1257 if (hr) {
1258 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1259 IPicture_Release(newpic);
1260 *ppvObj = NULL;
1261 return hr;
1263 IPersistStream_Load(ps,lpstream);
1264 IPersistStream_Release(ps);
1265 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
1266 if (hr)
1267 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
1268 IPicture_Release(newpic);
1269 return hr;
1272 /***********************************************************************
1273 * OleLoadPictureEx (OLEAUT32.425)
1275 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1276 REFIID reed, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
1278 FIXME("(%p,%ld,%d,%p,%lx,%lx,%lx,%p), not implemented\n",
1279 lpstream, lSize, fRunmode, reed, xsiz, ysiz, flags, ppvObj);
1280 return S_OK;