2005-07-31 12:11:56 +00:00
|
|
|
/*
|
|
|
|
* OLE Picture object
|
|
|
|
*
|
|
|
|
* Implementation of OLE IPicture and related interfaces
|
|
|
|
*
|
|
|
|
* Copyright 2000 Huw D M Davies for CodeWeavers.
|
|
|
|
* Copyright 2001 Marcus Meissner
|
2009-01-15 17:52:35 +00:00
|
|
|
* Copyright 2008 Kirill K. Smirnov
|
2005-07-31 12:11:56 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2007-04-20 11:44:43 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2005-07-31 12:11:56 +00:00
|
|
|
*
|
|
|
|
* BUGS
|
|
|
|
*
|
2008-07-10 09:14:19 +00:00
|
|
|
* Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well..
|
2005-07-31 12:11:56 +00:00
|
|
|
* Lots of methods are just stubs.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* NOTES (or things that msdn doesn't tell you)
|
|
|
|
*
|
|
|
|
* The width and height properties are returned in HIMETRIC units (0.01mm)
|
|
|
|
* IPicture::Render also uses these to select a region of the src picture.
|
|
|
|
* A bitmap's size is converted into these units by using the screen resolution
|
|
|
|
* thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-03-04 12:14:52 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2018-03-04 12:14:52 +00:00
|
|
|
#define COBJMACROS
|
|
|
|
#define NONAMELESSUNION
|
|
|
|
|
|
|
|
#include "winerror.h"
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "wingdi.h"
|
|
|
|
#include "winuser.h"
|
|
|
|
#include "ole2.h"
|
|
|
|
#include "olectl.h"
|
|
|
|
#include "oleauto.h"
|
|
|
|
#include "connpt.h"
|
|
|
|
#include "urlmon.h"
|
|
|
|
#include "initguid.h"
|
|
|
|
#include "wincodec.h"
|
|
|
|
#include "wine/debug.h"
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(olepicture);
|
|
|
|
|
|
|
|
#define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
|
|
|
|
#define BITMAP_FORMAT_JPEG 0xd8ff
|
|
|
|
#define BITMAP_FORMAT_GIF 0x4947
|
|
|
|
#define BITMAP_FORMAT_PNG 0x5089
|
|
|
|
#define BITMAP_FORMAT_APM 0xcdd7
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-12 17:30:09 +00:00
|
|
|
#include "pshpack1.h"
|
|
|
|
|
2008-01-15 19:22:36 +00:00
|
|
|
/* Header for Aldus Placable Metafiles - a standard metafile follows */
|
|
|
|
typedef struct _APM_HEADER
|
|
|
|
{
|
|
|
|
DWORD key;
|
|
|
|
WORD handle;
|
|
|
|
SHORT left;
|
|
|
|
SHORT top;
|
|
|
|
SHORT right;
|
|
|
|
SHORT bottom;
|
|
|
|
WORD inch;
|
|
|
|
DWORD reserved;
|
|
|
|
WORD checksum;
|
|
|
|
} APM_HEADER;
|
|
|
|
|
2005-08-12 17:30:09 +00:00
|
|
|
typedef struct {
|
|
|
|
BYTE bWidth;
|
|
|
|
BYTE bHeight;
|
|
|
|
BYTE bColorCount;
|
|
|
|
BYTE bReserved;
|
|
|
|
WORD xHotspot;
|
|
|
|
WORD yHotspot;
|
|
|
|
DWORD dwDIBSize;
|
|
|
|
DWORD dwDIBOffset;
|
|
|
|
} CURSORICONFILEDIRENTRY;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
WORD idReserved;
|
|
|
|
WORD idType;
|
|
|
|
WORD idCount;
|
|
|
|
CURSORICONFILEDIRENTRY idEntries[1];
|
|
|
|
} CURSORICONFILEDIR;
|
|
|
|
|
|
|
|
#include "poppack.h"
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/*************************************************************************
|
|
|
|
* Declaration of implementation class
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct OLEPictureImpl {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IPicture handles IUnknown
|
|
|
|
*/
|
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
IPicture IPicture_iface;
|
|
|
|
IDispatch IDispatch_iface;
|
|
|
|
IPersistStream IPersistStream_iface;
|
|
|
|
IConnectionPointContainer IConnectionPointContainer_iface;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* Object reference count */
|
2005-08-12 17:30:09 +00:00
|
|
|
LONG ref;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* We own the object and must destroy it ourselves */
|
|
|
|
BOOL fOwn;
|
|
|
|
|
|
|
|
/* Picture description */
|
|
|
|
PICTDESC desc;
|
|
|
|
|
|
|
|
/* These are the pixel size of a bitmap */
|
|
|
|
DWORD origWidth;
|
|
|
|
DWORD origHeight;
|
|
|
|
|
|
|
|
/* And these are the size of the picture converted into HIMETRIC units */
|
|
|
|
OLE_XSIZE_HIMETRIC himetricWidth;
|
|
|
|
OLE_YSIZE_HIMETRIC himetricHeight;
|
|
|
|
|
|
|
|
IConnectionPoint *pCP;
|
|
|
|
|
|
|
|
BOOL keepOrigFormat;
|
|
|
|
HDC hDCCur;
|
2012-12-12 13:52:25 +00:00
|
|
|
HBITMAP stock_bitmap;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* Bitmap transparency mask */
|
|
|
|
HBITMAP hbmMask;
|
|
|
|
HBITMAP hbmXor;
|
|
|
|
COLORREF rgbTrans;
|
|
|
|
|
|
|
|
/* data */
|
|
|
|
void* data;
|
|
|
|
int datalen;
|
|
|
|
BOOL bIsDirty; /* Set to TRUE if picture has changed */
|
|
|
|
unsigned int loadtime_magic; /* If a length header was found, saves value */
|
|
|
|
unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
|
|
|
|
} OLEPictureImpl;
|
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
static inline OLEPictureImpl *impl_from_IPicture(IPicture *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, OLEPictureImpl, IPicture_iface);
|
|
|
|
}
|
2005-09-05 22:00:07 +00:00
|
|
|
|
|
|
|
static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
return CONTAINING_RECORD(iface, OLEPictureImpl, IDispatch_iface);
|
2005-09-05 22:00:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
return CONTAINING_RECORD(iface, OLEPictureImpl, IPersistStream_iface);
|
2005-09-05 22:00:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
return CONTAINING_RECORD(iface, OLEPictureImpl, IConnectionPointContainer_iface);
|
2005-09-05 22:00:07 +00:00
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Predeclare VTables. They get initialized at the end.
|
|
|
|
*/
|
2005-08-03 22:46:31 +00:00
|
|
|
static const IPictureVtbl OLEPictureImpl_VTable;
|
|
|
|
static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
|
|
|
|
static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
|
|
|
|
static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
/* pixels to HIMETRIC units conversion */
|
|
|
|
static inline OLE_XSIZE_HIMETRIC xpixels_to_himetric(INT pixels, HDC hdc)
|
|
|
|
{
|
|
|
|
return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline OLE_YSIZE_HIMETRIC ypixels_to_himetric(INT pixels, HDC hdc)
|
|
|
|
{
|
|
|
|
return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* Implementation of the OLEPictureImpl class.
|
|
|
|
*/
|
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
static void OLEPictureImpl_SetBitmap(OLEPictureImpl *This)
|
|
|
|
{
|
2005-07-31 12:11:56 +00:00
|
|
|
BITMAP bm;
|
|
|
|
HDC hdcRef;
|
|
|
|
|
|
|
|
TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
|
2012-12-12 13:52:25 +00:00
|
|
|
if(GetObjectW(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
|
2005-07-31 12:11:56 +00:00
|
|
|
ERR("GetObject fails\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
This->origWidth = bm.bmWidth;
|
|
|
|
This->origHeight = bm.bmHeight;
|
2012-12-12 13:52:25 +00:00
|
|
|
|
|
|
|
TRACE("width %d, height %d, bpp %d\n", bm.bmWidth, bm.bmHeight, bm.bmBitsPixel);
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/* The width and height are stored in HIMETRIC units (0.01 mm),
|
|
|
|
so we take our pixel width divide by pixels per inch and
|
|
|
|
multiply by 25.4 * 100 */
|
|
|
|
/* Should we use GetBitmapDimension if available? */
|
|
|
|
hdcRef = CreateCompatibleDC(0);
|
2012-12-12 13:52:25 +00:00
|
|
|
|
|
|
|
This->himetricWidth = xpixels_to_himetric(bm.bmWidth, hdcRef);
|
|
|
|
This->himetricHeight = ypixels_to_himetric(bm.bmHeight, hdcRef);
|
|
|
|
This->stock_bitmap = GetCurrentObject( hdcRef, OBJ_BITMAP );
|
|
|
|
|
|
|
|
This->loadtime_format = BITMAP_FORMAT_BMP;
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
DeleteDC(hdcRef);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
|
|
|
|
{
|
|
|
|
ICONINFO infoIcon;
|
|
|
|
|
|
|
|
TRACE("icon handle %p\n", This->desc.u.icon.hicon);
|
|
|
|
if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
|
|
|
|
HDC hdcRef;
|
|
|
|
BITMAP bm;
|
|
|
|
|
|
|
|
TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
|
2012-12-12 13:52:25 +00:00
|
|
|
if(GetObjectW(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
|
2005-07-31 12:11:56 +00:00
|
|
|
ERR("GetObject fails on icon bitmap\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
This->origWidth = bm.bmWidth;
|
|
|
|
This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
|
|
|
|
/* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
|
|
|
|
hdcRef = GetDC(0);
|
2012-12-12 13:52:25 +00:00
|
|
|
|
|
|
|
This->himetricWidth = xpixels_to_himetric(This->origWidth, hdcRef);
|
|
|
|
This->himetricHeight = ypixels_to_himetric(This->origHeight, hdcRef);
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
ReleaseDC(0, hdcRef);
|
|
|
|
|
|
|
|
DeleteObject(infoIcon.hbmMask);
|
|
|
|
if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
|
|
|
|
} else {
|
|
|
|
ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-28 16:05:15 +00:00
|
|
|
static void OLEPictureImpl_SetEMF(OLEPictureImpl *This)
|
|
|
|
{
|
|
|
|
ENHMETAHEADER emh;
|
|
|
|
|
|
|
|
GetEnhMetaFileHeader(This->desc.u.emf.hemf, sizeof(emh), &emh);
|
|
|
|
|
|
|
|
This->origWidth = 0;
|
|
|
|
This->origHeight = 0;
|
|
|
|
This->himetricWidth = emh.rclFrame.right - emh.rclFrame.left;
|
|
|
|
This->himetricHeight = emh.rclFrame.bottom - emh.rclFrame.top;
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_Construct
|
|
|
|
*
|
|
|
|
* This method will construct a new instance of the OLEPictureImpl
|
|
|
|
* class.
|
|
|
|
*
|
|
|
|
* The caller of this method must release the object when it's
|
|
|
|
* done with it.
|
|
|
|
*/
|
2019-01-29 12:18:42 +00:00
|
|
|
static HRESULT OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn, OLEPictureImpl **pict)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2019-01-29 12:18:42 +00:00
|
|
|
OLEPictureImpl *newObject;
|
|
|
|
HRESULT hr;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
if (pictDesc)
|
|
|
|
TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate space for the object.
|
|
|
|
*/
|
|
|
|
newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
|
2019-01-29 12:18:42 +00:00
|
|
|
if (!newObject)
|
|
|
|
return E_OUTOFMEMORY;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize the virtual function table.
|
|
|
|
*/
|
2012-12-12 13:52:25 +00:00
|
|
|
newObject->IPicture_iface.lpVtbl = &OLEPictureImpl_VTable;
|
|
|
|
newObject->IDispatch_iface.lpVtbl = &OLEPictureImpl_IDispatch_VTable;
|
|
|
|
newObject->IPersistStream_iface.lpVtbl = &OLEPictureImpl_IPersistStream_VTable;
|
|
|
|
newObject->IConnectionPointContainer_iface.lpVtbl = &OLEPictureImpl_IConnectionPointContainer_VTable;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
newObject->pCP = NULL;
|
2019-01-29 12:18:42 +00:00
|
|
|
hr = CreateConnectionPoint((IUnknown*)&newObject->IPicture_iface, &IID_IPropertyNotifySink,
|
2016-11-17 22:58:15 +00:00
|
|
|
&newObject->pCP);
|
2019-01-29 12:18:42 +00:00
|
|
|
if (hr != S_OK)
|
2006-03-27 16:44:53 +00:00
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, newObject);
|
2019-01-29 12:18:42 +00:00
|
|
|
return hr;
|
2006-03-27 16:44:53 +00:00
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Start with one reference count. The caller of this function
|
|
|
|
* must release the interface pointer when it is done.
|
|
|
|
*/
|
|
|
|
newObject->ref = 1;
|
|
|
|
newObject->hDCCur = 0;
|
|
|
|
|
|
|
|
newObject->fOwn = fOwn;
|
|
|
|
|
|
|
|
/* dunno about original value */
|
|
|
|
newObject->keepOrigFormat = TRUE;
|
|
|
|
|
|
|
|
newObject->hbmMask = NULL;
|
|
|
|
newObject->hbmXor = NULL;
|
|
|
|
newObject->loadtime_magic = 0xdeadbeef;
|
|
|
|
newObject->loadtime_format = 0;
|
|
|
|
newObject->bIsDirty = FALSE;
|
|
|
|
|
|
|
|
if (pictDesc) {
|
2008-07-10 09:14:19 +00:00
|
|
|
newObject->desc = *pictDesc;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
switch(pictDesc->picType) {
|
|
|
|
case PICTYPE_BITMAP:
|
|
|
|
OLEPictureImpl_SetBitmap(newObject);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PICTYPE_METAFILE:
|
|
|
|
TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
|
|
|
|
newObject->himetricWidth = pictDesc->u.wmf.xExt;
|
|
|
|
newObject->himetricHeight = pictDesc->u.wmf.yExt;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PICTYPE_NONE:
|
|
|
|
/* not sure what to do here */
|
|
|
|
newObject->himetricWidth = newObject->himetricHeight = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PICTYPE_ICON:
|
|
|
|
OLEPictureImpl_SetIcon(newObject);
|
|
|
|
break;
|
2018-01-28 16:05:15 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
case PICTYPE_ENHMETAFILE:
|
2018-01-28 16:05:15 +00:00
|
|
|
OLEPictureImpl_SetEMF(newObject);
|
|
|
|
break;
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
default:
|
2019-01-29 12:18:42 +00:00
|
|
|
WARN("Unsupported type %d\n", pictDesc->picType);
|
|
|
|
IPicture_Release(&newObject->IPicture_iface);
|
|
|
|
return E_UNEXPECTED;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
newObject->desc.picType = PICTYPE_UNINITIALIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE("returning %p\n", newObject);
|
2019-01-29 12:18:42 +00:00
|
|
|
*pict = newObject;
|
|
|
|
return S_OK;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_Destroy
|
|
|
|
*
|
|
|
|
* This method is called by the Release method when the reference
|
|
|
|
* count goes down to 0. It will free all resources used by
|
|
|
|
* this object. */
|
|
|
|
static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
|
|
|
|
{
|
|
|
|
TRACE("(%p)\n", Obj);
|
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
if (Obj->pCP)
|
|
|
|
IConnectionPoint_Release(Obj->pCP);
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
if(Obj->fOwn) { /* We need to destroy the picture */
|
|
|
|
switch(Obj->desc.picType) {
|
|
|
|
case PICTYPE_BITMAP:
|
|
|
|
DeleteObject(Obj->desc.u.bmp.hbitmap);
|
|
|
|
if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
|
|
|
|
if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
|
|
|
|
break;
|
|
|
|
case PICTYPE_METAFILE:
|
|
|
|
DeleteMetaFile(Obj->desc.u.wmf.hmeta);
|
|
|
|
break;
|
|
|
|
case PICTYPE_ICON:
|
|
|
|
DestroyIcon(Obj->desc.u.icon.hicon);
|
|
|
|
break;
|
|
|
|
case PICTYPE_ENHMETAFILE:
|
|
|
|
DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
|
|
|
|
break;
|
2005-08-03 22:46:31 +00:00
|
|
|
case PICTYPE_NONE:
|
2007-07-27 09:59:17 +00:00
|
|
|
case PICTYPE_UNINITIALIZED:
|
2005-08-03 22:46:31 +00:00
|
|
|
/* Nothing to do */
|
|
|
|
break;
|
2005-07-31 12:11:56 +00:00
|
|
|
default:
|
|
|
|
FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, Obj->data);
|
|
|
|
HeapFree(GetProcessHeap(), 0, Obj);
|
|
|
|
}
|
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_AddRef (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI OLEPictureImpl_AddRef(
|
|
|
|
IPicture* iface)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2006-03-27 16:44:53 +00:00
|
|
|
ULONG refCount = InterlockedIncrement(&This->ref);
|
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
|
2006-03-27 16:44:53 +00:00
|
|
|
|
|
|
|
return refCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_Release (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI OLEPictureImpl_Release(
|
|
|
|
IPicture* iface)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2006-03-27 16:44:53 +00:00
|
|
|
ULONG refCount = InterlockedDecrement(&This->ref);
|
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
|
2006-03-27 16:44:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the reference count goes down to 0, perform suicide.
|
|
|
|
*/
|
|
|
|
if (!refCount) OLEPictureImpl_Destroy(This);
|
|
|
|
|
|
|
|
return refCount;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_QueryInterface (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_QueryInterface(
|
|
|
|
IPicture* iface,
|
|
|
|
REFIID riid,
|
|
|
|
void** ppvObject)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
|
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
if (!ppvObject)
|
2005-07-31 12:11:56 +00:00
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
*ppvObject = 0;
|
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
|
2017-03-05 21:50:37 +00:00
|
|
|
*ppvObject = &This->IPicture_iface;
|
2007-04-20 11:44:43 +00:00
|
|
|
else if (IsEqualIID(&IID_IDispatch, riid))
|
2012-12-12 13:52:25 +00:00
|
|
|
*ppvObject = &This->IDispatch_iface;
|
2007-04-20 11:44:43 +00:00
|
|
|
else if (IsEqualIID(&IID_IPictureDisp, riid))
|
2012-12-12 13:52:25 +00:00
|
|
|
*ppvObject = &This->IDispatch_iface;
|
2007-04-20 11:44:43 +00:00
|
|
|
else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
|
2012-12-12 13:52:25 +00:00
|
|
|
*ppvObject = &This->IPersistStream_iface;
|
2007-04-20 11:44:43 +00:00
|
|
|
else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
|
2012-12-12 13:52:25 +00:00
|
|
|
*ppvObject = &This->IConnectionPointContainer_iface;
|
2007-04-20 11:44:43 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
if (!*ppvObject)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2016-03-04 09:33:34 +00:00
|
|
|
FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));
|
2005-07-31 12:11:56 +00:00
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
IPicture_AddRef(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
2006-03-27 16:44:53 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* OLEPicture_SendNotify (internal)
|
|
|
|
*
|
|
|
|
* Sends notification messages of changed properties to any interested
|
|
|
|
* connections.
|
|
|
|
*/
|
|
|
|
static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
|
|
|
|
{
|
|
|
|
IEnumConnections *pEnum;
|
|
|
|
CONNECTDATA CD;
|
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
if (IConnectionPoint_EnumConnections(this->pCP, &pEnum) != S_OK)
|
2005-07-31 12:11:56 +00:00
|
|
|
return;
|
|
|
|
while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
|
|
|
|
IPropertyNotifySink *sink;
|
|
|
|
|
|
|
|
IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
|
|
|
|
IPropertyNotifySink_OnChanged(sink, dispID);
|
|
|
|
IPropertyNotifySink_Release(sink);
|
|
|
|
IUnknown_Release(CD.pUnk);
|
|
|
|
}
|
|
|
|
IEnumConnections_Release(pEnum);
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_get_Handle
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
|
|
|
|
OLE_HANDLE *phandle)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p)->(%p)\n", This, phandle);
|
2009-01-18 19:23:59 +00:00
|
|
|
|
|
|
|
if(!phandle)
|
|
|
|
return E_POINTER;
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
switch(This->desc.picType) {
|
2005-08-03 22:46:31 +00:00
|
|
|
case PICTYPE_NONE:
|
2007-07-27 09:59:17 +00:00
|
|
|
case PICTYPE_UNINITIALIZED:
|
2005-08-03 22:46:31 +00:00
|
|
|
*phandle = 0;
|
|
|
|
break;
|
2005-07-31 12:11:56 +00:00
|
|
|
case PICTYPE_BITMAP:
|
2009-01-18 19:23:59 +00:00
|
|
|
*phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
|
2005-07-31 12:11:56 +00:00
|
|
|
break;
|
|
|
|
case PICTYPE_METAFILE:
|
2009-01-18 19:23:59 +00:00
|
|
|
*phandle = HandleToUlong(This->desc.u.wmf.hmeta);
|
2005-07-31 12:11:56 +00:00
|
|
|
break;
|
|
|
|
case PICTYPE_ICON:
|
2009-01-18 19:23:59 +00:00
|
|
|
*phandle = HandleToUlong(This->desc.u.icon.hicon);
|
2005-07-31 12:11:56 +00:00
|
|
|
break;
|
|
|
|
case PICTYPE_ENHMETAFILE:
|
2009-01-18 19:23:59 +00:00
|
|
|
*phandle = HandleToUlong(This->desc.u.emf.hemf);
|
2005-07-31 12:11:56 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("Unimplemented type %d\n", This->desc.picType);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
TRACE("returning handle %08x\n", *phandle);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_get_hPal
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
|
|
|
|
OLE_HANDLE *phandle)
|
|
|
|
{
|
2019-01-29 12:18:42 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-08-03 22:46:31 +00:00
|
|
|
|
2019-01-29 12:18:42 +00:00
|
|
|
TRACE("(%p)->(%p)\n", This, phandle);
|
2005-09-05 22:00:07 +00:00
|
|
|
|
2019-01-29 12:18:42 +00:00
|
|
|
if (!phandle) return E_POINTER;
|
2005-09-05 22:00:07 +00:00
|
|
|
|
2019-01-29 12:18:42 +00:00
|
|
|
if (This->desc.picType == PICTYPE_BITMAP)
|
|
|
|
{
|
|
|
|
*phandle = HandleToUlong(This->desc.u.bmp.hpal);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return E_FAIL;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_get_Type
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
|
|
|
|
short *ptype)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
|
2009-01-18 19:23:59 +00:00
|
|
|
|
|
|
|
if(!ptype)
|
|
|
|
return E_POINTER;
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
*ptype = This->desc.picType;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_get_Width
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
|
|
|
|
OLE_XSIZE_HIMETRIC *pwidth)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
|
2005-07-31 12:11:56 +00:00
|
|
|
*pwidth = This->himetricWidth;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_get_Height
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
|
|
|
|
OLE_YSIZE_HIMETRIC *pheight)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
|
2005-07-31 12:11:56 +00:00
|
|
|
*pheight = This->himetricHeight;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2019-01-29 12:18:42 +00:00
|
|
|
static void render_masked_bitmap(OLEPictureImpl *This, HDC hdc,
|
|
|
|
LONG x, LONG y, LONG cx, LONG cy, OLE_XPOS_HIMETRIC xSrc, OLE_YPOS_HIMETRIC ySrc,
|
|
|
|
OLE_XSIZE_HIMETRIC cxSrc, OLE_YSIZE_HIMETRIC cySrc, HBITMAP hbmMask, HBITMAP hbmXor)
|
|
|
|
{
|
|
|
|
HDC hdcBmp;
|
|
|
|
|
|
|
|
/* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
|
|
|
|
* NB y-axis gets flipped
|
|
|
|
*/
|
|
|
|
|
|
|
|
hdcBmp = CreateCompatibleDC(0);
|
|
|
|
SetMapMode(hdcBmp, MM_ANISOTROPIC);
|
|
|
|
SetWindowOrgEx(hdcBmp, 0, 0, NULL);
|
|
|
|
SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
|
|
|
|
SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
|
|
|
|
SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
|
|
|
|
|
|
|
|
if (hbmMask)
|
|
|
|
{
|
|
|
|
SetBkColor(hdc, RGB(255, 255, 255));
|
|
|
|
SetTextColor(hdc, RGB(0, 0, 0));
|
|
|
|
|
|
|
|
SelectObject(hdcBmp, hbmMask);
|
|
|
|
StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCAND);
|
|
|
|
|
|
|
|
if (hbmXor)
|
|
|
|
{
|
|
|
|
SelectObject(hdcBmp, hbmXor);
|
|
|
|
StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
|
|
|
|
}
|
|
|
|
else StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc - This->himetricHeight,
|
|
|
|
cxSrc, cySrc, SRCPAINT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SelectObject(hdcBmp, hbmXor);
|
|
|
|
StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteDC(hdcBmp);
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_Render
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
|
|
|
|
LONG x, LONG y, LONG cx, LONG cy,
|
|
|
|
OLE_XPOS_HIMETRIC xSrc,
|
|
|
|
OLE_YPOS_HIMETRIC ySrc,
|
|
|
|
OLE_XSIZE_HIMETRIC cxSrc,
|
|
|
|
OLE_YSIZE_HIMETRIC cySrc,
|
|
|
|
LPCRECT prcWBounds)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
|
2005-07-31 12:11:56 +00:00
|
|
|
This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
|
|
|
|
if(prcWBounds)
|
2016-06-07 10:51:58 +00:00
|
|
|
TRACE("prcWBounds %s\n", wine_dbgstr_rect(prcWBounds));
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2009-01-15 17:52:35 +00:00
|
|
|
if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
|
|
|
|
return CTL_E_INVALIDPROPERTYVALUE;
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/*
|
|
|
|
* While the documentation suggests this to be here (or after rendering?)
|
|
|
|
* it does cause an endless recursion in my sample app. -MM 20010804
|
|
|
|
OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch(This->desc.picType) {
|
2009-01-15 17:52:35 +00:00
|
|
|
case PICTYPE_UNINITIALIZED:
|
|
|
|
case PICTYPE_NONE:
|
|
|
|
/* nothing to do */
|
|
|
|
return S_OK;
|
2005-07-31 12:11:56 +00:00
|
|
|
case PICTYPE_BITMAP:
|
2019-01-29 12:18:42 +00:00
|
|
|
{
|
|
|
|
HBITMAP hbmMask, hbmXor;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2019-01-29 12:18:42 +00:00
|
|
|
if (This->hbmMask)
|
|
|
|
{
|
|
|
|
hbmMask = This->hbmMask;
|
|
|
|
hbmXor = This->hbmXor;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
2019-01-29 12:18:42 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
hbmMask = 0;
|
|
|
|
hbmXor = This->desc.u.bmp.hbitmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
render_masked_bitmap(This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, hbmMask, hbmXor);
|
2005-07-31 12:11:56 +00:00
|
|
|
break;
|
2019-01-29 12:18:42 +00:00
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
case PICTYPE_ICON:
|
2019-01-29 12:18:42 +00:00
|
|
|
{
|
|
|
|
ICONINFO info;
|
|
|
|
|
|
|
|
if (!GetIconInfo(This->desc.u.icon.hicon, &info))
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
render_masked_bitmap(This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, info.hbmMask, info.hbmColor);
|
|
|
|
|
|
|
|
DeleteObject(info.hbmMask);
|
|
|
|
if (info.hbmColor) DeleteObject(info.hbmColor);
|
2005-07-31 12:11:56 +00:00
|
|
|
break;
|
2019-01-29 12:18:42 +00:00
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
case PICTYPE_METAFILE:
|
2008-01-15 19:22:36 +00:00
|
|
|
{
|
2009-02-07 07:52:12 +00:00
|
|
|
POINT prevOrg, prevWndOrg;
|
|
|
|
SIZE prevExt, prevWndExt;
|
2008-01-15 19:22:36 +00:00
|
|
|
int oldmode;
|
|
|
|
|
2009-02-07 07:52:12 +00:00
|
|
|
/* Render the WMF to the appropriate location by setting the
|
|
|
|
appropriate ratio between "device units" and "logical units" */
|
2008-01-15 19:22:36 +00:00
|
|
|
oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
|
2009-02-07 07:52:12 +00:00
|
|
|
/* For the "source rectangle" the y-axis must be inverted */
|
|
|
|
SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
|
|
|
|
SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
|
|
|
|
/* For the "destination rectangle" no inversion is necessary */
|
2008-01-15 19:22:36 +00:00
|
|
|
SetViewportOrgEx(hdc, x, y, &prevOrg);
|
|
|
|
SetViewportExtEx(hdc, cx, cy, &prevExt);
|
|
|
|
|
|
|
|
if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
|
|
|
|
ERR("PlayMetaFile failed!\n");
|
|
|
|
|
2009-02-07 07:52:12 +00:00
|
|
|
/* We're done, restore the DC to the previous settings for converting
|
|
|
|
logical units to device units */
|
|
|
|
SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
|
|
|
|
SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
|
2008-01-15 19:22:36 +00:00
|
|
|
SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
|
|
|
|
SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
|
|
|
|
SetMapMode(hdc, oldmode);
|
2007-07-27 09:59:17 +00:00
|
|
|
break;
|
2008-01-15 19:22:36 +00:00
|
|
|
}
|
2007-07-27 09:59:17 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
case PICTYPE_ENHMETAFILE:
|
2007-07-27 09:59:17 +00:00
|
|
|
{
|
2008-01-15 19:22:36 +00:00
|
|
|
RECT rc = { x, y, x + cx, y + cy };
|
2007-07-27 09:59:17 +00:00
|
|
|
PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
default:
|
|
|
|
FIXME("type %d not implemented\n", This->desc.picType);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_set_hPal
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
|
|
|
|
OLE_HANDLE hpal)
|
|
|
|
{
|
2019-01-29 12:18:42 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
|
|
|
|
|
|
|
TRACE("(%p)->(%08x)\n", This, hpal);
|
|
|
|
|
|
|
|
if (This->desc.picType == PICTYPE_BITMAP)
|
|
|
|
{
|
|
|
|
This->desc.u.bmp.hpal = ULongToHandle(hpal);
|
|
|
|
OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return E_FAIL;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_get_CurDC
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
|
|
|
|
HDC *phdc)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p), returning %p\n", This, This->hDCCur);
|
|
|
|
if (phdc) *phdc = This->hDCCur;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_SelectPicture
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
|
|
|
|
HDC hdcIn,
|
|
|
|
HDC *phdcOut,
|
|
|
|
OLE_HANDLE *phbmpOut)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
|
|
|
|
if (This->desc.picType == PICTYPE_BITMAP) {
|
|
|
|
if (phdcOut)
|
|
|
|
*phdcOut = This->hDCCur;
|
2012-12-12 13:52:25 +00:00
|
|
|
if (This->hDCCur) SelectObject(This->hDCCur,This->stock_bitmap);
|
|
|
|
if (hdcIn) SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
|
2005-07-31 12:11:56 +00:00
|
|
|
This->hDCCur = hdcIn;
|
|
|
|
if (phbmpOut)
|
2009-01-18 19:23:59 +00:00
|
|
|
*phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
|
2005-07-31 12:11:56 +00:00
|
|
|
return S_OK;
|
|
|
|
} else {
|
|
|
|
FIXME("Don't know how to select picture type %d\n",This->desc.picType);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_get_KeepOriginalFormat
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
|
|
|
|
BOOL *pfKeep)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p)->(%p)\n", This, pfKeep);
|
|
|
|
if (!pfKeep)
|
|
|
|
return E_POINTER;
|
|
|
|
*pfKeep = This->keepOrigFormat;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_put_KeepOriginalFormat
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
|
|
|
|
BOOL keep)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p)->(%d)\n", This, keep);
|
|
|
|
This->keepOrigFormat = keep;
|
|
|
|
/* FIXME: what DISPID notification here? */
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_PictureChanged
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p)->()\n", This);
|
|
|
|
OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
|
|
|
|
This->bIsDirty = TRUE;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_get_Attributes
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
|
|
|
|
DWORD *pdwAttr)
|
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p)->(%p).\n", This, pdwAttr);
|
2009-01-18 19:23:59 +00:00
|
|
|
|
|
|
|
if(!pdwAttr)
|
|
|
|
return E_POINTER;
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
*pdwAttr = 0;
|
|
|
|
switch (This->desc.picType) {
|
2009-01-18 19:23:59 +00:00
|
|
|
case PICTYPE_UNINITIALIZED:
|
|
|
|
case PICTYPE_NONE: break;
|
2005-07-31 12:11:56 +00:00
|
|
|
case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
|
|
|
|
case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
|
2007-07-27 09:59:17 +00:00
|
|
|
case PICTYPE_ENHMETAFILE: /* fall through */
|
2005-07-31 12:11:56 +00:00
|
|
|
case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
|
|
|
|
default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* IConnectionPointContainer
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
|
|
|
|
IConnectionPointContainer* iface,
|
|
|
|
REFIID riid,
|
2005-09-05 22:00:07 +00:00
|
|
|
VOID** ppvoid)
|
|
|
|
{
|
|
|
|
OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_QueryInterface(&This->IPicture_iface,riid,ppvoid);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
|
|
|
|
IConnectionPointContainer* iface)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_AddRef(&This->IPicture_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
|
|
|
|
IConnectionPointContainer* iface)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_Release(&This->IPicture_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
|
|
|
|
IConnectionPointContainer* iface,
|
2005-09-05 22:00:07 +00:00
|
|
|
IEnumConnectionPoints** ppEnum)
|
|
|
|
{
|
|
|
|
OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
FIXME("(%p,%p), stub!\n",This,ppEnum);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
|
|
|
|
IConnectionPointContainer* iface,
|
|
|
|
REFIID riid,
|
2005-09-05 22:00:07 +00:00
|
|
|
IConnectionPoint **ppCP)
|
|
|
|
{
|
|
|
|
OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
|
|
|
|
if (!ppCP)
|
|
|
|
return E_POINTER;
|
|
|
|
*ppCP = NULL;
|
|
|
|
if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
|
2014-04-24 15:12:07 +00:00
|
|
|
return IConnectionPoint_QueryInterface(This->pCP, &IID_IConnectionPoint, (void**)ppCP);
|
2006-03-27 16:44:53 +00:00
|
|
|
FIXME("no connection point for %s\n",debugstr_guid(riid));
|
|
|
|
return CONNECT_E_NOCONNECTION;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
2006-03-27 16:44:53 +00:00
|
|
|
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/************************************************************************
|
|
|
|
* IPersistStream
|
|
|
|
*/
|
2006-03-27 16:44:53 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
|
|
|
|
IPersistStream* iface,
|
|
|
|
REFIID riid,
|
|
|
|
VOID** ppvoid)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IPersistStream_AddRef (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
|
|
|
|
IPersistStream* iface)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_AddRef(&This->IPicture_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IPersistStream_Release (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
|
|
|
|
IPersistStream* iface)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_Release(&This->IPicture_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IPersistStream_GetClassID
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_GetClassID(
|
|
|
|
IPersistStream* iface,CLSID* pClassID)
|
|
|
|
{
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%p)\n", pClassID);
|
2008-07-10 09:14:19 +00:00
|
|
|
*pClassID = CLSID_StdPicture;
|
2007-04-20 11:44:43 +00:00
|
|
|
return S_OK;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IPersistStream_IsDirty
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_IsDirty(
|
|
|
|
IPersistStream* iface)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
FIXME("(%p),stub!\n",This);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2009-08-22 19:07:35 +00:00
|
|
|
static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
BITMAPINFOHEADER bih;
|
|
|
|
UINT width, height;
|
|
|
|
UINT stride, buffersize;
|
2018-01-28 16:05:15 +00:00
|
|
|
BYTE *bits, *mask = NULL;
|
2009-08-22 19:07:35 +00:00
|
|
|
WICRect rc;
|
|
|
|
IWICBitmapSource *real_source;
|
|
|
|
UINT x, y;
|
|
|
|
COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
|
|
|
|
BOOL has_alpha=FALSE;
|
|
|
|
|
|
|
|
hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
|
|
|
|
if (FAILED(hr)) return hr;
|
|
|
|
|
|
|
|
hr = IWICBitmapSource_GetSize(real_source, &width, &height);
|
|
|
|
if (FAILED(hr)) goto end;
|
|
|
|
|
|
|
|
bih.biSize = sizeof(bih);
|
|
|
|
bih.biWidth = width;
|
|
|
|
bih.biHeight = -height;
|
|
|
|
bih.biPlanes = 1;
|
|
|
|
bih.biBitCount = 32;
|
|
|
|
bih.biCompression = BI_RGB;
|
|
|
|
bih.biSizeImage = 0;
|
|
|
|
bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
|
|
|
|
bih.biYPelsPerMeter = 4085;
|
|
|
|
bih.biClrUsed = 0;
|
|
|
|
bih.biClrImportant = 0;
|
|
|
|
|
|
|
|
stride = 4 * width;
|
|
|
|
buffersize = stride * height;
|
|
|
|
|
2018-01-28 16:05:15 +00:00
|
|
|
mask = HeapAlloc(GetProcessHeap(), 0, buffersize);
|
|
|
|
if (!mask)
|
2017-03-05 21:50:37 +00:00
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2018-01-28 16:05:15 +00:00
|
|
|
This->desc.u.bmp.hbitmap = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void **)&bits, NULL, 0);
|
|
|
|
if (This->desc.u.bmp.hbitmap == 0)
|
|
|
|
{
|
|
|
|
hr = E_FAIL;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2009-08-22 19:07:35 +00:00
|
|
|
rc.X = 0;
|
|
|
|
rc.Y = 0;
|
|
|
|
rc.Width = width;
|
|
|
|
rc.Height = height;
|
|
|
|
hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
|
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
2018-01-28 16:05:15 +00:00
|
|
|
DeleteObject(This->desc.u.bmp.hbitmap);
|
2009-08-22 19:07:35 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
This->desc.picType = PICTYPE_BITMAP;
|
|
|
|
OLEPictureImpl_SetBitmap(This);
|
|
|
|
|
|
|
|
/* set transparent pixels to black, all others to white */
|
|
|
|
for(y = 0; y < height; y++){
|
|
|
|
for(x = 0; x < width; x++){
|
|
|
|
DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
|
|
|
|
if((*pixel & 0x80000000) == 0)
|
|
|
|
{
|
|
|
|
has_alpha = TRUE;
|
2018-01-28 16:05:15 +00:00
|
|
|
*(DWORD *)(mask + stride * y + 4 * x) = black;
|
2009-08-22 19:07:35 +00:00
|
|
|
}
|
|
|
|
else
|
2018-01-28 16:05:15 +00:00
|
|
|
*(DWORD *)(mask + stride * y + 4 * x) = white;
|
2009-08-22 19:07:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (has_alpha)
|
|
|
|
{
|
2018-01-28 16:05:15 +00:00
|
|
|
HDC hdcref, hdcBmp, hdcXor, hdcMask;
|
2009-08-22 19:07:35 +00:00
|
|
|
HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
|
|
|
|
|
2018-01-28 16:05:15 +00:00
|
|
|
hdcref = GetDC(0);
|
|
|
|
|
2009-08-22 19:07:35 +00:00
|
|
|
This->hbmXor = CreateDIBitmap(
|
|
|
|
hdcref,
|
|
|
|
&bih,
|
|
|
|
CBM_INIT,
|
2018-01-28 16:05:15 +00:00
|
|
|
mask,
|
2009-08-22 19:07:35 +00:00
|
|
|
(BITMAPINFO*)&bih,
|
|
|
|
DIB_RGB_COLORS
|
|
|
|
);
|
|
|
|
|
|
|
|
This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
|
|
|
|
hdcBmp = CreateCompatibleDC(NULL);
|
|
|
|
hdcXor = CreateCompatibleDC(NULL);
|
|
|
|
hdcMask = CreateCompatibleDC(NULL);
|
|
|
|
|
|
|
|
hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
|
|
|
|
hbmoldXor = SelectObject(hdcXor,This->hbmXor);
|
|
|
|
hbmoldMask = SelectObject(hdcMask,This->hbmMask);
|
|
|
|
|
|
|
|
SetBkColor(hdcXor,black);
|
|
|
|
BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
|
|
|
|
BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
|
|
|
|
|
|
|
|
SelectObject(hdcBmp,hbmoldBmp);
|
|
|
|
SelectObject(hdcXor,hbmoldXor);
|
|
|
|
SelectObject(hdcMask,hbmoldMask);
|
|
|
|
|
|
|
|
DeleteDC(hdcBmp);
|
|
|
|
DeleteDC(hdcXor);
|
|
|
|
DeleteDC(hdcMask);
|
2018-01-28 16:05:15 +00:00
|
|
|
ReleaseDC(0, hdcref);
|
2009-08-22 19:07:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
2018-01-28 16:05:15 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, mask);
|
2009-08-22 19:07:35 +00:00
|
|
|
IWICBitmapSource_Release(real_source);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
2009-09-05 15:03:37 +00:00
|
|
|
IWICImagingFactory *factory;
|
2009-08-22 19:07:35 +00:00
|
|
|
IWICBitmapDecoder *decoder;
|
|
|
|
IWICBitmapFrameDecode *framedecode;
|
|
|
|
HRESULT initresult;
|
2009-09-05 15:03:37 +00:00
|
|
|
IWICStream *stream;
|
2009-08-22 19:07:35 +00:00
|
|
|
|
|
|
|
initresult = CoInitialize(NULL);
|
|
|
|
|
2009-09-05 15:03:37 +00:00
|
|
|
hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
|
|
|
|
&IID_IWICImagingFactory, (void**)&factory);
|
|
|
|
if (SUCCEEDED(hr)) /* created factory */
|
2009-08-22 19:07:35 +00:00
|
|
|
{
|
2009-09-05 15:03:37 +00:00
|
|
|
hr = IWICImagingFactory_CreateStream(factory, &stream);
|
|
|
|
IWICImagingFactory_Release(factory);
|
2007-07-27 09:59:17 +00:00
|
|
|
}
|
|
|
|
|
2009-09-05 15:03:37 +00:00
|
|
|
if (SUCCEEDED(hr)) /* created stream */
|
|
|
|
{
|
|
|
|
hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
|
2007-07-27 09:59:17 +00:00
|
|
|
|
2009-09-05 15:03:37 +00:00
|
|
|
if (SUCCEEDED(hr)) /* initialized stream */
|
|
|
|
{
|
|
|
|
hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
|
|
|
|
&IID_IWICBitmapDecoder, (void**)&decoder);
|
|
|
|
if (SUCCEEDED(hr)) /* created decoder */
|
|
|
|
{
|
|
|
|
hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
|
2007-07-27 09:59:17 +00:00
|
|
|
|
2009-09-05 15:03:37 +00:00
|
|
|
if (SUCCEEDED(hr)) /* initialized decoder */
|
|
|
|
hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
|
2007-07-27 09:59:17 +00:00
|
|
|
|
2009-09-05 15:03:37 +00:00
|
|
|
IWICBitmapDecoder_Release(decoder);
|
|
|
|
}
|
2007-07-27 09:59:17 +00:00
|
|
|
}
|
|
|
|
|
2009-09-05 15:03:37 +00:00
|
|
|
IWICStream_Release(stream);
|
2007-07-27 09:59:17 +00:00
|
|
|
}
|
|
|
|
|
2009-09-05 15:03:37 +00:00
|
|
|
if (SUCCEEDED(hr)) /* got framedecode */
|
|
|
|
{
|
|
|
|
hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
|
|
|
|
IWICBitmapFrameDecode_Release(framedecode);
|
2008-01-15 19:22:36 +00:00
|
|
|
}
|
|
|
|
|
2009-09-05 15:03:37 +00:00
|
|
|
if (SUCCEEDED(initresult)) CoUninitialize();
|
|
|
|
return hr;
|
2007-07-27 09:59:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************
|
|
|
|
* start of Icon-specific code
|
|
|
|
*/
|
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
|
|
|
|
{
|
2005-07-31 12:11:56 +00:00
|
|
|
HICON hicon;
|
|
|
|
CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
|
|
|
|
HDC hdcRef;
|
|
|
|
int i;
|
|
|
|
|
2015-11-17 11:59:11 +00:00
|
|
|
TRACE("(this %p, xbuf %p, xread %u)\n", This, xbuf, xread);
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/*
|
|
|
|
FIXME("icon.idReserved=%d\n",cifd->idReserved);
|
|
|
|
FIXME("icon.idType=%d\n",cifd->idType);
|
|
|
|
FIXME("icon.idCount=%d\n",cifd->idCount);
|
|
|
|
|
|
|
|
for (i=0;i<cifd->idCount;i++) {
|
|
|
|
FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
|
|
|
|
FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
|
|
|
|
FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
|
|
|
|
FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
|
|
|
|
FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
|
|
|
|
FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
|
|
|
|
FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
|
|
|
|
FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
|
|
|
|
}
|
|
|
|
*/
|
2015-11-17 11:59:11 +00:00
|
|
|
|
|
|
|
/* Need at least one icon to do something. */
|
|
|
|
if (!cifd->idCount)
|
|
|
|
{
|
|
|
|
ERR("Invalid icon count of zero.\n");
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
i=0;
|
|
|
|
/* If we have more than one icon, try to find the best.
|
|
|
|
* this currently means '32 pixel wide'.
|
|
|
|
*/
|
|
|
|
if (cifd->idCount!=1) {
|
|
|
|
for (i=0;i<cifd->idCount;i++) {
|
|
|
|
if (cifd->idEntries[i].bWidth == 32)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i==cifd->idCount) i=0;
|
|
|
|
}
|
2015-11-17 11:59:11 +00:00
|
|
|
if (xread < cifd->idEntries[i].dwDIBOffset + cifd->idEntries[i].dwDIBSize)
|
|
|
|
{
|
|
|
|
ERR("Icon data address %u is over %u bytes available.\n",
|
|
|
|
cifd->idEntries[i].dwDIBOffset + cifd->idEntries[i].dwDIBSize, xread);
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
2012-12-12 13:52:25 +00:00
|
|
|
if (cifd->idType == 2)
|
|
|
|
{
|
|
|
|
LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, cifd->idEntries[i].dwDIBSize + 4);
|
|
|
|
memcpy(buf, &cifd->idEntries[i].xHotspot, 4);
|
|
|
|
memcpy(buf + 4, xbuf+cifd->idEntries[i].dwDIBOffset, cifd->idEntries[i].dwDIBSize);
|
|
|
|
hicon = CreateIconFromResourceEx(
|
|
|
|
buf,
|
|
|
|
cifd->idEntries[i].dwDIBSize + 4,
|
|
|
|
FALSE, /* is cursor */
|
|
|
|
0x00030000,
|
|
|
|
cifd->idEntries[i].bWidth,
|
|
|
|
cifd->idEntries[i].bHeight,
|
|
|
|
0
|
|
|
|
);
|
|
|
|
HeapFree(GetProcessHeap(), 0, buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hicon = CreateIconFromResourceEx(
|
|
|
|
xbuf+cifd->idEntries[i].dwDIBOffset,
|
|
|
|
cifd->idEntries[i].dwDIBSize,
|
|
|
|
TRUE, /* is icon */
|
|
|
|
0x00030000,
|
|
|
|
cifd->idEntries[i].bWidth,
|
|
|
|
cifd->idEntries[i].bHeight,
|
|
|
|
0
|
|
|
|
);
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
if (!hicon) {
|
2009-01-15 17:52:35 +00:00
|
|
|
ERR("CreateIcon failed.\n");
|
2006-03-27 16:44:53 +00:00
|
|
|
return E_FAIL;
|
2005-07-31 12:11:56 +00:00
|
|
|
} else {
|
|
|
|
This->desc.picType = PICTYPE_ICON;
|
|
|
|
This->desc.u.icon.hicon = hicon;
|
|
|
|
This->origWidth = cifd->idEntries[i].bWidth;
|
|
|
|
This->origHeight = cifd->idEntries[i].bHeight;
|
|
|
|
hdcRef = CreateCompatibleDC(0);
|
2012-12-12 13:52:25 +00:00
|
|
|
This->himetricWidth = xpixels_to_himetric(cifd->idEntries[i].bWidth, hdcRef);
|
|
|
|
This->himetricHeight= ypixels_to_himetric(cifd->idEntries[i].bHeight, hdcRef);
|
2005-07-31 12:11:56 +00:00
|
|
|
DeleteDC(hdcRef);
|
2006-03-27 16:44:53 +00:00
|
|
|
return S_OK;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-15 17:52:35 +00:00
|
|
|
static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
|
|
|
|
const BYTE *data, ULONG size)
|
2007-07-27 09:59:17 +00:00
|
|
|
{
|
|
|
|
HENHMETAFILE hemf;
|
2009-01-15 17:52:35 +00:00
|
|
|
ENHMETAHEADER hdr;
|
2007-07-27 09:59:17 +00:00
|
|
|
|
|
|
|
hemf = SetEnhMetaFileBits(size, data);
|
|
|
|
if (!hemf) return E_FAIL;
|
|
|
|
|
2009-01-15 17:52:35 +00:00
|
|
|
GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
|
|
|
|
|
2007-07-27 09:59:17 +00:00
|
|
|
This->desc.picType = PICTYPE_ENHMETAFILE;
|
|
|
|
This->desc.u.emf.hemf = hemf;
|
|
|
|
|
|
|
|
This->origWidth = 0;
|
|
|
|
This->origHeight = 0;
|
2009-01-15 17:52:35 +00:00
|
|
|
This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
|
|
|
|
This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
|
2007-07-27 09:59:17 +00:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2008-01-15 19:22:36 +00:00
|
|
|
static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
|
|
|
|
const BYTE *data, ULONG size)
|
|
|
|
{
|
2010-04-20 17:36:44 +00:00
|
|
|
const APM_HEADER *header = (const APM_HEADER *)data;
|
2009-01-15 17:52:35 +00:00
|
|
|
HMETAFILE hmf;
|
2008-01-15 19:22:36 +00:00
|
|
|
|
|
|
|
if (size < sizeof(APM_HEADER))
|
|
|
|
return E_FAIL;
|
|
|
|
if (header->key != 0x9ac6cdd7)
|
|
|
|
return E_FAIL;
|
|
|
|
|
2009-01-15 17:52:35 +00:00
|
|
|
/* SetMetaFileBitsEx performs data check on its own */
|
|
|
|
hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
|
|
|
|
if (!hmf) return E_FAIL;
|
2008-01-15 19:22:36 +00:00
|
|
|
|
2009-01-15 17:52:35 +00:00
|
|
|
This->desc.picType = PICTYPE_METAFILE;
|
|
|
|
This->desc.u.wmf.hmeta = hmf;
|
|
|
|
This->desc.u.wmf.xExt = 0;
|
|
|
|
This->desc.u.wmf.yExt = 0;
|
|
|
|
|
|
|
|
This->origWidth = 0;
|
|
|
|
This->origHeight = 0;
|
2008-01-15 19:22:36 +00:00
|
|
|
This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
|
|
|
|
This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IPersistStream_Load (IUnknown)
|
|
|
|
*
|
|
|
|
* Loads the binary data from the IStream. Starts at current position.
|
|
|
|
* There appears to be an 2 DWORD header:
|
|
|
|
* DWORD magic;
|
|
|
|
* DWORD len;
|
|
|
|
*
|
2012-12-12 13:52:25 +00:00
|
|
|
* Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
|
2006-03-27 16:44:53 +00:00
|
|
|
*/
|
2012-12-12 13:52:25 +00:00
|
|
|
static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm) {
|
|
|
|
HRESULT hr;
|
|
|
|
BOOL headerisdata;
|
2006-03-27 16:44:53 +00:00
|
|
|
BOOL statfailed = FALSE;
|
|
|
|
ULONG xread, toread;
|
2007-04-20 11:44:43 +00:00
|
|
|
ULONG headerread;
|
2006-03-27 16:44:53 +00:00
|
|
|
BYTE *xbuf;
|
|
|
|
DWORD header[2];
|
|
|
|
WORD magic;
|
|
|
|
STATSTG statstg;
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
2008-01-15 19:22:36 +00:00
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
TRACE("(%p,%p)\n",This,pStm);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
/****************************************************************************************
|
|
|
|
* Part 1: Load the data
|
|
|
|
*/
|
|
|
|
/* Sometimes we have a header, sometimes we don't. Apply some guesses to find
|
|
|
|
* out whether we do.
|
|
|
|
*
|
|
|
|
* UPDATE: the IStream can be mapped to a plain file instead of a stream in a
|
|
|
|
* compound file. This may explain most, if not all, of the cases of "no
|
|
|
|
* header", and the header validation should take this into account.
|
|
|
|
* At least in Visual Basic 6, resource streams, valid headers are
|
|
|
|
* header[0] == "lt\0\0",
|
|
|
|
* header[1] == length_of_stream.
|
|
|
|
*
|
|
|
|
* Also handle streams where we do not have a working "Stat" method by
|
|
|
|
* reading all data until the end of the stream.
|
|
|
|
*/
|
2012-12-12 13:52:25 +00:00
|
|
|
hr = IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
|
|
|
|
if (hr != S_OK) {
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
|
2006-03-27 16:44:53 +00:00
|
|
|
statfailed = TRUE;
|
|
|
|
/* we will read at least 8 byte ... just right below */
|
|
|
|
statstg.cbSize.QuadPart = 8;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
toread = 0;
|
|
|
|
headerread = 0;
|
2006-03-27 16:44:53 +00:00
|
|
|
headerisdata = FALSE;
|
2007-04-20 11:44:43 +00:00
|
|
|
do {
|
2012-12-12 13:52:25 +00:00
|
|
|
hr = IStream_Read(pStm, header, 8, &xread);
|
|
|
|
if (hr != S_OK || xread!=8) {
|
2009-01-15 17:52:35 +00:00
|
|
|
ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
|
|
|
|
return (hr?hr:E_FAIL);
|
2007-04-20 11:44:43 +00:00
|
|
|
}
|
|
|
|
headerread += xread;
|
|
|
|
xread = 0;
|
2014-04-24 15:12:07 +00:00
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
|
2008-01-15 19:22:36 +00:00
|
|
|
if (toread != 0 && toread != header[1])
|
2007-04-20 11:44:43 +00:00
|
|
|
FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
|
|
|
|
toread, header[1]);
|
2007-04-20 10:28:01 +00:00
|
|
|
toread = header[1];
|
2014-04-24 15:12:07 +00:00
|
|
|
if (statfailed)
|
|
|
|
{
|
|
|
|
statstg.cbSize.QuadPart = header[1] + 8;
|
|
|
|
statfailed = FALSE;
|
|
|
|
}
|
2007-04-20 11:44:43 +00:00
|
|
|
if (toread == 0) break;
|
|
|
|
} else {
|
|
|
|
if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
|
|
|
|
!memcmp(&(header[0]), "BM", 2) || /* BMP header */
|
|
|
|
!memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
|
2008-01-15 19:22:36 +00:00
|
|
|
(header[0] == EMR_HEADER) || /* EMF header */
|
2012-12-12 13:52:25 +00:00
|
|
|
(header[0] == 0x10000) || /* icon: idReserved 0, idType 1 */
|
|
|
|
(header[0] == 0x20000) || /* cursor: idReserved 0, idType 2 */
|
2007-04-20 11:44:43 +00:00
|
|
|
(header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
|
|
|
|
(header[1]==0)
|
|
|
|
) {/* Found start of bitmap data */
|
|
|
|
headerisdata = TRUE;
|
2008-01-15 19:22:36 +00:00
|
|
|
if (toread == 0)
|
2007-04-20 11:44:43 +00:00
|
|
|
toread = statstg.cbSize.QuadPart-8;
|
|
|
|
else toread -= 8;
|
|
|
|
xread = 8;
|
|
|
|
} else {
|
|
|
|
FIXME("Unknown stream header magic: %08x\n", header[0]);
|
|
|
|
toread = header[1];
|
|
|
|
}
|
2006-03-27 16:44:53 +00:00
|
|
|
}
|
2007-04-20 11:44:43 +00:00
|
|
|
} while (!headerisdata);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
if (statfailed) { /* we don't know the size ... read all we get */
|
2013-03-23 11:24:29 +00:00
|
|
|
unsigned int sizeinc = 4096;
|
|
|
|
unsigned int origsize = sizeinc;
|
2006-03-27 16:44:53 +00:00
|
|
|
ULONG nread = 42;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
TRACE("Reading all data from stream.\n");
|
|
|
|
xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
|
|
|
|
if (headerisdata)
|
2008-09-14 05:15:39 +00:00
|
|
|
memcpy (xbuf, header, 8);
|
2006-03-27 16:44:53 +00:00
|
|
|
while (1) {
|
|
|
|
while (xread < origsize) {
|
|
|
|
hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
|
2012-12-12 13:52:25 +00:00
|
|
|
xread += nread;
|
|
|
|
if (hr != S_OK || !nread)
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-12-12 13:52:25 +00:00
|
|
|
if (!nread || hr != S_OK) /* done, or error */
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
|
|
|
if (xread == origsize) {
|
|
|
|
origsize += sizeinc;
|
|
|
|
sizeinc = 2*sizeinc; /* exponential increase */
|
|
|
|
xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
|
|
|
|
}
|
|
|
|
}
|
2012-12-12 13:52:25 +00:00
|
|
|
if (hr != S_OK)
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("hr in no-stat loader case is %08x\n", hr);
|
|
|
|
TRACE("loaded %d bytes.\n", xread);
|
2006-03-27 16:44:53 +00:00
|
|
|
This->datalen = xread;
|
|
|
|
This->data = xbuf;
|
|
|
|
} else {
|
|
|
|
This->datalen = toread+(headerisdata?8:0);
|
|
|
|
xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
|
2008-09-14 05:15:39 +00:00
|
|
|
if (!xbuf)
|
|
|
|
return E_OUTOFMEMORY;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
if (headerisdata)
|
2008-09-14 05:15:39 +00:00
|
|
|
memcpy (xbuf, header, 8);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
while (xread < This->datalen) {
|
|
|
|
ULONG nread;
|
|
|
|
hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
|
2012-12-12 13:52:25 +00:00
|
|
|
xread += nread;
|
|
|
|
if (hr != S_OK || !nread)
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (xread != This->datalen)
|
2009-01-15 17:52:35 +00:00
|
|
|
ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
|
2006-03-27 16:44:53 +00:00
|
|
|
}
|
|
|
|
if (This->datalen == 0) { /* Marks the "NONE" picture */
|
|
|
|
This->desc.picType = PICTYPE_NONE;
|
|
|
|
return S_OK;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
|
|
|
|
/****************************************************************************************
|
|
|
|
* Part 2: Process the loaded data
|
|
|
|
*/
|
|
|
|
|
|
|
|
magic = xbuf[0] + (xbuf[1]<<8);
|
2007-07-27 09:59:17 +00:00
|
|
|
This->loadtime_format = magic;
|
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
switch (magic) {
|
2008-07-10 09:14:19 +00:00
|
|
|
case BITMAP_FORMAT_GIF: /* GIF */
|
2009-08-22 19:07:35 +00:00
|
|
|
hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
2008-07-10 09:14:19 +00:00
|
|
|
case BITMAP_FORMAT_JPEG: /* JPEG */
|
2009-09-05 15:03:37 +00:00
|
|
|
hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
2008-07-10 09:14:19 +00:00
|
|
|
case BITMAP_FORMAT_BMP: /* Bitmap */
|
2018-01-28 16:05:15 +00:00
|
|
|
hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICBmpDecoder, xbuf, xread);
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
2008-07-10 09:14:19 +00:00
|
|
|
case BITMAP_FORMAT_PNG: /* PNG */
|
2009-09-05 15:03:37 +00:00
|
|
|
hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
|
2007-07-27 09:59:17 +00:00
|
|
|
break;
|
2008-07-10 09:14:19 +00:00
|
|
|
case BITMAP_FORMAT_APM: /* APM */
|
2008-01-15 19:22:36 +00:00
|
|
|
hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
|
|
|
|
break;
|
2012-12-12 13:52:25 +00:00
|
|
|
case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
|
2006-03-27 16:44:53 +00:00
|
|
|
hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
unsigned int i;
|
2007-07-27 09:59:17 +00:00
|
|
|
|
2009-01-15 17:52:35 +00:00
|
|
|
/* let's see if it's a EMF */
|
|
|
|
hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
|
2007-07-27 09:59:17 +00:00
|
|
|
if (hr == S_OK) break;
|
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
|
2006-03-27 16:44:53 +00:00
|
|
|
hr=E_FAIL;
|
|
|
|
for (i=0;i<xread+8;i++) {
|
2008-09-14 05:15:39 +00:00
|
|
|
if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
|
2006-03-27 16:44:53 +00:00
|
|
|
else MESSAGE("%02x ",xbuf[i-8]);
|
|
|
|
if (i % 10 == 9) MESSAGE("\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
2006-03-27 16:44:53 +00:00
|
|
|
MESSAGE("\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
This->bIsDirty = FALSE;
|
|
|
|
|
|
|
|
/* FIXME: this notify is not really documented */
|
|
|
|
if (hr==S_OK)
|
|
|
|
OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
|
|
|
|
return hr;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 15:12:07 +00:00
|
|
|
static BOOL serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2014-04-24 15:12:07 +00:00
|
|
|
BOOL success = FALSE;
|
2005-07-31 12:11:56 +00:00
|
|
|
HDC hDC;
|
|
|
|
BITMAPINFO * pInfoBitmap;
|
|
|
|
int iNumPaletteEntries;
|
|
|
|
unsigned char * pPixelData;
|
|
|
|
BITMAPFILEHEADER * pFileHeader;
|
|
|
|
BITMAPINFO * pInfoHeader;
|
|
|
|
|
|
|
|
pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
|
|
|
|
|
|
|
/* Find out bitmap size and padded length */
|
|
|
|
hDC = GetDC(0);
|
|
|
|
pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
|
|
|
|
GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
|
|
|
|
|
|
|
|
/* Fetch bitmap palette & pixel data */
|
|
|
|
|
|
|
|
pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
|
|
|
|
GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
|
|
|
|
|
|
|
|
/* Calculate the total length required for the BMP data */
|
|
|
|
if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
|
|
|
|
iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
|
|
|
|
if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
|
|
|
|
} else {
|
|
|
|
if (pInfoBitmap->bmiHeader.biBitCount <= 8)
|
|
|
|
iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
|
|
|
|
else
|
|
|
|
iNumPaletteEntries = 0;
|
|
|
|
}
|
|
|
|
*pLength =
|
|
|
|
sizeof(BITMAPFILEHEADER) +
|
|
|
|
sizeof(BITMAPINFOHEADER) +
|
|
|
|
iNumPaletteEntries * sizeof(RGBQUAD) +
|
|
|
|
pInfoBitmap->bmiHeader.biSizeImage;
|
|
|
|
*ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
|
|
|
|
|
|
|
|
/* Fill the BITMAPFILEHEADER */
|
2009-03-03 09:12:43 +00:00
|
|
|
pFileHeader = *ppBuffer;
|
2008-07-10 09:14:19 +00:00
|
|
|
pFileHeader->bfType = BITMAP_FORMAT_BMP;
|
2005-07-31 12:11:56 +00:00
|
|
|
pFileHeader->bfSize = *pLength;
|
|
|
|
pFileHeader->bfOffBits =
|
|
|
|
sizeof(BITMAPFILEHEADER) +
|
|
|
|
sizeof(BITMAPINFOHEADER) +
|
|
|
|
iNumPaletteEntries * sizeof(RGBQUAD);
|
|
|
|
|
|
|
|
/* Fill the BITMAPINFOHEADER and the palette data */
|
|
|
|
pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
|
|
|
|
memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
|
|
|
|
memcpy(
|
|
|
|
(unsigned char *)(*ppBuffer) +
|
|
|
|
sizeof(BITMAPFILEHEADER) +
|
|
|
|
sizeof(BITMAPINFOHEADER) +
|
|
|
|
iNumPaletteEntries * sizeof(RGBQUAD),
|
|
|
|
pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
|
2014-04-24 15:12:07 +00:00
|
|
|
success = TRUE;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, pPixelData);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pInfoBitmap);
|
2014-04-24 15:12:07 +00:00
|
|
|
return success;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 15:12:07 +00:00
|
|
|
static BOOL serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
ICONINFO infoIcon;
|
2014-04-24 15:12:07 +00:00
|
|
|
BOOL success = FALSE;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
*ppBuffer = NULL; *pLength = 0;
|
|
|
|
if (GetIconInfo(hIcon, &infoIcon)) {
|
|
|
|
HDC hDC;
|
|
|
|
BITMAPINFO * pInfoBitmap;
|
|
|
|
unsigned char * pIconData = NULL;
|
|
|
|
unsigned int iDataSize = 0;
|
|
|
|
|
|
|
|
pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
|
|
|
|
|
|
|
/* Find out icon size */
|
|
|
|
hDC = GetDC(0);
|
|
|
|
pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
|
|
|
|
GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
|
|
|
|
if (1) {
|
|
|
|
/* Auxiliary pointers */
|
|
|
|
CURSORICONFILEDIR * pIconDir;
|
|
|
|
CURSORICONFILEDIRENTRY * pIconEntry;
|
|
|
|
BITMAPINFOHEADER * pIconBitmapHeader;
|
|
|
|
unsigned int iOffsetPalette;
|
|
|
|
unsigned int iOffsetColorData;
|
|
|
|
unsigned int iOffsetMaskData;
|
|
|
|
|
|
|
|
unsigned int iLengthScanLineMask;
|
|
|
|
unsigned int iNumEntriesPalette;
|
|
|
|
|
|
|
|
iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
|
|
|
|
/*
|
|
|
|
FIXME("DEBUG: bitmap size is %d x %d\n",
|
|
|
|
pInfoBitmap->bmiHeader.biWidth,
|
|
|
|
pInfoBitmap->bmiHeader.biHeight);
|
|
|
|
FIXME("DEBUG: bitmap bpp is %d\n",
|
|
|
|
pInfoBitmap->bmiHeader.biBitCount);
|
|
|
|
FIXME("DEBUG: bitmap nplanes is %d\n",
|
|
|
|
pInfoBitmap->bmiHeader.biPlanes);
|
2007-04-20 11:44:43 +00:00
|
|
|
FIXME("DEBUG: bitmap biSizeImage is %u\n",
|
2005-07-31 12:11:56 +00:00
|
|
|
pInfoBitmap->bmiHeader.biSizeImage);
|
|
|
|
*/
|
|
|
|
/* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
|
|
|
|
iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
|
|
|
|
pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
|
|
|
|
|
|
|
|
/* Fill out the CURSORICONFILEDIR */
|
|
|
|
pIconDir = (CURSORICONFILEDIR *)pIconData;
|
|
|
|
pIconDir->idType = 1;
|
|
|
|
pIconDir->idCount = 1;
|
2012-12-12 13:52:25 +00:00
|
|
|
pIconDir->idReserved = 0;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* Fill out the CURSORICONFILEDIRENTRY */
|
|
|
|
pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
|
|
|
|
pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
|
|
|
|
pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
|
|
|
|
pIconEntry->bColorCount =
|
|
|
|
(pInfoBitmap->bmiHeader.biBitCount < 8)
|
|
|
|
? 1 << pInfoBitmap->bmiHeader.biBitCount
|
|
|
|
: 0;
|
|
|
|
pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
|
|
|
|
pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
|
|
|
|
pIconEntry->dwDIBSize = 0;
|
|
|
|
pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
|
|
|
|
|
|
|
|
/* Fill out the BITMAPINFOHEADER */
|
|
|
|
pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
|
2008-07-10 09:14:19 +00:00
|
|
|
*pIconBitmapHeader = pInfoBitmap->bmiHeader;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* Find out whether a palette exists for the bitmap */
|
|
|
|
if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
|
|
|
|
|| (pInfoBitmap->bmiHeader.biBitCount == 24)
|
|
|
|
|| (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
|
|
|
|
iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
|
2008-01-15 19:22:36 +00:00
|
|
|
if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
|
2005-07-31 12:11:56 +00:00
|
|
|
} else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
|
|
|
|
&& pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
|
|
|
|
iNumEntriesPalette = 3;
|
|
|
|
} else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
|
|
|
|
iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
|
|
|
|
} else {
|
|
|
|
iNumEntriesPalette = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add bitmap size and header size to icon data size. */
|
|
|
|
iOffsetPalette = iDataSize;
|
|
|
|
iDataSize += iNumEntriesPalette * sizeof(DWORD);
|
|
|
|
iOffsetColorData = iDataSize;
|
|
|
|
iDataSize += pIconBitmapHeader->biSizeImage;
|
|
|
|
iOffsetMaskData = iDataSize;
|
|
|
|
iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
|
|
|
|
pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
|
|
|
|
pIconBitmapHeader->biHeight *= 2;
|
|
|
|
pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
|
|
|
|
pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
|
|
|
|
pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
|
|
|
|
pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
|
|
|
|
|
|
|
|
/* Get the actual bitmap data from the icon bitmap */
|
|
|
|
GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
|
|
|
|
pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
|
|
|
|
if (iNumEntriesPalette > 0) {
|
|
|
|
memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
|
|
|
|
iNumEntriesPalette * sizeof(RGBQUAD));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset all values so that GetDIBits call succeeds */
|
|
|
|
memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
|
|
|
|
memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
|
|
|
pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
|
|
|
|
/*
|
|
|
|
if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
|
|
|
|
&& GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
|
|
|
|
pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
|
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
printf("ERROR: unable to get bitmap mask (error %u)\n",
|
2005-07-31 12:11:56 +00:00
|
|
|
GetLastError());
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
|
|
|
|
GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
|
|
|
|
|
|
|
|
/* Write out everything produced so far to the stream */
|
|
|
|
*ppBuffer = pIconData; *pLength = iDataSize;
|
2014-04-24 15:12:07 +00:00
|
|
|
success = TRUE;
|
2005-07-31 12:11:56 +00:00
|
|
|
} else {
|
|
|
|
/*
|
2007-04-20 11:44:43 +00:00
|
|
|
printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
|
2005-07-31 12:11:56 +00:00
|
|
|
GetLastError());
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
Remarks (from MSDN entry on GetIconInfo):
|
|
|
|
|
|
|
|
GetIconInfo creates bitmaps for the hbmMask and hbmColor
|
|
|
|
members of ICONINFO. The calling application must manage
|
|
|
|
these bitmaps and delete them when they are no longer
|
|
|
|
necessary.
|
|
|
|
*/
|
|
|
|
if (hDC) ReleaseDC(0, hDC);
|
|
|
|
DeleteObject(infoIcon.hbmMask);
|
|
|
|
if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pInfoBitmap);
|
|
|
|
} else {
|
2007-04-20 11:44:43 +00:00
|
|
|
printf("ERROR: Unable to get icon information (error %u)\n",
|
2005-07-31 12:11:56 +00:00
|
|
|
GetLastError());
|
|
|
|
}
|
2014-04-24 15:12:07 +00:00
|
|
|
return success;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
2018-01-28 16:05:15 +00:00
|
|
|
static BOOL serializeEMF(HENHMETAFILE hemf, void **buf, unsigned *size)
|
|
|
|
{
|
|
|
|
*size = GetEnhMetaFileBits(hemf, 0, NULL);
|
|
|
|
if (!*size) return FALSE;
|
|
|
|
|
|
|
|
*buf = HeapAlloc(GetProcessHeap(), 0, *size);
|
|
|
|
if (!*buf) return FALSE;
|
|
|
|
|
|
|
|
return GetEnhMetaFileBits(hemf, *size, *buf) != 0;
|
|
|
|
}
|
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
static HRESULT WINAPI OLEPictureImpl_Save(
|
|
|
|
IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
|
|
|
|
{
|
|
|
|
HRESULT hResult = E_NOTIMPL;
|
|
|
|
void * pIconData;
|
|
|
|
unsigned int iDataSize;
|
2012-12-12 13:52:25 +00:00
|
|
|
DWORD header[2];
|
2006-03-27 16:44:53 +00:00
|
|
|
ULONG dummy;
|
2014-04-24 15:12:07 +00:00
|
|
|
BOOL serializeResult = FALSE;
|
2007-04-20 11:44:43 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
2006-03-27 16:44:53 +00:00
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("%p %p %d\n", This, pStm, fClearDirty);
|
2006-03-27 16:44:53 +00:00
|
|
|
|
|
|
|
switch (This->desc.picType) {
|
2012-12-12 13:52:25 +00:00
|
|
|
case PICTYPE_NONE:
|
|
|
|
header[0] = 0x0000746c;
|
|
|
|
header[1] = 0;
|
|
|
|
hResult = IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
|
|
|
|
break;
|
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
case PICTYPE_ICON:
|
2007-04-20 11:44:43 +00:00
|
|
|
if (This->bIsDirty || !This->data) {
|
|
|
|
if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
|
|
|
|
ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
|
2006-03-27 16:44:53 +00:00
|
|
|
hResult = E_FAIL;
|
2007-04-20 11:44:43 +00:00
|
|
|
break;
|
2006-03-27 16:44:53 +00:00
|
|
|
}
|
2007-04-20 11:44:43 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, This->data);
|
|
|
|
This->data = pIconData;
|
|
|
|
This->datalen = iDataSize;
|
|
|
|
}
|
2006-03-27 16:44:53 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
|
|
|
|
header[1] = This->datalen;
|
|
|
|
IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
|
2007-04-20 11:44:43 +00:00
|
|
|
IStream_Write(pStm, This->data, This->datalen, &dummy);
|
|
|
|
hResult = S_OK;
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
|
|
|
case PICTYPE_BITMAP:
|
2012-12-12 13:52:25 +00:00
|
|
|
if (This->bIsDirty || !This->data) {
|
2008-07-10 09:14:19 +00:00
|
|
|
switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
|
|
|
|
case BITMAP_FORMAT_BMP:
|
2014-04-24 15:12:07 +00:00
|
|
|
serializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
2008-07-10 09:14:19 +00:00
|
|
|
case BITMAP_FORMAT_JPEG:
|
2006-03-27 16:44:53 +00:00
|
|
|
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
|
|
|
|
break;
|
2008-07-10 09:14:19 +00:00
|
|
|
case BITMAP_FORMAT_GIF:
|
2006-03-27 16:44:53 +00:00
|
|
|
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
|
|
|
|
break;
|
2008-07-10 09:14:19 +00:00
|
|
|
case BITMAP_FORMAT_PNG:
|
2007-07-27 09:59:17 +00:00
|
|
|
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
|
|
|
|
break;
|
2006-03-27 16:44:53 +00:00
|
|
|
default:
|
|
|
|
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
|
|
|
|
break;
|
|
|
|
}
|
2012-12-12 13:52:25 +00:00
|
|
|
|
2014-04-24 15:12:07 +00:00
|
|
|
if (!serializeResult)
|
2012-12-12 13:52:25 +00:00
|
|
|
{
|
|
|
|
hResult = E_FAIL;
|
|
|
|
break;
|
2006-03-27 16:44:53 +00:00
|
|
|
}
|
2012-12-12 13:52:25 +00:00
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, This->data);
|
|
|
|
This->data = pIconData;
|
|
|
|
This->datalen = iDataSize;
|
2006-03-27 16:44:53 +00:00
|
|
|
}
|
2012-12-12 13:52:25 +00:00
|
|
|
|
|
|
|
header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
|
|
|
|
header[1] = This->datalen;
|
|
|
|
IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
|
|
|
|
IStream_Write(pStm, This->data, This->datalen, &dummy);
|
|
|
|
hResult = S_OK;
|
2006-03-27 16:44:53 +00:00
|
|
|
break;
|
2018-01-28 16:05:15 +00:00
|
|
|
|
|
|
|
case PICTYPE_ENHMETAFILE:
|
|
|
|
if (This->bIsDirty || !This->data)
|
|
|
|
{
|
|
|
|
serializeResult = serializeEMF(This->desc.u.emf.hemf, &pIconData, &iDataSize);
|
|
|
|
if (!serializeResult)
|
|
|
|
{
|
|
|
|
hResult = E_FAIL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, This->data);
|
|
|
|
This->data = pIconData;
|
|
|
|
This->datalen = iDataSize;
|
|
|
|
}
|
|
|
|
header[0] = 0x0000746c;
|
|
|
|
header[1] = This->datalen;
|
|
|
|
IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
|
|
|
|
IStream_Write(pStm, This->data, This->datalen, &dummy);
|
|
|
|
hResult = S_OK;
|
|
|
|
break;
|
|
|
|
|
2006-03-27 16:44:53 +00:00
|
|
|
case PICTYPE_METAFILE:
|
|
|
|
FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
|
|
|
|
return hResult;
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
|
|
|
|
IPersistStream* iface,ULARGE_INTEGER*pcbSize)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
FIXME("(%p,%p),stub!\n",This,pcbSize);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2018-01-28 16:05:15 +00:00
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_SaveAsFile
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
|
|
|
|
IStream *stream, BOOL mem_copy, LONG *size)
|
|
|
|
{
|
|
|
|
OLEPictureImpl *This = impl_from_IPicture(iface);
|
|
|
|
void *data;
|
|
|
|
unsigned data_size;
|
|
|
|
ULONG written;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
FIXME("(%p)->(%p,%d,%p): semi-stub\n", This, stream, mem_copy, size);
|
|
|
|
|
|
|
|
switch (This->desc.picType)
|
|
|
|
{
|
|
|
|
case PICTYPE_NONE:
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
case PICTYPE_ICON:
|
|
|
|
if (!mem_copy) return E_FAIL;
|
|
|
|
|
|
|
|
if (This->bIsDirty || !This->data)
|
|
|
|
{
|
|
|
|
if (!serializeIcon(This->desc.u.icon.hicon, &data, &data_size))
|
|
|
|
return E_FAIL;
|
|
|
|
HeapFree(GetProcessHeap(), 0, This->data);
|
|
|
|
This->data = data;
|
|
|
|
This->datalen = data_size;
|
|
|
|
}
|
|
|
|
hr = IStream_Write(stream, This->data, This->datalen, &written);
|
|
|
|
if (hr == S_OK && size) *size = written;
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
case PICTYPE_BITMAP:
|
|
|
|
if (!mem_copy) return E_FAIL;
|
|
|
|
|
|
|
|
if (This->bIsDirty || !This->data)
|
|
|
|
{
|
|
|
|
switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP)
|
|
|
|
{
|
|
|
|
case BITMAP_FORMAT_BMP:
|
|
|
|
if (!serializeBMP(This->desc.u.bmp.hbitmap, &data, &data_size))
|
|
|
|
return E_FAIL;
|
|
|
|
break;
|
|
|
|
case BITMAP_FORMAT_JPEG:
|
|
|
|
FIXME("BITMAP_FORMAT_JPEG is not implemented\n");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
case BITMAP_FORMAT_GIF:
|
|
|
|
FIXME("BITMAP_FORMAT_GIF is not implemented\n");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
case BITMAP_FORMAT_PNG:
|
|
|
|
FIXME("BITMAP_FORMAT_PNG is not implemented\n");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
default:
|
|
|
|
FIXME("PICTYPE_BITMAP/%#x is not implemented\n", This->loadtime_format);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, This->data);
|
|
|
|
This->data = data;
|
|
|
|
This->datalen = data_size;
|
|
|
|
}
|
|
|
|
hr = IStream_Write(stream, This->data, This->datalen, &written);
|
|
|
|
if (hr == S_OK && size) *size = written;
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
case PICTYPE_METAFILE:
|
|
|
|
FIXME("PICTYPE_METAFILE is not implemented\n");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
|
|
|
|
case PICTYPE_ENHMETAFILE:
|
|
|
|
if (!mem_copy) return E_FAIL;
|
|
|
|
|
|
|
|
if (This->bIsDirty || !This->data)
|
|
|
|
{
|
|
|
|
if (!serializeEMF(This->desc.u.emf.hemf, &data, &data_size))
|
|
|
|
return E_FAIL;
|
|
|
|
HeapFree(GetProcessHeap(), 0, This->data);
|
|
|
|
This->data = data;
|
|
|
|
This->datalen = data_size;
|
|
|
|
}
|
|
|
|
hr = IStream_Write(stream, This->data, This->datalen, &written);
|
|
|
|
if (hr == S_OK && size) *size = written;
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
default:
|
|
|
|
FIXME("%#x is not implemented\n", This->desc.picType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
2006-03-27 16:44:53 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/************************************************************************
|
|
|
|
* IDispatch
|
|
|
|
*/
|
2006-03-27 16:44:53 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
|
|
|
|
IDispatch* iface,
|
|
|
|
REFIID riid,
|
|
|
|
VOID** ppvoid)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IDispatch(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IDispatch_AddRef (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
|
|
|
|
IDispatch* iface)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IDispatch(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_AddRef(&This->IPicture_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_IDispatch_Release (IUnknown)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IUnknown methods.
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
|
|
|
|
IDispatch* iface)
|
|
|
|
{
|
2005-09-05 22:00:07 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IDispatch(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_Release(&This->IPicture_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_GetTypeInfoCount (IDispatch)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IDispatch methods.
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
|
|
|
|
IDispatch* iface,
|
|
|
|
unsigned int* pctinfo)
|
|
|
|
{
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%p)\n", pctinfo);
|
2007-04-20 02:30:53 +00:00
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
*pctinfo = 1;
|
|
|
|
|
|
|
|
return S_OK;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_GetTypeInfo (IDispatch)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IDispatch methods.
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
|
|
|
|
IDispatch* iface,
|
|
|
|
UINT iTInfo,
|
|
|
|
LCID lcid,
|
|
|
|
ITypeInfo** ppTInfo)
|
|
|
|
{
|
2007-04-20 11:44:43 +00:00
|
|
|
static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
|
|
|
|
ITypeLib *tl;
|
|
|
|
HRESULT hres;
|
2007-04-20 02:30:53 +00:00
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
|
|
|
|
|
|
|
|
if (iTInfo != 0)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
hres = LoadTypeLib(stdole2tlb, &tl);
|
|
|
|
if (FAILED(hres))
|
|
|
|
{
|
|
|
|
ERR("Could not load stdole2.tlb\n");
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
|
|
|
|
if (FAILED(hres))
|
|
|
|
ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
|
|
|
|
|
|
|
|
return hres;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_GetIDsOfNames (IDispatch)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IDispatch methods.
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
|
|
|
|
IDispatch* iface,
|
|
|
|
REFIID riid,
|
|
|
|
LPOLESTR* rgszNames,
|
|
|
|
UINT cNames,
|
|
|
|
LCID lcid,
|
|
|
|
DISPID* rgDispId)
|
|
|
|
{
|
2008-01-15 19:22:36 +00:00
|
|
|
ITypeInfo * pTInfo;
|
|
|
|
HRESULT hres;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2008-01-15 19:22:36 +00:00
|
|
|
TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
|
|
|
|
rgszNames, cNames, (int)lcid, rgDispId);
|
|
|
|
|
|
|
|
if (cNames == 0)
|
|
|
|
{
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* retrieve type information */
|
|
|
|
hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
|
|
|
|
|
|
|
|
if (FAILED(hres))
|
|
|
|
{
|
|
|
|
ERR("GetTypeInfo failed.\n");
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert names to DISPIDs */
|
|
|
|
hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
|
|
|
|
ITypeInfo_Release(pTInfo);
|
|
|
|
|
|
|
|
return hres;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* OLEPictureImpl_Invoke (IDispatch)
|
|
|
|
*
|
|
|
|
* See Windows documentation for more details on IDispatch methods.
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI OLEPictureImpl_Invoke(
|
|
|
|
IDispatch* iface,
|
|
|
|
DISPID dispIdMember,
|
|
|
|
REFIID riid,
|
|
|
|
LCID lcid,
|
|
|
|
WORD wFlags,
|
|
|
|
DISPPARAMS* pDispParams,
|
|
|
|
VARIANT* pVarResult,
|
|
|
|
EXCEPINFO* pExepInfo,
|
|
|
|
UINT* puArgErr)
|
|
|
|
{
|
2006-03-27 16:44:53 +00:00
|
|
|
OLEPictureImpl *This = impl_from_IDispatch(iface);
|
2014-04-24 15:12:07 +00:00
|
|
|
HRESULT hr;
|
2007-04-20 11:44:43 +00:00
|
|
|
|
|
|
|
/* validate parameters */
|
|
|
|
|
|
|
|
if (!IsEqualIID(riid, &IID_NULL))
|
|
|
|
{
|
|
|
|
ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
|
|
|
|
return DISP_E_UNKNOWNNAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pDispParams)
|
|
|
|
{
|
|
|
|
ERR("null pDispParams not allowed\n");
|
|
|
|
return DISP_E_PARAMNOTOPTIONAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wFlags & DISPATCH_PROPERTYGET)
|
2006-03-27 16:44:53 +00:00
|
|
|
{
|
|
|
|
if (pDispParams->cArgs != 0)
|
|
|
|
{
|
2007-04-20 11:44:43 +00:00
|
|
|
ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
|
|
|
|
return DISP_E_BADPARAMCOUNT;
|
|
|
|
}
|
|
|
|
if (!pVarResult)
|
|
|
|
{
|
|
|
|
ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
|
|
|
|
return DISP_E_PARAMNOTOPTIONAL;
|
2007-04-20 02:30:53 +00:00
|
|
|
}
|
|
|
|
}
|
2007-04-20 11:44:43 +00:00
|
|
|
else if (wFlags & DISPATCH_PROPERTYPUT)
|
2007-04-20 02:30:53 +00:00
|
|
|
{
|
2007-04-20 11:44:43 +00:00
|
|
|
if (pDispParams->cArgs != 1)
|
|
|
|
{
|
|
|
|
ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
|
|
|
|
return DISP_E_BADPARAMCOUNT;
|
|
|
|
}
|
|
|
|
}
|
2007-04-20 02:30:53 +00:00
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
switch (dispIdMember)
|
|
|
|
{
|
|
|
|
case DISPID_PICT_HANDLE:
|
|
|
|
if (wFlags & DISPATCH_PROPERTYGET)
|
|
|
|
{
|
|
|
|
TRACE("DISPID_PICT_HANDLE\n");
|
|
|
|
V_VT(pVarResult) = VT_I4;
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_get_Handle(&This->IPicture_iface, &V_UINT(pVarResult));
|
2007-04-20 11:44:43 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DISPID_PICT_HPAL:
|
|
|
|
if (wFlags & DISPATCH_PROPERTYGET)
|
|
|
|
{
|
|
|
|
TRACE("DISPID_PICT_HPAL\n");
|
|
|
|
V_VT(pVarResult) = VT_I4;
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_get_hPal(&This->IPicture_iface, &V_UINT(pVarResult));
|
2007-04-20 11:44:43 +00:00
|
|
|
}
|
|
|
|
else if (wFlags & DISPATCH_PROPERTYPUT)
|
|
|
|
{
|
|
|
|
VARIANTARG vararg;
|
2014-04-24 15:12:07 +00:00
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("DISPID_PICT_HPAL\n");
|
|
|
|
|
|
|
|
VariantInit(&vararg);
|
|
|
|
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
|
|
|
|
if (FAILED(hr))
|
|
|
|
return hr;
|
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
hr = IPicture_set_hPal(&This->IPicture_iface, V_I4(&vararg));
|
2007-04-20 11:44:43 +00:00
|
|
|
|
|
|
|
VariantClear(&vararg);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DISPID_PICT_TYPE:
|
|
|
|
if (wFlags & DISPATCH_PROPERTYGET)
|
|
|
|
{
|
|
|
|
TRACE("DISPID_PICT_TYPE\n");
|
|
|
|
V_VT(pVarResult) = VT_I2;
|
2012-12-12 13:52:25 +00:00
|
|
|
return OLEPictureImpl_get_Type(&This->IPicture_iface, &V_I2(pVarResult));
|
2007-04-20 11:44:43 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DISPID_PICT_WIDTH:
|
|
|
|
if (wFlags & DISPATCH_PROPERTYGET)
|
|
|
|
{
|
|
|
|
TRACE("DISPID_PICT_WIDTH\n");
|
|
|
|
V_VT(pVarResult) = VT_I4;
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_get_Width(&This->IPicture_iface, &V_I4(pVarResult));
|
2007-04-20 11:44:43 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DISPID_PICT_HEIGHT:
|
|
|
|
if (wFlags & DISPATCH_PROPERTYGET)
|
|
|
|
{
|
|
|
|
TRACE("DISPID_PICT_HEIGHT\n");
|
|
|
|
V_VT(pVarResult) = VT_I4;
|
2012-12-12 13:52:25 +00:00
|
|
|
return IPicture_get_Height(&This->IPicture_iface, &V_I4(pVarResult));
|
2007-04-20 11:44:43 +00:00
|
|
|
}
|
|
|
|
break;
|
2014-04-24 15:12:07 +00:00
|
|
|
case DISPID_PICT_RENDER:
|
|
|
|
if (wFlags & DISPATCH_METHOD)
|
|
|
|
{
|
|
|
|
VARIANTARG *args = pDispParams->rgvarg;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
TRACE("DISPID_PICT_RENDER\n");
|
|
|
|
|
|
|
|
if (pDispParams->cArgs != 10)
|
|
|
|
return DISP_E_BADPARAMCOUNT;
|
|
|
|
|
|
|
|
/* All parameters are supposed to be VT_I4 (on 64 bits too). */
|
|
|
|
for (i = 0; i < pDispParams->cArgs; i++)
|
|
|
|
if (V_VT(&args[i]) != VT_I4)
|
|
|
|
{
|
|
|
|
ERR("DISPID_PICT_RENDER: wrong argument type %d:%d\n", i, V_VT(&args[i]));
|
|
|
|
return DISP_E_TYPEMISMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: rectangle pointer argument handling seems broken on 64 bits,
|
|
|
|
currently Render() doesn't use it at all so for now NULL is passed. */
|
|
|
|
return IPicture_Render(&This->IPicture_iface,
|
|
|
|
LongToHandle(V_I4(&args[9])),
|
|
|
|
V_I4(&args[8]),
|
|
|
|
V_I4(&args[7]),
|
|
|
|
V_I4(&args[6]),
|
|
|
|
V_I4(&args[5]),
|
|
|
|
V_I4(&args[4]),
|
|
|
|
V_I4(&args[3]),
|
|
|
|
V_I4(&args[2]),
|
|
|
|
V_I4(&args[1]),
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
break;
|
2006-03-27 16:44:53 +00:00
|
|
|
}
|
2007-04-20 11:44:43 +00:00
|
|
|
|
|
|
|
ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
|
|
|
|
return DISP_E_MEMBERNOTFOUND;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-08-03 22:46:31 +00:00
|
|
|
static const IPictureVtbl OLEPictureImpl_VTable =
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
OLEPictureImpl_QueryInterface,
|
|
|
|
OLEPictureImpl_AddRef,
|
|
|
|
OLEPictureImpl_Release,
|
|
|
|
OLEPictureImpl_get_Handle,
|
|
|
|
OLEPictureImpl_get_hPal,
|
|
|
|
OLEPictureImpl_get_Type,
|
|
|
|
OLEPictureImpl_get_Width,
|
|
|
|
OLEPictureImpl_get_Height,
|
|
|
|
OLEPictureImpl_Render,
|
|
|
|
OLEPictureImpl_set_hPal,
|
|
|
|
OLEPictureImpl_get_CurDC,
|
|
|
|
OLEPictureImpl_SelectPicture,
|
|
|
|
OLEPictureImpl_get_KeepOriginalFormat,
|
|
|
|
OLEPictureImpl_put_KeepOriginalFormat,
|
|
|
|
OLEPictureImpl_PictureChanged,
|
|
|
|
OLEPictureImpl_SaveAsFile,
|
|
|
|
OLEPictureImpl_get_Attributes
|
|
|
|
};
|
|
|
|
|
2005-08-03 22:46:31 +00:00
|
|
|
static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
OLEPictureImpl_IDispatch_QueryInterface,
|
|
|
|
OLEPictureImpl_IDispatch_AddRef,
|
|
|
|
OLEPictureImpl_IDispatch_Release,
|
|
|
|
OLEPictureImpl_GetTypeInfoCount,
|
|
|
|
OLEPictureImpl_GetTypeInfo,
|
|
|
|
OLEPictureImpl_GetIDsOfNames,
|
|
|
|
OLEPictureImpl_Invoke
|
|
|
|
};
|
|
|
|
|
2005-08-03 22:46:31 +00:00
|
|
|
static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
OLEPictureImpl_IPersistStream_QueryInterface,
|
|
|
|
OLEPictureImpl_IPersistStream_AddRef,
|
|
|
|
OLEPictureImpl_IPersistStream_Release,
|
|
|
|
OLEPictureImpl_GetClassID,
|
|
|
|
OLEPictureImpl_IsDirty,
|
|
|
|
OLEPictureImpl_Load,
|
|
|
|
OLEPictureImpl_Save,
|
|
|
|
OLEPictureImpl_GetSizeMax
|
|
|
|
};
|
|
|
|
|
2005-08-03 22:46:31 +00:00
|
|
|
static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
OLEPictureImpl_IConnectionPointContainer_QueryInterface,
|
|
|
|
OLEPictureImpl_IConnectionPointContainer_AddRef,
|
|
|
|
OLEPictureImpl_IConnectionPointContainer_Release,
|
|
|
|
OLEPictureImpl_EnumConnectionPoints,
|
|
|
|
OLEPictureImpl_FindConnectionPoint
|
|
|
|
};
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* OleCreatePictureIndirect (OLEAUT32.419)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
|
2012-12-12 13:52:25 +00:00
|
|
|
BOOL Own, void **ppvObj )
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2012-12-12 13:52:25 +00:00
|
|
|
OLEPictureImpl* newPict;
|
|
|
|
HRESULT hr;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), Own, ppvObj);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
*ppvObj = NULL;
|
|
|
|
|
2019-01-29 12:18:42 +00:00
|
|
|
hr = OLEPictureImpl_Construct(lpPictDesc, Own, &newPict);
|
|
|
|
if (hr != S_OK) return hr;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure it supports the interface required by the caller.
|
|
|
|
*/
|
2012-12-12 13:52:25 +00:00
|
|
|
hr = IPicture_QueryInterface(&newPict->IPicture_iface, riid, ppvObj);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Release the reference obtained in the constructor. If
|
|
|
|
* the QueryInterface was unsuccessful, it will free the class.
|
|
|
|
*/
|
2012-12-12 13:52:25 +00:00
|
|
|
IPicture_Release(&newPict->IPicture_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* OleLoadPicture (OLEAUT32.418)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
|
|
|
|
REFIID riid, LPVOID *ppvObj )
|
|
|
|
{
|
|
|
|
LPPERSISTSTREAM ps;
|
|
|
|
IPicture *newpic;
|
|
|
|
HRESULT hr;
|
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
|
2005-07-31 12:11:56 +00:00
|
|
|
lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
|
|
|
|
|
|
|
|
hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
|
2012-12-12 13:52:25 +00:00
|
|
|
if (hr != S_OK)
|
2005-07-31 12:11:56 +00:00
|
|
|
return hr;
|
|
|
|
hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
|
2012-12-12 13:52:25 +00:00
|
|
|
if (hr != S_OK) {
|
2009-01-15 17:52:35 +00:00
|
|
|
ERR("Could not get IPersistStream iface from Ole Picture?\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
IPicture_Release(newpic);
|
|
|
|
*ppvObj = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
2008-09-14 05:15:39 +00:00
|
|
|
hr = IPersistStream_Load(ps,lpstream);
|
2005-07-31 12:11:56 +00:00
|
|
|
IPersistStream_Release(ps);
|
2008-09-14 05:15:39 +00:00
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
ERR("IPersistStream_Load failed\n");
|
|
|
|
IPicture_Release(newpic);
|
|
|
|
*ppvObj = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
hr = IPicture_QueryInterface(newpic,riid,ppvObj);
|
2012-12-12 13:52:25 +00:00
|
|
|
if (hr != S_OK)
|
2009-01-15 17:52:35 +00:00
|
|
|
ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
|
2005-07-31 12:11:56 +00:00
|
|
|
IPicture_Release(newpic);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* OleLoadPictureEx (OLEAUT32.401)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
|
|
|
|
REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
|
|
|
|
{
|
|
|
|
LPPERSISTSTREAM ps;
|
|
|
|
IPicture *newpic;
|
|
|
|
HRESULT hr;
|
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
|
2005-07-31 12:11:56 +00:00
|
|
|
lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
|
|
|
|
|
|
|
|
hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
|
2012-12-12 13:52:25 +00:00
|
|
|
if (hr != S_OK)
|
2005-07-31 12:11:56 +00:00
|
|
|
return hr;
|
|
|
|
hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
|
2012-12-12 13:52:25 +00:00
|
|
|
if (hr != S_OK) {
|
2009-01-15 17:52:35 +00:00
|
|
|
ERR("Could not get IPersistStream iface from Ole Picture?\n");
|
2005-07-31 12:11:56 +00:00
|
|
|
IPicture_Release(newpic);
|
|
|
|
*ppvObj = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
2009-01-15 17:52:35 +00:00
|
|
|
hr = IPersistStream_Load(ps,lpstream);
|
2005-07-31 12:11:56 +00:00
|
|
|
IPersistStream_Release(ps);
|
2009-01-15 17:52:35 +00:00
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
ERR("IPersistStream_Load failed\n");
|
|
|
|
IPicture_Release(newpic);
|
|
|
|
*ppvObj = NULL;
|
|
|
|
return hr;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
hr = IPicture_QueryInterface(newpic,riid,ppvObj);
|
2012-12-12 13:52:25 +00:00
|
|
|
if (hr != S_OK)
|
2009-01-15 17:52:35 +00:00
|
|
|
ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
|
2005-07-31 12:11:56 +00:00
|
|
|
IPicture_Release(newpic);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2018-01-28 16:05:15 +00:00
|
|
|
static HRESULT create_stream(const WCHAR *filename, IStream **stream)
|
|
|
|
{
|
|
|
|
HANDLE hFile;
|
|
|
|
DWORD dwFileSize;
|
|
|
|
HGLOBAL hGlobal = NULL;
|
|
|
|
DWORD dwBytesRead;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
|
|
hFile = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
|
|
|
|
dwFileSize = GetFileSize(hFile, NULL);
|
|
|
|
if (dwFileSize != INVALID_FILE_SIZE)
|
|
|
|
{
|
|
|
|
hGlobal = GlobalAlloc(GMEM_FIXED, dwFileSize);
|
|
|
|
if (!hGlobal)
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL))
|
|
|
|
{
|
|
|
|
GlobalFree(hGlobal);
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle(hFile);
|
|
|
|
|
|
|
|
if (FAILED(hr)) return hr;
|
|
|
|
|
|
|
|
hr = CreateStreamOnHGlobal(hGlobal, TRUE, stream);
|
|
|
|
if (FAILED(hr))
|
|
|
|
GlobalFree(hGlobal);
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2016-06-07 10:51:58 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* OleLoadPictureFile (OLEAUT32.422)
|
|
|
|
*/
|
2018-01-28 16:05:15 +00:00
|
|
|
HRESULT WINAPI OleLoadPictureFile(VARIANT filename, IDispatch **picture)
|
2016-06-07 10:51:58 +00:00
|
|
|
{
|
2018-01-28 16:05:15 +00:00
|
|
|
IStream *stream;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%s,%p)\n", wine_dbgstr_variant(&filename), picture);
|
|
|
|
|
|
|
|
if (V_VT(&filename) != VT_BSTR)
|
|
|
|
return CTL_E_FILENOTFOUND;
|
|
|
|
|
|
|
|
hr = create_stream(V_BSTR(&filename), &stream);
|
|
|
|
if (hr != S_OK)
|
|
|
|
{
|
|
|
|
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
|
|
|
return CTL_E_FILENOTFOUND;
|
|
|
|
|
|
|
|
return CTL_E_PATHFILEACCESSERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = OleLoadPicture(stream, 0, FALSE, &IID_IDispatch, (void **)picture);
|
|
|
|
IStream_Release(stream);
|
|
|
|
return hr;
|
2016-06-07 10:51:58 +00:00
|
|
|
}
|
|
|
|
|
2015-04-15 18:09:13 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* OleSavePictureFile (OLEAUT32.423)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI OleSavePictureFile(IDispatch *picture, BSTR filename)
|
|
|
|
{
|
|
|
|
FIXME("(%p %s): stub\n", picture, debugstr_w(filename));
|
|
|
|
return CTL_E_FILENOTFOUND;
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* OleLoadPicturePath (OLEAUT32.424)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
|
|
|
|
DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
|
|
|
|
LPVOID *ppvRet )
|
|
|
|
{
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
static const WCHAR file[] = { 'f','i','l','e',':',0 };
|
2005-07-31 12:11:56 +00:00
|
|
|
IStream *stream;
|
|
|
|
HRESULT hRes;
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
WCHAR *file_candidate;
|
|
|
|
WCHAR path_buf[MAX_PATH];
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2007-04-20 11:44:43 +00:00
|
|
|
TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
|
2005-07-31 12:11:56 +00:00
|
|
|
debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
|
|
|
|
debugstr_guid(riid), ppvRet);
|
|
|
|
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
if (!szURLorPath || !ppvRet)
|
|
|
|
return E_INVALIDARG;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
*ppvRet = NULL;
|
|
|
|
|
|
|
|
/* Convert file URLs to DOS paths. */
|
2019-11-23 11:05:03 +00:00
|
|
|
if (wcsncmp(szURLorPath, file, 5) == 0) {
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
DWORD size;
|
|
|
|
hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
|
2019-01-29 12:18:42 +00:00
|
|
|
ARRAY_SIZE(path_buf), &size, 0);
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
if (FAILED(hRes))
|
|
|
|
return hRes;
|
|
|
|
|
|
|
|
file_candidate = path_buf;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
file_candidate = szURLorPath;
|
|
|
|
|
|
|
|
/* Handle candidate DOS paths separately. */
|
|
|
|
if (file_candidate[1] == ':') {
|
2018-01-28 16:05:15 +00:00
|
|
|
hRes = create_stream(file_candidate, &stream);
|
|
|
|
if (FAILED(hRes))
|
2012-12-12 13:52:25 +00:00
|
|
|
return INET_E_RESOURCE_NOT_FOUND;
|
2005-07-31 12:11:56 +00:00
|
|
|
} else {
|
|
|
|
IMoniker *pmnk;
|
|
|
|
IBindCtx *pbc;
|
|
|
|
|
|
|
|
hRes = CreateBindCtx(0, &pbc);
|
2008-01-15 19:22:36 +00:00
|
|
|
if (SUCCEEDED(hRes))
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
|
|
|
|
if (SUCCEEDED(hRes))
|
2008-01-15 19:22:36 +00:00
|
|
|
{
|
2005-07-31 12:11:56 +00:00
|
|
|
hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
|
|
|
|
IMoniker_Release(pmnk);
|
|
|
|
}
|
|
|
|
IBindCtx_Release(pbc);
|
|
|
|
}
|
|
|
|
if (FAILED(hRes))
|
|
|
|
return hRes;
|
|
|
|
}
|
|
|
|
|
2018-01-28 16:05:15 +00:00
|
|
|
hRes = OleLoadPicture(stream, 0, FALSE, riid, ppvRet);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
IStream_Release(stream);
|
|
|
|
|
|
|
|
return hRes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* StdPic ClassFactory
|
|
|
|
*/
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* IUnknown fields */
|
2012-12-12 13:52:25 +00:00
|
|
|
IClassFactory IClassFactory_iface;
|
|
|
|
LONG ref;
|
2005-07-31 12:11:56 +00:00
|
|
|
} IClassFactoryImpl;
|
|
|
|
|
2012-12-12 13:52:25 +00:00
|
|
|
static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
static HRESULT WINAPI
|
|
|
|
SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
|
2012-12-12 13:52:25 +00:00
|
|
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI
|
|
|
|
SPCF_AddRef(LPCLASSFACTORY iface) {
|
2012-12-12 13:52:25 +00:00
|
|
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
return InterlockedIncrement(&This->ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
|
2012-12-12 13:52:25 +00:00
|
|
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
/* static class, won't be freed */
|
|
|
|
return InterlockedDecrement(&This->ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI SPCF_CreateInstance(
|
|
|
|
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
|
|
|
|
) {
|
|
|
|
/* Creates an uninitialized picture */
|
|
|
|
return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
|
2012-12-12 13:52:25 +00:00
|
|
|
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
FIXME("(%p)->(%d),stub!\n",This,dolock);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2005-08-03 22:46:31 +00:00
|
|
|
static const IClassFactoryVtbl SPCF_Vtbl = {
|
2005-07-31 12:11:56 +00:00
|
|
|
SPCF_QueryInterface,
|
|
|
|
SPCF_AddRef,
|
|
|
|
SPCF_Release,
|
|
|
|
SPCF_CreateInstance,
|
|
|
|
SPCF_LockServer
|
|
|
|
};
|
2012-12-12 13:52:25 +00:00
|
|
|
static IClassFactoryImpl STDPIC_CF = {{&SPCF_Vtbl}, 1 };
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2009-03-03 09:12:43 +00:00
|
|
|
void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }
|