Release 0.9.39.
[wine/gsoc-2012-control.git] / dlls / oleaut32 / olepicture.c
blob5d3a9f0d1e238e42d14899d59b5d37ba357b09cf
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 #define COBJMACROS
52 #define NONAMELESSUNION
53 #define NONAMELESSSTRUCT
55 #include "winerror.h"
56 #include "windef.h"
57 #include "winbase.h"
58 #include "wingdi.h"
59 #include "winuser.h"
60 #include "ole2.h"
61 #include "olectl.h"
62 #include "oleauto.h"
63 #include "connpt.h"
64 #include "urlmon.h"
65 #include "wine/debug.h"
66 #include "wine/unicode.h"
68 #include "wine/wingdi16.h"
70 #ifdef HAVE_JPEGLIB_H
71 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
72 #define XMD_H
73 #define UINT8 JPEG_UINT8
74 #define UINT16 JPEG_UINT16
75 #undef FAR
76 #define boolean jpeg_boolean
77 # include <jpeglib.h>
78 #undef jpeg_boolean
79 #undef UINT16
80 #ifndef SONAME_LIBJPEG
81 #define SONAME_LIBJPEG "libjpeg.so"
82 #endif
83 #endif
85 #include "ungif.h"
87 WINE_DEFAULT_DEBUG_CHANNEL(ole);
89 #include "pshpack1.h"
91 typedef struct {
92 BYTE bWidth;
93 BYTE bHeight;
94 BYTE bColorCount;
95 BYTE bReserved;
96 WORD xHotspot;
97 WORD yHotspot;
98 DWORD dwDIBSize;
99 DWORD dwDIBOffset;
100 } CURSORICONFILEDIRENTRY;
102 typedef struct
104 WORD idReserved;
105 WORD idType;
106 WORD idCount;
107 CURSORICONFILEDIRENTRY idEntries[1];
108 } CURSORICONFILEDIR;
110 #include "poppack.h"
112 /*************************************************************************
113 * Declaration of implementation class
116 typedef struct OLEPictureImpl {
119 * IPicture handles IUnknown
122 const IPictureVtbl *lpVtbl;
123 const IDispatchVtbl *lpvtblIDispatch;
124 const IPersistStreamVtbl *lpvtblIPersistStream;
125 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
127 /* Object reference count */
128 LONG ref;
130 /* We own the object and must destroy it ourselves */
131 BOOL fOwn;
133 /* Picture description */
134 PICTDESC desc;
136 /* These are the pixel size of a bitmap */
137 DWORD origWidth;
138 DWORD origHeight;
140 /* And these are the size of the picture converted into HIMETRIC units */
141 OLE_XSIZE_HIMETRIC himetricWidth;
142 OLE_YSIZE_HIMETRIC himetricHeight;
144 IConnectionPoint *pCP;
146 BOOL keepOrigFormat;
147 HDC hDCCur;
149 /* Bitmap transparency mask */
150 HBITMAP hbmMask;
151 HBITMAP hbmXor;
152 COLORREF rgbTrans;
154 /* data */
155 void* data;
156 int datalen;
157 BOOL bIsDirty; /* Set to TRUE if picture has changed */
158 unsigned int loadtime_magic; /* If a length header was found, saves value */
159 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
160 } OLEPictureImpl;
163 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
166 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
168 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
171 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
173 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
176 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
178 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
182 * Predeclare VTables. They get initialized at the end.
184 static const IPictureVtbl OLEPictureImpl_VTable;
185 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
186 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
187 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
189 /***********************************************************************
190 * Implementation of the OLEPictureImpl class.
193 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
194 BITMAP bm;
195 HDC hdcRef;
197 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
198 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
199 ERR("GetObject fails\n");
200 return;
202 This->origWidth = bm.bmWidth;
203 This->origHeight = bm.bmHeight;
204 /* The width and height are stored in HIMETRIC units (0.01 mm),
205 so we take our pixel width divide by pixels per inch and
206 multiply by 25.4 * 100 */
207 /* Should we use GetBitmapDimension if available? */
208 hdcRef = CreateCompatibleDC(0);
209 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
210 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
211 DeleteDC(hdcRef);
214 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
216 ICONINFO infoIcon;
218 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
219 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
220 HDC hdcRef;
221 BITMAP bm;
223 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
224 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
225 ERR("GetObject fails on icon bitmap\n");
226 return;
229 This->origWidth = bm.bmWidth;
230 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
231 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
232 hdcRef = GetDC(0);
233 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
234 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
235 ReleaseDC(0, hdcRef);
237 DeleteObject(infoIcon.hbmMask);
238 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
239 } else {
240 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
244 /************************************************************************
245 * OLEPictureImpl_Construct
247 * This method will construct a new instance of the OLEPictureImpl
248 * class.
250 * The caller of this method must release the object when it's
251 * done with it.
253 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
255 OLEPictureImpl* newObject = 0;
257 if (pictDesc)
258 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
261 * Allocate space for the object.
263 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
265 if (newObject==0)
266 return newObject;
269 * Initialize the virtual function table.
271 newObject->lpVtbl = &OLEPictureImpl_VTable;
272 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
273 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
274 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
276 newObject->pCP = NULL;
277 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
278 if (!newObject->pCP)
280 HeapFree(GetProcessHeap(), 0, newObject);
281 return NULL;
285 * Start with one reference count. The caller of this function
286 * must release the interface pointer when it is done.
288 newObject->ref = 1;
289 newObject->hDCCur = 0;
291 newObject->fOwn = fOwn;
293 /* dunno about original value */
294 newObject->keepOrigFormat = TRUE;
296 newObject->hbmMask = NULL;
297 newObject->hbmXor = NULL;
298 newObject->loadtime_magic = 0xdeadbeef;
299 newObject->loadtime_format = 0;
300 newObject->bIsDirty = FALSE;
302 if (pictDesc) {
303 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
305 switch(pictDesc->picType) {
306 case PICTYPE_BITMAP:
307 OLEPictureImpl_SetBitmap(newObject);
308 break;
310 case PICTYPE_METAFILE:
311 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
312 newObject->himetricWidth = pictDesc->u.wmf.xExt;
313 newObject->himetricHeight = pictDesc->u.wmf.yExt;
314 break;
316 case PICTYPE_NONE:
317 /* not sure what to do here */
318 newObject->himetricWidth = newObject->himetricHeight = 0;
319 break;
321 case PICTYPE_ICON:
322 OLEPictureImpl_SetIcon(newObject);
323 break;
324 case PICTYPE_ENHMETAFILE:
325 default:
326 FIXME("Unsupported type %d\n", pictDesc->picType);
327 newObject->himetricWidth = newObject->himetricHeight = 0;
328 break;
330 } else {
331 newObject->desc.picType = PICTYPE_UNINITIALIZED;
334 TRACE("returning %p\n", newObject);
335 return newObject;
338 /************************************************************************
339 * OLEPictureImpl_Destroy
341 * This method is called by the Release method when the reference
342 * count goes down to 0. It will free all resources used by
343 * this object. */
344 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
346 TRACE("(%p)\n", Obj);
348 if (Obj->pCP)
349 IConnectionPoint_Release(Obj->pCP);
351 if(Obj->fOwn) { /* We need to destroy the picture */
352 switch(Obj->desc.picType) {
353 case PICTYPE_BITMAP:
354 DeleteObject(Obj->desc.u.bmp.hbitmap);
355 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
356 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
357 break;
358 case PICTYPE_METAFILE:
359 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
360 break;
361 case PICTYPE_ICON:
362 DestroyIcon(Obj->desc.u.icon.hicon);
363 break;
364 case PICTYPE_ENHMETAFILE:
365 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
366 break;
367 case PICTYPE_NONE:
368 case PICTYPE_UNINITIALIZED:
369 /* Nothing to do */
370 break;
371 default:
372 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
373 break;
376 HeapFree(GetProcessHeap(), 0, Obj->data);
377 HeapFree(GetProcessHeap(), 0, Obj);
381 /************************************************************************
382 * OLEPictureImpl_AddRef (IUnknown)
384 * See Windows documentation for more details on IUnknown methods.
386 static ULONG WINAPI OLEPictureImpl_AddRef(
387 IPicture* iface)
389 OLEPictureImpl *This = (OLEPictureImpl *)iface;
390 ULONG refCount = InterlockedIncrement(&This->ref);
392 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
394 return refCount;
397 /************************************************************************
398 * OLEPictureImpl_Release (IUnknown)
400 * See Windows documentation for more details on IUnknown methods.
402 static ULONG WINAPI OLEPictureImpl_Release(
403 IPicture* iface)
405 OLEPictureImpl *This = (OLEPictureImpl *)iface;
406 ULONG refCount = InterlockedDecrement(&This->ref);
408 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
411 * If the reference count goes down to 0, perform suicide.
413 if (!refCount) OLEPictureImpl_Destroy(This);
415 return refCount;
418 /************************************************************************
419 * OLEPictureImpl_QueryInterface (IUnknown)
421 * See Windows documentation for more details on IUnknown methods.
423 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
424 IPicture* iface,
425 REFIID riid,
426 void** ppvObject)
428 OLEPictureImpl *This = (OLEPictureImpl *)iface;
429 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
432 * Perform a sanity check on the parameters.
434 if ( (This==0) || (ppvObject==0) )
435 return E_INVALIDARG;
438 * Initialize the return parameter.
440 *ppvObject = 0;
443 * Compare the riid with the interface IDs implemented by this object.
445 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
446 *ppvObject = (IPicture*)This;
447 else if (IsEqualIID(&IID_IDispatch, riid))
448 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
449 else if (IsEqualIID(&IID_IPictureDisp, riid))
450 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
451 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
452 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
453 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
454 *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
457 * Check that we obtained an interface.
459 if ((*ppvObject)==0)
461 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
462 return E_NOINTERFACE;
466 * Query Interface always increases the reference count by one when it is
467 * successful
469 OLEPictureImpl_AddRef((IPicture*)This);
471 return S_OK;
474 /***********************************************************************
475 * OLEPicture_SendNotify (internal)
477 * Sends notification messages of changed properties to any interested
478 * connections.
480 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
482 IEnumConnections *pEnum;
483 CONNECTDATA CD;
485 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
486 return;
487 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
488 IPropertyNotifySink *sink;
490 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
491 IPropertyNotifySink_OnChanged(sink, dispID);
492 IPropertyNotifySink_Release(sink);
493 IUnknown_Release(CD.pUnk);
495 IEnumConnections_Release(pEnum);
496 return;
499 /************************************************************************
500 * OLEPictureImpl_get_Handle
502 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
503 OLE_HANDLE *phandle)
505 OLEPictureImpl *This = (OLEPictureImpl *)iface;
506 TRACE("(%p)->(%p)\n", This, phandle);
507 switch(This->desc.picType) {
508 case PICTYPE_NONE:
509 case PICTYPE_UNINITIALIZED:
510 *phandle = 0;
511 break;
512 case PICTYPE_BITMAP:
513 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
514 break;
515 case PICTYPE_METAFILE:
516 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
517 break;
518 case PICTYPE_ICON:
519 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
520 break;
521 case PICTYPE_ENHMETAFILE:
522 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
523 break;
524 default:
525 FIXME("Unimplemented type %d\n", This->desc.picType);
526 return E_NOTIMPL;
528 TRACE("returning handle %08x\n", *phandle);
529 return S_OK;
532 /************************************************************************
533 * OLEPictureImpl_get_hPal
535 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
536 OLE_HANDLE *phandle)
538 OLEPictureImpl *This = (OLEPictureImpl *)iface;
539 HRESULT hres;
540 TRACE("(%p)->(%p)\n", This, phandle);
542 if (!phandle)
543 return E_POINTER;
545 switch (This->desc.picType) {
546 case PICTYPE_UNINITIALIZED:
547 case PICTYPE_NONE:
548 *phandle = 0;
549 hres = S_FALSE;
550 break;
551 case PICTYPE_BITMAP:
552 *phandle = (OLE_HANDLE)This->desc.u.bmp.hpal;
553 hres = S_OK;
554 break;
555 case PICTYPE_ICON:
556 case PICTYPE_METAFILE:
557 case PICTYPE_ENHMETAFILE:
558 default:
559 FIXME("unimplemented for type %d. Returning 0 palette.\n",
560 This->desc.picType);
561 *phandle = 0;
562 hres = S_OK;
565 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
566 return hres;
569 /************************************************************************
570 * OLEPictureImpl_get_Type
572 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
573 short *ptype)
575 OLEPictureImpl *This = (OLEPictureImpl *)iface;
576 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
577 *ptype = This->desc.picType;
578 return S_OK;
581 /************************************************************************
582 * OLEPictureImpl_get_Width
584 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
585 OLE_XSIZE_HIMETRIC *pwidth)
587 OLEPictureImpl *This = (OLEPictureImpl *)iface;
588 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
589 *pwidth = This->himetricWidth;
590 return S_OK;
593 /************************************************************************
594 * OLEPictureImpl_get_Height
596 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
597 OLE_YSIZE_HIMETRIC *pheight)
599 OLEPictureImpl *This = (OLEPictureImpl *)iface;
600 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
601 *pheight = This->himetricHeight;
602 return S_OK;
605 /************************************************************************
606 * OLEPictureImpl_Render
608 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
609 LONG x, LONG y, LONG cx, LONG cy,
610 OLE_XPOS_HIMETRIC xSrc,
611 OLE_YPOS_HIMETRIC ySrc,
612 OLE_XSIZE_HIMETRIC cxSrc,
613 OLE_YSIZE_HIMETRIC cySrc,
614 LPCRECT prcWBounds)
616 OLEPictureImpl *This = (OLEPictureImpl *)iface;
617 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
618 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
619 if(prcWBounds)
620 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
621 prcWBounds->right, prcWBounds->bottom);
624 * While the documentation suggests this to be here (or after rendering?)
625 * it does cause an endless recursion in my sample app. -MM 20010804
626 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
629 switch(This->desc.picType) {
630 case PICTYPE_BITMAP:
632 HBITMAP hbmpOld;
633 HDC hdcBmp;
635 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
636 NB y-axis gets flipped */
638 hdcBmp = CreateCompatibleDC(0);
639 SetMapMode(hdcBmp, MM_ANISOTROPIC);
640 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
641 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
642 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
643 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
645 if (This->hbmMask) {
646 HDC hdcMask = CreateCompatibleDC(0);
647 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
649 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
651 SetMapMode(hdcMask, MM_ANISOTROPIC);
652 SetWindowOrgEx(hdcMask, 0, 0, NULL);
653 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
654 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
655 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
657 SetBkColor(hdc, RGB(255, 255, 255));
658 SetTextColor(hdc, RGB(0, 0, 0));
659 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
660 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
662 SelectObject(hdcMask, hOldbm);
663 DeleteDC(hdcMask);
664 } else {
665 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
666 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
669 SelectObject(hdcBmp, hbmpOld);
670 DeleteDC(hdcBmp);
672 break;
673 case PICTYPE_ICON:
674 FIXME("Not quite correct implementation of rendering icons...\n");
675 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
676 break;
678 case PICTYPE_METAFILE:
679 PlayMetaFile(hdc, This->desc.u.wmf.hmeta);
680 break;
682 case PICTYPE_ENHMETAFILE:
684 RECT rc = { x, y, cx, cy };
685 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
686 break;
689 default:
690 FIXME("type %d not implemented\n", This->desc.picType);
691 return E_NOTIMPL;
693 return S_OK;
696 /************************************************************************
697 * OLEPictureImpl_set_hPal
699 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
700 OLE_HANDLE hpal)
702 OLEPictureImpl *This = (OLEPictureImpl *)iface;
703 FIXME("(%p)->(%08x): stub\n", This, hpal);
704 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
705 return E_NOTIMPL;
708 /************************************************************************
709 * OLEPictureImpl_get_CurDC
711 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
712 HDC *phdc)
714 OLEPictureImpl *This = (OLEPictureImpl *)iface;
715 TRACE("(%p), returning %p\n", This, This->hDCCur);
716 if (phdc) *phdc = This->hDCCur;
717 return S_OK;
720 /************************************************************************
721 * OLEPictureImpl_SelectPicture
723 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
724 HDC hdcIn,
725 HDC *phdcOut,
726 OLE_HANDLE *phbmpOut)
728 OLEPictureImpl *This = (OLEPictureImpl *)iface;
729 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
730 if (This->desc.picType == PICTYPE_BITMAP) {
731 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
733 if (phdcOut)
734 *phdcOut = This->hDCCur;
735 This->hDCCur = hdcIn;
736 if (phbmpOut)
737 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
738 return S_OK;
739 } else {
740 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
741 return E_FAIL;
745 /************************************************************************
746 * OLEPictureImpl_get_KeepOriginalFormat
748 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
749 BOOL *pfKeep)
751 OLEPictureImpl *This = (OLEPictureImpl *)iface;
752 TRACE("(%p)->(%p)\n", This, pfKeep);
753 if (!pfKeep)
754 return E_POINTER;
755 *pfKeep = This->keepOrigFormat;
756 return S_OK;
759 /************************************************************************
760 * OLEPictureImpl_put_KeepOriginalFormat
762 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
763 BOOL keep)
765 OLEPictureImpl *This = (OLEPictureImpl *)iface;
766 TRACE("(%p)->(%d)\n", This, keep);
767 This->keepOrigFormat = keep;
768 /* FIXME: what DISPID notification here? */
769 return S_OK;
772 /************************************************************************
773 * OLEPictureImpl_PictureChanged
775 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
777 OLEPictureImpl *This = (OLEPictureImpl *)iface;
778 TRACE("(%p)->()\n", This);
779 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
780 This->bIsDirty = TRUE;
781 return S_OK;
784 /************************************************************************
785 * OLEPictureImpl_SaveAsFile
787 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
788 IStream *pstream,
789 BOOL SaveMemCopy,
790 LONG *pcbSize)
792 OLEPictureImpl *This = (OLEPictureImpl *)iface;
793 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
794 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
797 /************************************************************************
798 * OLEPictureImpl_get_Attributes
800 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
801 DWORD *pdwAttr)
803 OLEPictureImpl *This = (OLEPictureImpl *)iface;
804 TRACE("(%p)->(%p).\n", This, pdwAttr);
805 *pdwAttr = 0;
806 switch (This->desc.picType) {
807 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
808 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
809 case PICTYPE_ENHMETAFILE: /* fall through */
810 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
811 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
813 return S_OK;
817 /************************************************************************
818 * IConnectionPointContainer
820 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
821 IConnectionPointContainer* iface,
822 REFIID riid,
823 VOID** ppvoid)
825 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
827 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
830 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
831 IConnectionPointContainer* iface)
833 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
835 return IPicture_AddRef((IPicture *)This);
838 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
839 IConnectionPointContainer* iface)
841 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
843 return IPicture_Release((IPicture *)This);
846 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
847 IConnectionPointContainer* iface,
848 IEnumConnectionPoints** ppEnum)
850 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
852 FIXME("(%p,%p), stub!\n",This,ppEnum);
853 return E_NOTIMPL;
856 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
857 IConnectionPointContainer* iface,
858 REFIID riid,
859 IConnectionPoint **ppCP)
861 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
862 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
863 if (!ppCP)
864 return E_POINTER;
865 *ppCP = NULL;
866 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
867 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
868 FIXME("no connection point for %s\n",debugstr_guid(riid));
869 return CONNECT_E_NOCONNECTION;
873 /************************************************************************
874 * IPersistStream
877 /************************************************************************
878 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
880 * See Windows documentation for more details on IUnknown methods.
882 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
883 IPersistStream* iface,
884 REFIID riid,
885 VOID** ppvoid)
887 OLEPictureImpl *This = impl_from_IPersistStream(iface);
889 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
892 /************************************************************************
893 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
895 * See Windows documentation for more details on IUnknown methods.
897 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
898 IPersistStream* iface)
900 OLEPictureImpl *This = impl_from_IPersistStream(iface);
902 return IPicture_AddRef((IPicture *)This);
905 /************************************************************************
906 * OLEPictureImpl_IPersistStream_Release (IUnknown)
908 * See Windows documentation for more details on IUnknown methods.
910 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
911 IPersistStream* iface)
913 OLEPictureImpl *This = impl_from_IPersistStream(iface);
915 return IPicture_Release((IPicture *)This);
918 /************************************************************************
919 * OLEPictureImpl_IPersistStream_GetClassID
921 static HRESULT WINAPI OLEPictureImpl_GetClassID(
922 IPersistStream* iface,CLSID* pClassID)
924 TRACE("(%p)\n", pClassID);
925 memcpy(pClassID, &CLSID_StdPicture, sizeof(*pClassID));
926 return S_OK;
929 /************************************************************************
930 * OLEPictureImpl_IPersistStream_IsDirty
932 static HRESULT WINAPI OLEPictureImpl_IsDirty(
933 IPersistStream* iface)
935 OLEPictureImpl *This = impl_from_IPersistStream(iface);
936 FIXME("(%p),stub!\n",This);
937 return E_NOTIMPL;
940 #ifdef HAVE_JPEGLIB_H
942 static void *libjpeg_handle;
943 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
944 MAKE_FUNCPTR(jpeg_std_error);
945 MAKE_FUNCPTR(jpeg_CreateDecompress);
946 MAKE_FUNCPTR(jpeg_read_header);
947 MAKE_FUNCPTR(jpeg_start_decompress);
948 MAKE_FUNCPTR(jpeg_read_scanlines);
949 MAKE_FUNCPTR(jpeg_finish_decompress);
950 MAKE_FUNCPTR(jpeg_destroy_decompress);
951 #undef MAKE_FUNCPTR
953 static void *load_libjpeg(void)
955 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
957 #define LOAD_FUNCPTR(f) \
958 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
959 libjpeg_handle = NULL; \
960 return NULL; \
963 LOAD_FUNCPTR(jpeg_std_error);
964 LOAD_FUNCPTR(jpeg_CreateDecompress);
965 LOAD_FUNCPTR(jpeg_read_header);
966 LOAD_FUNCPTR(jpeg_start_decompress);
967 LOAD_FUNCPTR(jpeg_read_scanlines);
968 LOAD_FUNCPTR(jpeg_finish_decompress);
969 LOAD_FUNCPTR(jpeg_destroy_decompress);
970 #undef LOAD_FUNCPTR
972 return libjpeg_handle;
975 /* for the jpeg decompressor source manager. */
976 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
978 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
979 ERR("(), should not get here.\n");
980 return FALSE;
983 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
984 TRACE("Skipping %ld bytes...\n", num_bytes);
985 cinfo->src->next_input_byte += num_bytes;
986 cinfo->src->bytes_in_buffer -= num_bytes;
989 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
990 ERR("(desired=%d), should not get here.\n",desired);
991 return FALSE;
993 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
994 #endif /* HAVE_JPEGLIB_H */
996 struct gifdata {
997 unsigned char *data;
998 unsigned int curoff;
999 unsigned int len;
1002 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
1003 struct gifdata *gd = (struct gifdata*)gif->UserData;
1005 if (len+gd->curoff > gd->len) {
1006 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
1007 len = gd->len - gd->curoff;
1009 memcpy(data, gd->data+gd->curoff, len);
1010 gd->curoff += len;
1011 return len;
1015 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1017 struct gifdata gd;
1018 GifFileType *gif;
1019 BITMAPINFO *bmi;
1020 HDC hdcref;
1021 LPBYTE bytes;
1022 int i,j,ret;
1023 GifImageDesc *gid;
1024 SavedImage *si;
1025 ColorMapObject *cm;
1026 int transparent = -1;
1027 ExtensionBlock *eb;
1028 int padding;
1030 gd.data = xbuf;
1031 gd.curoff = 0;
1032 gd.len = xread;
1033 gif = DGifOpen((void*)&gd, _gif_inputfunc);
1034 ret = DGifSlurp(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 si = gif->SavedImages+0;
1054 gid = &(si->ImageDesc);
1055 cm = gid->ColorMap;
1056 if (!cm) cm = gif->SColorMap;
1057 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1058 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
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 = (unsigned char)eb->Bytes[3];
1070 for (i = 0; i < cm->ColorCount; 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, j = 0; i < gid->Height; i++) {
1083 if (gif->Image.Interlace) {
1084 memcpy(
1085 bytes + (gid->Top + j) * padding + gid->Left,
1086 si->RasterBits + i * gid->Width,
1087 gid->Width);
1089 /* Lower bits of interlaced counter encode current interlace */
1090 if (j & 1) j += 2; /* Currently filling odd rows */
1091 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1092 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1094 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1095 /* End of current interlace, go to next interlace */
1096 if (j & 2) j = 1; /* Next iteration fills odd rows */
1097 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1098 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1100 } else {
1101 memcpy(
1102 bytes + (gid->Top + i) * padding + gid->Left,
1103 si->RasterBits + i * gid->Width,
1104 gid->Width);
1108 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1109 bmi->bmiHeader.biWidth = gif->SWidth;
1110 bmi->bmiHeader.biHeight = -gif->SHeight;
1111 bmi->bmiHeader.biPlanes = 1;
1112 bmi->bmiHeader.biBitCount = 8;
1113 bmi->bmiHeader.biCompression = BI_RGB;
1114 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1115 bmi->bmiHeader.biXPelsPerMeter = 0;
1116 bmi->bmiHeader.biYPelsPerMeter = 0;
1117 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1118 bmi->bmiHeader.biClrImportant = 0;
1120 hdcref = GetDC(0);
1121 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1122 hdcref,
1123 &bmi->bmiHeader,
1124 CBM_INIT,
1125 bytes,
1126 bmi,
1127 DIB_RGB_COLORS
1130 if (transparent > -1) {
1131 /* Create the Mask */
1132 HDC hdc = CreateCompatibleDC(0);
1133 HDC hdcMask = CreateCompatibleDC(0);
1134 HBITMAP hOldbitmap;
1135 HBITMAP hOldbitmapmask;
1137 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1138 HBITMAP hTempMask;
1140 This->hbmXor = CreateDIBitmap(
1141 hdcref,
1142 &bmi->bmiHeader,
1143 CBM_INIT,
1144 bytes,
1145 bmi,
1146 DIB_RGB_COLORS
1149 bmi->bmiColors[0].rgbRed = 0;
1150 bmi->bmiColors[0].rgbGreen = 0;
1151 bmi->bmiColors[0].rgbBlue = 0;
1152 bmi->bmiColors[1].rgbRed = 255;
1153 bmi->bmiColors[1].rgbGreen = 255;
1154 bmi->bmiColors[1].rgbBlue = 255;
1156 bmi->bmiHeader.biBitCount = 1;
1157 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1158 bmi->bmiHeader.biClrUsed = 2;
1160 for (i = 0; i < gif->SHeight; i++) {
1161 unsigned char * colorPointer = bytes + padding * i;
1162 unsigned char * monoPointer = bytes + monopadding * i;
1163 for (j = 0; j < gif->SWidth; j++) {
1164 unsigned char pixel = colorPointer[j];
1165 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1166 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1169 hdcref = GetDC(0);
1170 hTempMask = CreateDIBitmap(
1171 hdcref,
1172 &bmi->bmiHeader,
1173 CBM_INIT,
1174 bytes,
1175 bmi,
1176 DIB_RGB_COLORS
1178 DeleteDC(hdcref);
1180 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1181 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1182 hOldbitmap = SelectObject(hdc, hTempMask);
1183 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1185 SetBkColor(hdc, RGB(255, 255, 255));
1186 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1188 /* We no longer need the original bitmap, so we apply the first
1189 transformation with the mask to speed up the rendering */
1190 SelectObject(hdc, This->hbmXor);
1191 SetBkColor(hdc, RGB(0,0,0));
1192 SetTextColor(hdc, RGB(255,255,255));
1193 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1194 hdcMask, 0, 0, SRCAND);
1196 SelectObject(hdc, hOldbitmap);
1197 SelectObject(hdcMask, hOldbitmapmask);
1198 DeleteDC(hdcMask);
1199 DeleteDC(hdc);
1200 DeleteObject(hTempMask);
1203 DeleteDC(hdcref);
1204 This->desc.picType = PICTYPE_BITMAP;
1205 OLEPictureImpl_SetBitmap(This);
1206 DGifCloseFile(gif);
1207 HeapFree(GetProcessHeap(),0,bytes);
1208 return S_OK;
1211 static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1213 #ifdef HAVE_JPEGLIB_H
1214 struct jpeg_decompress_struct jd;
1215 struct jpeg_error_mgr jerr;
1216 int ret;
1217 JDIMENSION x;
1218 JSAMPROW samprow,oldsamprow;
1219 BITMAPINFOHEADER bmi;
1220 LPBYTE bits;
1221 HDC hdcref;
1222 struct jpeg_source_mgr xjsm;
1223 LPBYTE oldbits;
1224 unsigned int i;
1226 if(!libjpeg_handle) {
1227 if(!load_libjpeg()) {
1228 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1229 return E_FAIL;
1233 /* This is basically so we can use in-memory data for jpeg decompression.
1234 * We need to have all the functions.
1236 xjsm.next_input_byte = xbuf;
1237 xjsm.bytes_in_buffer = xread;
1238 xjsm.init_source = _jpeg_init_source;
1239 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1240 xjsm.skip_input_data = _jpeg_skip_input_data;
1241 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1242 xjsm.term_source = _jpeg_term_source;
1244 jd.err = pjpeg_std_error(&jerr);
1245 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1246 * jpeg_create_decompress(&jd); */
1247 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1248 jd.src = &xjsm;
1249 ret=pjpeg_read_header(&jd,TRUE);
1250 jd.out_color_space = JCS_RGB;
1251 pjpeg_start_decompress(&jd);
1252 if (ret != JPEG_HEADER_OK) {
1253 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1254 HeapFree(GetProcessHeap(),0,xbuf);
1255 return E_FAIL;
1258 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1259 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1260 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1262 oldbits = bits;
1263 oldsamprow = samprow;
1264 while ( jd.output_scanline<jd.output_height ) {
1265 x = pjpeg_read_scanlines(&jd,&samprow,1);
1266 if (x != 1) {
1267 FIXME("failed to read current scanline?\n");
1268 break;
1270 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1271 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1272 *(bits++) = *(samprow+2);
1273 *(bits++) = *(samprow+1);
1274 *(bits++) = *(samprow);
1276 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1277 samprow = oldsamprow;
1279 bits = oldbits;
1281 bmi.biSize = sizeof(bmi);
1282 bmi.biWidth = jd.output_width;
1283 bmi.biHeight = -jd.output_height;
1284 bmi.biPlanes = 1;
1285 bmi.biBitCount = jd.output_components<<3;
1286 bmi.biCompression = BI_RGB;
1287 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1288 bmi.biXPelsPerMeter = 0;
1289 bmi.biYPelsPerMeter = 0;
1290 bmi.biClrUsed = 0;
1291 bmi.biClrImportant = 0;
1293 HeapFree(GetProcessHeap(),0,samprow);
1294 pjpeg_finish_decompress(&jd);
1295 pjpeg_destroy_decompress(&jd);
1296 hdcref = GetDC(0);
1297 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1298 hdcref,
1299 &bmi,
1300 CBM_INIT,
1301 bits,
1302 (BITMAPINFO*)&bmi,
1303 DIB_RGB_COLORS
1305 DeleteDC(hdcref);
1306 This->desc.picType = PICTYPE_BITMAP;
1307 OLEPictureImpl_SetBitmap(This);
1308 HeapFree(GetProcessHeap(),0,bits);
1309 return S_OK;
1310 #else
1311 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1312 return E_FAIL;
1313 #endif
1316 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1318 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1319 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1320 HDC hdcref;
1322 /* Does not matter whether this is a coreheader or not, we only use
1323 * components which are in both
1325 hdcref = GetDC(0);
1326 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1327 hdcref,
1328 &(bi->bmiHeader),
1329 CBM_INIT,
1330 xbuf+bfh->bfOffBits,
1332 DIB_RGB_COLORS
1334 DeleteDC(hdcref);
1335 This->desc.picType = PICTYPE_BITMAP;
1336 OLEPictureImpl_SetBitmap(This);
1337 return S_OK;
1340 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1342 HICON hicon;
1343 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1344 HDC hdcRef;
1345 int i;
1348 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1349 FIXME("icon.idType=%d\n",cifd->idType);
1350 FIXME("icon.idCount=%d\n",cifd->idCount);
1352 for (i=0;i<cifd->idCount;i++) {
1353 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1354 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1355 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1356 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1357 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1358 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1359 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1360 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1363 i=0;
1364 /* If we have more than one icon, try to find the best.
1365 * this currently means '32 pixel wide'.
1367 if (cifd->idCount!=1) {
1368 for (i=0;i<cifd->idCount;i++) {
1369 if (cifd->idEntries[i].bWidth == 32)
1370 break;
1372 if (i==cifd->idCount) i=0;
1375 hicon = CreateIconFromResourceEx(
1376 xbuf+cifd->idEntries[i].dwDIBOffset,
1377 cifd->idEntries[i].dwDIBSize,
1378 TRUE, /* is icon */
1379 0x00030000,
1380 cifd->idEntries[i].bWidth,
1381 cifd->idEntries[i].bHeight,
1384 if (!hicon) {
1385 FIXME("CreateIcon failed.\n");
1386 return E_FAIL;
1387 } else {
1388 This->desc.picType = PICTYPE_ICON;
1389 This->desc.u.icon.hicon = hicon;
1390 This->origWidth = cifd->idEntries[i].bWidth;
1391 This->origHeight = cifd->idEntries[i].bHeight;
1392 hdcRef = CreateCompatibleDC(0);
1393 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1394 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1395 DeleteDC(hdcRef);
1396 return S_OK;
1400 static HRESULT OLEPictureImpl_LoadMetafile(OLEPictureImpl *This,
1401 const BYTE *data, ULONG size)
1403 HMETAFILE hmf;
1404 HENHMETAFILE hemf;
1406 /* SetMetaFileBitsEx performs data check on its own */
1407 hmf = SetMetaFileBitsEx(size, data);
1408 if (hmf)
1410 This->desc.picType = PICTYPE_METAFILE;
1411 This->desc.u.wmf.hmeta = hmf;
1412 This->desc.u.wmf.xExt = 0;
1413 This->desc.u.wmf.yExt = 0;
1415 This->origWidth = 0;
1416 This->origHeight = 0;
1417 This->himetricWidth = 0;
1418 This->himetricHeight = 0;
1420 return S_OK;
1423 hemf = SetEnhMetaFileBits(size, data);
1424 if (!hemf) return E_FAIL;
1426 This->desc.picType = PICTYPE_ENHMETAFILE;
1427 This->desc.u.emf.hemf = hemf;
1429 This->origWidth = 0;
1430 This->origHeight = 0;
1431 This->himetricWidth = 0;
1432 This->himetricHeight = 0;
1434 return S_OK;
1437 /************************************************************************
1438 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1440 * Loads the binary data from the IStream. Starts at current position.
1441 * There appears to be an 2 DWORD header:
1442 * DWORD magic;
1443 * DWORD len;
1445 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1447 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1448 HRESULT hr = E_FAIL;
1449 BOOL headerisdata = FALSE;
1450 BOOL statfailed = FALSE;
1451 ULONG xread, toread;
1452 ULONG headerread;
1453 BYTE *xbuf;
1454 DWORD header[2];
1455 WORD magic;
1456 STATSTG statstg;
1457 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1459 TRACE("(%p,%p)\n",This,pStm);
1461 /****************************************************************************************
1462 * Part 1: Load the data
1464 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1465 * out whether we do.
1467 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1468 * compound file. This may explain most, if not all, of the cases of "no
1469 * header", and the header validation should take this into account.
1470 * At least in Visual Basic 6, resource streams, valid headers are
1471 * header[0] == "lt\0\0",
1472 * header[1] == length_of_stream.
1474 * Also handle streams where we do not have a working "Stat" method by
1475 * reading all data until the end of the stream.
1477 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1478 if (hr) {
1479 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1480 statfailed = TRUE;
1481 /* we will read at least 8 byte ... just right below */
1482 statstg.cbSize.QuadPart = 8;
1485 toread = 0;
1486 headerread = 0;
1487 headerisdata = FALSE;
1488 do {
1489 hr=IStream_Read(pStm,header,8,&xread);
1490 if (hr || xread!=8) {
1491 FIXME("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1492 return hr;
1494 headerread += xread;
1495 xread = 0;
1497 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1498 if (toread != 0 && toread != header[1])
1499 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1500 toread, header[1]);
1501 toread = header[1];
1502 if (toread == 0) break;
1503 } else {
1504 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1505 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1506 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1507 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1508 (header[1]==0)
1509 ) {/* Found start of bitmap data */
1510 headerisdata = TRUE;
1511 if (toread == 0)
1512 toread = statstg.cbSize.QuadPart-8;
1513 else toread -= 8;
1514 xread = 8;
1515 } else {
1516 FIXME("Unknown stream header magic: %08x\n", header[0]);
1517 toread = header[1];
1520 } while (!headerisdata);
1522 if (statfailed) { /* we don't know the size ... read all we get */
1523 int sizeinc = 4096;
1524 int origsize = sizeinc;
1525 ULONG nread = 42;
1527 TRACE("Reading all data from stream.\n");
1528 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1529 if (headerisdata)
1530 memcpy (xbuf, &header, 8);
1531 while (1) {
1532 while (xread < origsize) {
1533 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1534 xread+=nread;
1535 if (hr || !nread)
1536 break;
1538 if (!nread || hr) /* done, or error */
1539 break;
1540 if (xread == origsize) {
1541 origsize += sizeinc;
1542 sizeinc = 2*sizeinc; /* exponential increase */
1543 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1546 if (hr)
1547 TRACE("hr in no-stat loader case is %08x\n", hr);
1548 TRACE("loaded %d bytes.\n", xread);
1549 This->datalen = xread;
1550 This->data = xbuf;
1551 } else {
1552 This->datalen = toread+(headerisdata?8:0);
1553 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1555 if (headerisdata)
1556 memcpy (xbuf, &header, 8);
1558 while (xread < This->datalen) {
1559 ULONG nread;
1560 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1561 xread+=nread;
1562 if (hr || !nread)
1563 break;
1565 if (xread != This->datalen)
1566 FIXME("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1568 if (This->datalen == 0) { /* Marks the "NONE" picture */
1569 This->desc.picType = PICTYPE_NONE;
1570 return S_OK;
1574 /****************************************************************************************
1575 * Part 2: Process the loaded data
1578 magic = xbuf[0] + (xbuf[1]<<8);
1579 switch (magic) {
1580 case 0x4947: /* GIF */
1581 hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
1582 break;
1583 case 0xd8ff: /* JPEG */
1584 hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
1585 break;
1586 case 0x4d42: /* Bitmap */
1587 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1588 break;
1589 case 0x0000: { /* ICON , first word is dwReserved */
1590 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1591 break;
1593 default:
1595 unsigned int i;
1597 /* let's see if it's a metafile */
1598 hr = OLEPictureImpl_LoadMetafile(This, xbuf, xread);
1599 if (hr == S_OK) break;
1601 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1602 hr=E_FAIL;
1603 for (i=0;i<xread+8;i++) {
1604 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1605 else MESSAGE("%02x ",xbuf[i-8]);
1606 if (i % 10 == 9) MESSAGE("\n");
1608 MESSAGE("\n");
1609 break;
1612 This->bIsDirty = FALSE;
1614 /* FIXME: this notify is not really documented */
1615 if (hr==S_OK)
1616 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1617 return hr;
1620 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1622 int iSuccess = 0;
1623 HDC hDC;
1624 BITMAPINFO * pInfoBitmap;
1625 int iNumPaletteEntries;
1626 unsigned char * pPixelData;
1627 BITMAPFILEHEADER * pFileHeader;
1628 BITMAPINFO * pInfoHeader;
1630 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1631 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1633 /* Find out bitmap size and padded length */
1634 hDC = GetDC(0);
1635 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1636 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1638 /* Fetch bitmap palette & pixel data */
1640 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1641 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1643 /* Calculate the total length required for the BMP data */
1644 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1645 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1646 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1647 } else {
1648 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1649 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1650 else
1651 iNumPaletteEntries = 0;
1653 *pLength =
1654 sizeof(BITMAPFILEHEADER) +
1655 sizeof(BITMAPINFOHEADER) +
1656 iNumPaletteEntries * sizeof(RGBQUAD) +
1657 pInfoBitmap->bmiHeader.biSizeImage;
1658 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1660 /* Fill the BITMAPFILEHEADER */
1661 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1662 pFileHeader->bfType = 0x4d42;
1663 pFileHeader->bfSize = *pLength;
1664 pFileHeader->bfOffBits =
1665 sizeof(BITMAPFILEHEADER) +
1666 sizeof(BITMAPINFOHEADER) +
1667 iNumPaletteEntries * sizeof(RGBQUAD);
1669 /* Fill the BITMAPINFOHEADER and the palette data */
1670 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1671 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1672 memcpy(
1673 (unsigned char *)(*ppBuffer) +
1674 sizeof(BITMAPFILEHEADER) +
1675 sizeof(BITMAPINFOHEADER) +
1676 iNumPaletteEntries * sizeof(RGBQUAD),
1677 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1678 iSuccess = 1;
1680 HeapFree(GetProcessHeap(), 0, pPixelData);
1681 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1682 return iSuccess;
1685 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1687 ICONINFO infoIcon;
1688 int iSuccess = 0;
1690 *ppBuffer = NULL; *pLength = 0;
1691 if (GetIconInfo(hIcon, &infoIcon)) {
1692 HDC hDC;
1693 BITMAPINFO * pInfoBitmap;
1694 unsigned char * pIconData = NULL;
1695 unsigned int iDataSize = 0;
1697 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1699 /* Find out icon size */
1700 hDC = GetDC(0);
1701 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1702 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1703 if (1) {
1704 /* Auxiliary pointers */
1705 CURSORICONFILEDIR * pIconDir;
1706 CURSORICONFILEDIRENTRY * pIconEntry;
1707 BITMAPINFOHEADER * pIconBitmapHeader;
1708 unsigned int iOffsetPalette;
1709 unsigned int iOffsetColorData;
1710 unsigned int iOffsetMaskData;
1712 unsigned int iLengthScanLineColor;
1713 unsigned int iLengthScanLineMask;
1714 unsigned int iNumEntriesPalette;
1716 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1717 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1719 FIXME("DEBUG: bitmap size is %d x %d\n",
1720 pInfoBitmap->bmiHeader.biWidth,
1721 pInfoBitmap->bmiHeader.biHeight);
1722 FIXME("DEBUG: bitmap bpp is %d\n",
1723 pInfoBitmap->bmiHeader.biBitCount);
1724 FIXME("DEBUG: bitmap nplanes is %d\n",
1725 pInfoBitmap->bmiHeader.biPlanes);
1726 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1727 pInfoBitmap->bmiHeader.biSizeImage);
1729 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1730 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1731 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1733 /* Fill out the CURSORICONFILEDIR */
1734 pIconDir = (CURSORICONFILEDIR *)pIconData;
1735 pIconDir->idType = 1;
1736 pIconDir->idCount = 1;
1738 /* Fill out the CURSORICONFILEDIRENTRY */
1739 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1740 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1741 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1742 pIconEntry->bColorCount =
1743 (pInfoBitmap->bmiHeader.biBitCount < 8)
1744 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1745 : 0;
1746 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1747 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1748 pIconEntry->dwDIBSize = 0;
1749 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1751 /* Fill out the BITMAPINFOHEADER */
1752 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1753 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1755 /* Find out whether a palette exists for the bitmap */
1756 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1757 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1758 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1759 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1760 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1761 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1762 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1763 iNumEntriesPalette = 3;
1764 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1765 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1766 } else {
1767 iNumEntriesPalette = 0;
1770 /* Add bitmap size and header size to icon data size. */
1771 iOffsetPalette = iDataSize;
1772 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1773 iOffsetColorData = iDataSize;
1774 iDataSize += pIconBitmapHeader->biSizeImage;
1775 iOffsetMaskData = iDataSize;
1776 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1777 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1778 pIconBitmapHeader->biHeight *= 2;
1779 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1780 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1781 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1782 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1784 /* Get the actual bitmap data from the icon bitmap */
1785 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1786 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1787 if (iNumEntriesPalette > 0) {
1788 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1789 iNumEntriesPalette * sizeof(RGBQUAD));
1792 /* Reset all values so that GetDIBits call succeeds */
1793 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1794 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1795 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1797 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1798 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1799 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1801 printf("ERROR: unable to get bitmap mask (error %u)\n",
1802 GetLastError());
1806 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1807 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1809 /* Write out everything produced so far to the stream */
1810 *ppBuffer = pIconData; *pLength = iDataSize;
1811 iSuccess = 1;
1812 } else {
1814 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1815 GetLastError());
1819 Remarks (from MSDN entry on GetIconInfo):
1821 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1822 members of ICONINFO. The calling application must manage
1823 these bitmaps and delete them when they are no longer
1824 necessary.
1826 if (hDC) ReleaseDC(0, hDC);
1827 DeleteObject(infoIcon.hbmMask);
1828 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1829 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1830 } else {
1831 printf("ERROR: Unable to get icon information (error %u)\n",
1832 GetLastError());
1834 return iSuccess;
1837 static HRESULT WINAPI OLEPictureImpl_Save(
1838 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1840 HRESULT hResult = E_NOTIMPL;
1841 void * pIconData;
1842 unsigned int iDataSize;
1843 ULONG dummy;
1844 int iSerializeResult = 0;
1845 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1847 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1849 switch (This->desc.picType) {
1850 case PICTYPE_ICON:
1851 if (This->bIsDirty || !This->data) {
1852 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1853 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1854 hResult = E_FAIL;
1855 break;
1857 HeapFree(GetProcessHeap(), 0, This->data);
1858 This->data = pIconData;
1859 This->datalen = iDataSize;
1861 if (This->loadtime_magic != 0xdeadbeef) {
1862 DWORD header[2];
1864 header[0] = This->loadtime_magic;
1865 header[1] = This->datalen;
1866 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1868 IStream_Write(pStm, This->data, This->datalen, &dummy);
1870 hResult = S_OK;
1871 break;
1872 case PICTYPE_BITMAP:
1873 if (This->bIsDirty) {
1874 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1875 case 0x4d42:
1876 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1877 break;
1878 case 0xd8ff:
1879 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1880 break;
1881 case 0x4947:
1882 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1883 break;
1884 default:
1885 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1886 break;
1888 if (iSerializeResult) {
1890 if (This->loadtime_magic != 0xdeadbeef) {
1892 if (1) {
1893 DWORD header[2];
1895 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1896 header[1] = iDataSize;
1897 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1899 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1901 HeapFree(GetProcessHeap(), 0, This->data);
1902 This->data = pIconData;
1903 This->datalen = iDataSize;
1904 hResult = S_OK;
1906 } else {
1908 if (This->loadtime_magic != 0xdeadbeef) {
1910 if (1) {
1911 DWORD header[2];
1913 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1914 header[1] = This->datalen;
1915 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1917 IStream_Write(pStm, This->data, This->datalen, &dummy);
1918 hResult = S_OK;
1920 break;
1921 case PICTYPE_METAFILE:
1922 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1923 break;
1924 case PICTYPE_ENHMETAFILE:
1925 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1926 break;
1927 default:
1928 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1929 break;
1931 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1932 return hResult;
1935 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1936 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1938 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1939 FIXME("(%p,%p),stub!\n",This,pcbSize);
1940 return E_NOTIMPL;
1944 /************************************************************************
1945 * IDispatch
1948 /************************************************************************
1949 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1951 * See Windows documentation for more details on IUnknown methods.
1953 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1954 IDispatch* iface,
1955 REFIID riid,
1956 VOID** ppvoid)
1958 OLEPictureImpl *This = impl_from_IDispatch(iface);
1960 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1963 /************************************************************************
1964 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1966 * See Windows documentation for more details on IUnknown methods.
1968 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1969 IDispatch* iface)
1971 OLEPictureImpl *This = impl_from_IDispatch(iface);
1973 return IPicture_AddRef((IPicture *)This);
1976 /************************************************************************
1977 * OLEPictureImpl_IDispatch_Release (IUnknown)
1979 * See Windows documentation for more details on IUnknown methods.
1981 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1982 IDispatch* iface)
1984 OLEPictureImpl *This = impl_from_IDispatch(iface);
1986 return IPicture_Release((IPicture *)This);
1989 /************************************************************************
1990 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1992 * See Windows documentation for more details on IDispatch methods.
1994 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1995 IDispatch* iface,
1996 unsigned int* pctinfo)
1998 TRACE("(%p)\n", pctinfo);
2000 *pctinfo = 1;
2002 return S_OK;
2005 /************************************************************************
2006 * OLEPictureImpl_GetTypeInfo (IDispatch)
2008 * See Windows documentation for more details on IDispatch methods.
2010 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
2011 IDispatch* iface,
2012 UINT iTInfo,
2013 LCID lcid,
2014 ITypeInfo** ppTInfo)
2016 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
2017 ITypeLib *tl;
2018 HRESULT hres;
2020 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
2022 if (iTInfo != 0)
2023 return E_FAIL;
2025 hres = LoadTypeLib(stdole2tlb, &tl);
2026 if (FAILED(hres))
2028 ERR("Could not load stdole2.tlb\n");
2029 return hres;
2032 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
2033 if (FAILED(hres))
2034 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
2036 return hres;
2039 /************************************************************************
2040 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2042 * See Windows documentation for more details on IDispatch methods.
2044 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2045 IDispatch* iface,
2046 REFIID riid,
2047 LPOLESTR* rgszNames,
2048 UINT cNames,
2049 LCID lcid,
2050 DISPID* rgDispId)
2052 FIXME("():Stub\n");
2054 return E_NOTIMPL;
2057 /************************************************************************
2058 * OLEPictureImpl_Invoke (IDispatch)
2060 * See Windows documentation for more details on IDispatch methods.
2062 static HRESULT WINAPI OLEPictureImpl_Invoke(
2063 IDispatch* iface,
2064 DISPID dispIdMember,
2065 REFIID riid,
2066 LCID lcid,
2067 WORD wFlags,
2068 DISPPARAMS* pDispParams,
2069 VARIANT* pVarResult,
2070 EXCEPINFO* pExepInfo,
2071 UINT* puArgErr)
2073 OLEPictureImpl *This = impl_from_IDispatch(iface);
2075 /* validate parameters */
2077 if (!IsEqualIID(riid, &IID_NULL))
2079 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2080 return DISP_E_UNKNOWNNAME;
2083 if (!pDispParams)
2085 ERR("null pDispParams not allowed\n");
2086 return DISP_E_PARAMNOTOPTIONAL;
2089 if (wFlags & DISPATCH_PROPERTYGET)
2091 if (pDispParams->cArgs != 0)
2093 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2094 return DISP_E_BADPARAMCOUNT;
2096 if (!pVarResult)
2098 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2099 return DISP_E_PARAMNOTOPTIONAL;
2102 else if (wFlags & DISPATCH_PROPERTYPUT)
2104 if (pDispParams->cArgs != 1)
2106 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2107 return DISP_E_BADPARAMCOUNT;
2111 switch (dispIdMember)
2113 case DISPID_PICT_HANDLE:
2114 if (wFlags & DISPATCH_PROPERTYGET)
2116 TRACE("DISPID_PICT_HANDLE\n");
2117 V_VT(pVarResult) = VT_I4;
2118 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2120 break;
2121 case DISPID_PICT_HPAL:
2122 if (wFlags & DISPATCH_PROPERTYGET)
2124 TRACE("DISPID_PICT_HPAL\n");
2125 V_VT(pVarResult) = VT_I4;
2126 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2128 else if (wFlags & DISPATCH_PROPERTYPUT)
2130 VARIANTARG vararg;
2131 HRESULT hr;
2132 TRACE("DISPID_PICT_HPAL\n");
2134 VariantInit(&vararg);
2135 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2136 if (FAILED(hr))
2137 return hr;
2139 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2141 VariantClear(&vararg);
2142 return hr;
2144 break;
2145 case DISPID_PICT_TYPE:
2146 if (wFlags & DISPATCH_PROPERTYGET)
2148 TRACE("DISPID_PICT_TYPE\n");
2149 V_VT(pVarResult) = VT_I2;
2150 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2152 break;
2153 case DISPID_PICT_WIDTH:
2154 if (wFlags & DISPATCH_PROPERTYGET)
2156 TRACE("DISPID_PICT_WIDTH\n");
2157 V_VT(pVarResult) = VT_I4;
2158 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2160 break;
2161 case DISPID_PICT_HEIGHT:
2162 if (wFlags & DISPATCH_PROPERTYGET)
2164 TRACE("DISPID_PICT_HEIGHT\n");
2165 V_VT(pVarResult) = VT_I4;
2166 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2168 break;
2171 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2172 return DISP_E_MEMBERNOTFOUND;
2176 static const IPictureVtbl OLEPictureImpl_VTable =
2178 OLEPictureImpl_QueryInterface,
2179 OLEPictureImpl_AddRef,
2180 OLEPictureImpl_Release,
2181 OLEPictureImpl_get_Handle,
2182 OLEPictureImpl_get_hPal,
2183 OLEPictureImpl_get_Type,
2184 OLEPictureImpl_get_Width,
2185 OLEPictureImpl_get_Height,
2186 OLEPictureImpl_Render,
2187 OLEPictureImpl_set_hPal,
2188 OLEPictureImpl_get_CurDC,
2189 OLEPictureImpl_SelectPicture,
2190 OLEPictureImpl_get_KeepOriginalFormat,
2191 OLEPictureImpl_put_KeepOriginalFormat,
2192 OLEPictureImpl_PictureChanged,
2193 OLEPictureImpl_SaveAsFile,
2194 OLEPictureImpl_get_Attributes
2197 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2199 OLEPictureImpl_IDispatch_QueryInterface,
2200 OLEPictureImpl_IDispatch_AddRef,
2201 OLEPictureImpl_IDispatch_Release,
2202 OLEPictureImpl_GetTypeInfoCount,
2203 OLEPictureImpl_GetTypeInfo,
2204 OLEPictureImpl_GetIDsOfNames,
2205 OLEPictureImpl_Invoke
2208 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2210 OLEPictureImpl_IPersistStream_QueryInterface,
2211 OLEPictureImpl_IPersistStream_AddRef,
2212 OLEPictureImpl_IPersistStream_Release,
2213 OLEPictureImpl_GetClassID,
2214 OLEPictureImpl_IsDirty,
2215 OLEPictureImpl_Load,
2216 OLEPictureImpl_Save,
2217 OLEPictureImpl_GetSizeMax
2220 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2222 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2223 OLEPictureImpl_IConnectionPointContainer_AddRef,
2224 OLEPictureImpl_IConnectionPointContainer_Release,
2225 OLEPictureImpl_EnumConnectionPoints,
2226 OLEPictureImpl_FindConnectionPoint
2229 /***********************************************************************
2230 * OleCreatePictureIndirect (OLEAUT32.419)
2232 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2233 BOOL fOwn, LPVOID *ppvObj )
2235 OLEPictureImpl* newPict = NULL;
2236 HRESULT hr = S_OK;
2238 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2241 * Sanity check
2243 if (ppvObj==0)
2244 return E_POINTER;
2246 *ppvObj = NULL;
2249 * Try to construct a new instance of the class.
2251 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2253 if (newPict == NULL)
2254 return E_OUTOFMEMORY;
2257 * Make sure it supports the interface required by the caller.
2259 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2262 * Release the reference obtained in the constructor. If
2263 * the QueryInterface was unsuccessful, it will free the class.
2265 IPicture_Release((IPicture*)newPict);
2267 return hr;
2271 /***********************************************************************
2272 * OleLoadPicture (OLEAUT32.418)
2274 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2275 REFIID riid, LPVOID *ppvObj )
2277 LPPERSISTSTREAM ps;
2278 IPicture *newpic;
2279 HRESULT hr;
2281 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2282 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2284 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2285 if (hr)
2286 return hr;
2287 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2288 if (hr) {
2289 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2290 IPicture_Release(newpic);
2291 *ppvObj = NULL;
2292 return hr;
2294 IPersistStream_Load(ps,lpstream);
2295 IPersistStream_Release(ps);
2296 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2297 if (hr)
2298 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2299 IPicture_Release(newpic);
2300 return hr;
2303 /***********************************************************************
2304 * OleLoadPictureEx (OLEAUT32.401)
2306 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2307 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2309 LPPERSISTSTREAM ps;
2310 IPicture *newpic;
2311 HRESULT hr;
2313 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2314 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2316 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2317 if (hr)
2318 return hr;
2319 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2320 if (hr) {
2321 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2322 IPicture_Release(newpic);
2323 *ppvObj = NULL;
2324 return hr;
2326 IPersistStream_Load(ps,lpstream);
2327 IPersistStream_Release(ps);
2328 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2329 if (hr)
2330 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2331 IPicture_Release(newpic);
2332 return hr;
2335 /***********************************************************************
2336 * OleLoadPicturePath (OLEAUT32.424)
2338 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2339 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2340 LPVOID *ppvRet )
2342 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2343 IPicture *ipicture;
2344 HANDLE hFile;
2345 DWORD dwFileSize;
2346 HGLOBAL hGlobal = NULL;
2347 DWORD dwBytesRead = 0;
2348 IStream *stream;
2349 BOOL bRead;
2350 IPersistStream *pStream;
2351 HRESULT hRes;
2353 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2354 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2355 debugstr_guid(riid), ppvRet);
2357 if (!ppvRet) return E_POINTER;
2359 if (strncmpW(szURLorPath, file, 7) == 0) {
2360 szURLorPath += 7;
2362 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2363 0, NULL);
2364 if (hFile == INVALID_HANDLE_VALUE)
2365 return E_UNEXPECTED;
2367 dwFileSize = GetFileSize(hFile, NULL);
2368 if (dwFileSize != INVALID_FILE_SIZE )
2370 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2371 if ( hGlobal)
2373 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2374 if (!bRead)
2376 GlobalFree(hGlobal);
2377 hGlobal = 0;
2381 CloseHandle(hFile);
2383 if (!hGlobal)
2384 return E_UNEXPECTED;
2386 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2387 if (FAILED(hRes))
2389 GlobalFree(hGlobal);
2390 return hRes;
2392 } else {
2393 IMoniker *pmnk;
2394 IBindCtx *pbc;
2396 hRes = CreateBindCtx(0, &pbc);
2397 if (SUCCEEDED(hRes))
2399 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2400 if (SUCCEEDED(hRes))
2402 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2403 IMoniker_Release(pmnk);
2405 IBindCtx_Release(pbc);
2407 if (FAILED(hRes))
2408 return hRes;
2411 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2412 &IID_IPicture, (LPVOID*)&ipicture);
2413 if (hRes != S_OK) {
2414 IStream_Release(stream);
2415 return hRes;
2418 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2419 if (hRes) {
2420 IStream_Release(stream);
2421 IPicture_Release(ipicture);
2422 return hRes;
2425 hRes = IPersistStream_Load(pStream, stream);
2426 IPersistStream_Release(pStream);
2427 IStream_Release(stream);
2429 if (hRes) {
2430 IPicture_Release(ipicture);
2431 return hRes;
2434 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2435 if (hRes)
2436 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2438 IPicture_Release(ipicture);
2439 return hRes;
2442 /*******************************************************************************
2443 * StdPic ClassFactory
2445 typedef struct
2447 /* IUnknown fields */
2448 const IClassFactoryVtbl *lpVtbl;
2449 LONG ref;
2450 } IClassFactoryImpl;
2452 static HRESULT WINAPI
2453 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2454 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2456 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2457 return E_NOINTERFACE;
2460 static ULONG WINAPI
2461 SPCF_AddRef(LPCLASSFACTORY iface) {
2462 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2463 return InterlockedIncrement(&This->ref);
2466 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2467 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2468 /* static class, won't be freed */
2469 return InterlockedDecrement(&This->ref);
2472 static HRESULT WINAPI SPCF_CreateInstance(
2473 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2475 /* Creates an uninitialized picture */
2476 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2480 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2481 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2482 FIXME("(%p)->(%d),stub!\n",This,dolock);
2483 return S_OK;
2486 static const IClassFactoryVtbl SPCF_Vtbl = {
2487 SPCF_QueryInterface,
2488 SPCF_AddRef,
2489 SPCF_Release,
2490 SPCF_CreateInstance,
2491 SPCF_LockServer
2493 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2495 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }