Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenolepicture.c
Go to the documentation of this file.
00001 /* 00002 * OLE Picture object 00003 * 00004 * Implementation of OLE IPicture and related interfaces 00005 * 00006 * Copyright 2000 Huw D M Davies for CodeWeavers. 00007 * Copyright 2001 Marcus Meissner 00008 * Copyright 2008 Kirill K. Smirnov 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00023 * 00024 * BUGS 00025 * 00026 * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well.. 00027 * Lots of methods are just stubs. 00028 * 00029 * 00030 * NOTES (or things that msdn doesn't tell you) 00031 * 00032 * The width and height properties are returned in HIMETRIC units (0.01mm) 00033 * IPicture::Render also uses these to select a region of the src picture. 00034 * A bitmap's size is converted into these units by using the screen resolution 00035 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540). 00036 * 00037 */ 00038 00039 #include "config.h" 00040 #include "wine/port.h" 00041 00042 #ifdef HAVE_UNISTD_H 00043 # include <unistd.h> 00044 #endif 00045 #include <stdarg.h> 00046 #include <stdio.h> 00047 #include <string.h> 00048 00049 #define COBJMACROS 00050 #define NONAMELESSUNION 00051 #define NONAMELESSSTRUCT 00052 00053 #include "winerror.h" 00054 #include "windef.h" 00055 #include "winbase.h" 00056 #include "wingdi.h" 00057 #include "winuser.h" 00058 #include "ole2.h" 00059 #include "olectl.h" 00060 #include "oleauto.h" 00061 #include "connpt.h" 00062 #include "urlmon.h" 00063 #include "wincodec.h" 00064 #include "wine/debug.h" 00065 #include "wine/unicode.h" 00066 #include "wine/library.h" 00067 00068 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00069 00070 #include "pshpack1.h" 00071 00072 /* Header for Aldus Placable Metafiles - a standard metafile follows */ 00073 typedef struct _APM_HEADER 00074 { 00075 DWORD key; 00076 WORD handle; 00077 SHORT left; 00078 SHORT top; 00079 SHORT right; 00080 SHORT bottom; 00081 WORD inch; 00082 DWORD reserved; 00083 WORD checksum; 00084 } APM_HEADER; 00085 00086 typedef struct { 00087 BYTE bWidth; 00088 BYTE bHeight; 00089 BYTE bColorCount; 00090 BYTE bReserved; 00091 WORD xHotspot; 00092 WORD yHotspot; 00093 DWORD dwDIBSize; 00094 DWORD dwDIBOffset; 00095 } CURSORICONFILEDIRENTRY; 00096 00097 typedef struct 00098 { 00099 WORD idReserved; 00100 WORD idType; 00101 WORD idCount; 00102 CURSORICONFILEDIRENTRY idEntries[1]; 00103 } CURSORICONFILEDIR; 00104 00105 #include "poppack.h" 00106 00107 /************************************************************************* 00108 * Declaration of implementation class 00109 */ 00110 00111 typedef struct OLEPictureImpl { 00112 00113 /* 00114 * IPicture handles IUnknown 00115 */ 00116 00117 const IPictureVtbl *lpVtbl; 00118 const IDispatchVtbl *lpvtblIDispatch; 00119 const IPersistStreamVtbl *lpvtblIPersistStream; 00120 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer; 00121 00122 /* Object reference count */ 00123 LONG ref; 00124 00125 /* We own the object and must destroy it ourselves */ 00126 BOOL fOwn; 00127 00128 /* Picture description */ 00129 PICTDESC desc; 00130 00131 /* These are the pixel size of a bitmap */ 00132 DWORD origWidth; 00133 DWORD origHeight; 00134 00135 /* And these are the size of the picture converted into HIMETRIC units */ 00136 OLE_XSIZE_HIMETRIC himetricWidth; 00137 OLE_YSIZE_HIMETRIC himetricHeight; 00138 00139 IConnectionPoint *pCP; 00140 00141 BOOL keepOrigFormat; 00142 HDC hDCCur; 00143 00144 /* Bitmap transparency mask */ 00145 HBITMAP hbmMask; 00146 HBITMAP hbmXor; 00147 COLORREF rgbTrans; 00148 00149 /* data */ 00150 void* data; 00151 int datalen; 00152 BOOL bIsDirty; /* Set to TRUE if picture has changed */ 00153 unsigned int loadtime_magic; /* If a length header was found, saves value */ 00154 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */ 00155 } OLEPictureImpl; 00156 00157 /* 00158 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables. 00159 */ 00160 00161 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface ) 00162 { 00163 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch)); 00164 } 00165 00166 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface ) 00167 { 00168 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream)); 00169 } 00170 00171 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface ) 00172 { 00173 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer)); 00174 } 00175 00176 /* 00177 * Predeclare VTables. They get initialized at the end. 00178 */ 00179 static const IPictureVtbl OLEPictureImpl_VTable; 00180 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable; 00181 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable; 00182 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable; 00183 00184 /*********************************************************************** 00185 * Implementation of the OLEPictureImpl class. 00186 */ 00187 00188 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) { 00189 BITMAP bm; 00190 HDC hdcRef; 00191 00192 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap); 00193 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) { 00194 ERR("GetObject fails\n"); 00195 return; 00196 } 00197 This->origWidth = bm.bmWidth; 00198 This->origHeight = bm.bmHeight; 00199 /* The width and height are stored in HIMETRIC units (0.01 mm), 00200 so we take our pixel width divide by pixels per inch and 00201 multiply by 25.4 * 100 */ 00202 /* Should we use GetBitmapDimension if available? */ 00203 hdcRef = CreateCompatibleDC(0); 00204 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX); 00205 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY); 00206 DeleteDC(hdcRef); 00207 } 00208 00209 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This) 00210 { 00211 ICONINFO infoIcon; 00212 00213 TRACE("icon handle %p\n", This->desc.u.icon.hicon); 00214 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) { 00215 HDC hdcRef; 00216 BITMAP bm; 00217 00218 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor); 00219 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) { 00220 ERR("GetObject fails on icon bitmap\n"); 00221 return; 00222 } 00223 00224 This->origWidth = bm.bmWidth; 00225 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2; 00226 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */ 00227 hdcRef = GetDC(0); 00228 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX); 00229 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY); 00230 ReleaseDC(0, hdcRef); 00231 00232 DeleteObject(infoIcon.hbmMask); 00233 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor); 00234 } else { 00235 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon); 00236 } 00237 } 00238 00239 /************************************************************************ 00240 * OLEPictureImpl_Construct 00241 * 00242 * This method will construct a new instance of the OLEPictureImpl 00243 * class. 00244 * 00245 * The caller of this method must release the object when it's 00246 * done with it. 00247 */ 00248 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn) 00249 { 00250 OLEPictureImpl* newObject = 0; 00251 00252 if (pictDesc) 00253 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType); 00254 00255 /* 00256 * Allocate space for the object. 00257 */ 00258 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl)); 00259 00260 if (newObject==0) 00261 return newObject; 00262 00263 /* 00264 * Initialize the virtual function table. 00265 */ 00266 newObject->lpVtbl = &OLEPictureImpl_VTable; 00267 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable; 00268 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable; 00269 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable; 00270 00271 newObject->pCP = NULL; 00272 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP); 00273 if (!newObject->pCP) 00274 { 00275 HeapFree(GetProcessHeap(), 0, newObject); 00276 return NULL; 00277 } 00278 00279 /* 00280 * Start with one reference count. The caller of this function 00281 * must release the interface pointer when it is done. 00282 */ 00283 newObject->ref = 1; 00284 newObject->hDCCur = 0; 00285 00286 newObject->fOwn = fOwn; 00287 00288 /* dunno about original value */ 00289 newObject->keepOrigFormat = TRUE; 00290 00291 newObject->hbmMask = NULL; 00292 newObject->hbmXor = NULL; 00293 newObject->loadtime_magic = 0xdeadbeef; 00294 newObject->loadtime_format = 0; 00295 newObject->bIsDirty = FALSE; 00296 00297 if (pictDesc) { 00298 newObject->desc = *pictDesc; 00299 00300 switch(pictDesc->picType) { 00301 case PICTYPE_BITMAP: 00302 OLEPictureImpl_SetBitmap(newObject); 00303 break; 00304 00305 case PICTYPE_METAFILE: 00306 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta); 00307 newObject->himetricWidth = pictDesc->u.wmf.xExt; 00308 newObject->himetricHeight = pictDesc->u.wmf.yExt; 00309 break; 00310 00311 case PICTYPE_NONE: 00312 /* not sure what to do here */ 00313 newObject->himetricWidth = newObject->himetricHeight = 0; 00314 break; 00315 00316 case PICTYPE_ICON: 00317 OLEPictureImpl_SetIcon(newObject); 00318 break; 00319 case PICTYPE_ENHMETAFILE: 00320 default: 00321 FIXME("Unsupported type %d\n", pictDesc->picType); 00322 newObject->himetricWidth = newObject->himetricHeight = 0; 00323 break; 00324 } 00325 } else { 00326 newObject->desc.picType = PICTYPE_UNINITIALIZED; 00327 } 00328 00329 TRACE("returning %p\n", newObject); 00330 return newObject; 00331 } 00332 00333 /************************************************************************ 00334 * OLEPictureImpl_Destroy 00335 * 00336 * This method is called by the Release method when the reference 00337 * count goes down to 0. It will free all resources used by 00338 * this object. */ 00339 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj) 00340 { 00341 TRACE("(%p)\n", Obj); 00342 00343 if (Obj->pCP) 00344 IConnectionPoint_Release(Obj->pCP); 00345 00346 if(Obj->fOwn) { /* We need to destroy the picture */ 00347 switch(Obj->desc.picType) { 00348 case PICTYPE_BITMAP: 00349 DeleteObject(Obj->desc.u.bmp.hbitmap); 00350 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask); 00351 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor); 00352 break; 00353 case PICTYPE_METAFILE: 00354 DeleteMetaFile(Obj->desc.u.wmf.hmeta); 00355 break; 00356 case PICTYPE_ICON: 00357 DestroyIcon(Obj->desc.u.icon.hicon); 00358 break; 00359 case PICTYPE_ENHMETAFILE: 00360 DeleteEnhMetaFile(Obj->desc.u.emf.hemf); 00361 break; 00362 case PICTYPE_NONE: 00363 case PICTYPE_UNINITIALIZED: 00364 /* Nothing to do */ 00365 break; 00366 default: 00367 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType); 00368 break; 00369 } 00370 } 00371 HeapFree(GetProcessHeap(), 0, Obj->data); 00372 HeapFree(GetProcessHeap(), 0, Obj); 00373 } 00374 00375 00376 /************************************************************************ 00377 * OLEPictureImpl_AddRef (IUnknown) 00378 * 00379 * See Windows documentation for more details on IUnknown methods. 00380 */ 00381 static ULONG WINAPI OLEPictureImpl_AddRef( 00382 IPicture* iface) 00383 { 00384 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00385 ULONG refCount = InterlockedIncrement(&This->ref); 00386 00387 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1); 00388 00389 return refCount; 00390 } 00391 00392 /************************************************************************ 00393 * OLEPictureImpl_Release (IUnknown) 00394 * 00395 * See Windows documentation for more details on IUnknown methods. 00396 */ 00397 static ULONG WINAPI OLEPictureImpl_Release( 00398 IPicture* iface) 00399 { 00400 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00401 ULONG refCount = InterlockedDecrement(&This->ref); 00402 00403 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1); 00404 00405 /* 00406 * If the reference count goes down to 0, perform suicide. 00407 */ 00408 if (!refCount) OLEPictureImpl_Destroy(This); 00409 00410 return refCount; 00411 } 00412 00413 /************************************************************************ 00414 * OLEPictureImpl_QueryInterface (IUnknown) 00415 * 00416 * See Windows documentation for more details on IUnknown methods. 00417 */ 00418 static HRESULT WINAPI OLEPictureImpl_QueryInterface( 00419 IPicture* iface, 00420 REFIID riid, 00421 void** ppvObject) 00422 { 00423 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00424 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject); 00425 00426 /* 00427 * Perform a sanity check on the parameters. 00428 */ 00429 if ( (This==0) || (ppvObject==0) ) 00430 return E_INVALIDARG; 00431 00432 /* 00433 * Initialize the return parameter. 00434 */ 00435 *ppvObject = 0; 00436 00437 /* 00438 * Compare the riid with the interface IDs implemented by this object. 00439 */ 00440 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid)) 00441 *ppvObject = This; 00442 else if (IsEqualIID(&IID_IDispatch, riid)) 00443 *ppvObject = &This->lpvtblIDispatch; 00444 else if (IsEqualIID(&IID_IPictureDisp, riid)) 00445 *ppvObject = &This->lpvtblIDispatch; 00446 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid)) 00447 *ppvObject = &This->lpvtblIPersistStream; 00448 else if (IsEqualIID(&IID_IConnectionPointContainer, riid)) 00449 *ppvObject = &This->lpvtblIConnectionPointContainer; 00450 00451 /* 00452 * Check that we obtained an interface. 00453 */ 00454 if ((*ppvObject)==0) 00455 { 00456 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid)); 00457 return E_NOINTERFACE; 00458 } 00459 00460 /* 00461 * Query Interface always increases the reference count by one when it is 00462 * successful 00463 */ 00464 OLEPictureImpl_AddRef((IPicture*)This); 00465 00466 return S_OK; 00467 } 00468 00469 /*********************************************************************** 00470 * OLEPicture_SendNotify (internal) 00471 * 00472 * Sends notification messages of changed properties to any interested 00473 * connections. 00474 */ 00475 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID) 00476 { 00477 IEnumConnections *pEnum; 00478 CONNECTDATA CD; 00479 00480 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum)) 00481 return; 00482 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) { 00483 IPropertyNotifySink *sink; 00484 00485 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink); 00486 IPropertyNotifySink_OnChanged(sink, dispID); 00487 IPropertyNotifySink_Release(sink); 00488 IUnknown_Release(CD.pUnk); 00489 } 00490 IEnumConnections_Release(pEnum); 00491 } 00492 00493 /************************************************************************ 00494 * OLEPictureImpl_get_Handle 00495 */ 00496 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface, 00497 OLE_HANDLE *phandle) 00498 { 00499 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00500 TRACE("(%p)->(%p)\n", This, phandle); 00501 00502 if(!phandle) 00503 return E_POINTER; 00504 00505 switch(This->desc.picType) { 00506 case PICTYPE_NONE: 00507 case PICTYPE_UNINITIALIZED: 00508 *phandle = 0; 00509 break; 00510 case PICTYPE_BITMAP: 00511 *phandle = HandleToUlong(This->desc.u.bmp.hbitmap); 00512 break; 00513 case PICTYPE_METAFILE: 00514 *phandle = HandleToUlong(This->desc.u.wmf.hmeta); 00515 break; 00516 case PICTYPE_ICON: 00517 *phandle = HandleToUlong(This->desc.u.icon.hicon); 00518 break; 00519 case PICTYPE_ENHMETAFILE: 00520 *phandle = HandleToUlong(This->desc.u.emf.hemf); 00521 break; 00522 default: 00523 FIXME("Unimplemented type %d\n", This->desc.picType); 00524 return E_NOTIMPL; 00525 } 00526 TRACE("returning handle %08x\n", *phandle); 00527 return S_OK; 00528 } 00529 00530 /************************************************************************ 00531 * OLEPictureImpl_get_hPal 00532 */ 00533 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface, 00534 OLE_HANDLE *phandle) 00535 { 00536 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00537 HRESULT hres; 00538 TRACE("(%p)->(%p)\n", This, phandle); 00539 00540 if (!phandle) 00541 return E_POINTER; 00542 00543 switch (This->desc.picType) { 00544 case (UINT)PICTYPE_UNINITIALIZED: 00545 case PICTYPE_NONE: 00546 *phandle = 0; 00547 hres = S_FALSE; 00548 break; 00549 case PICTYPE_BITMAP: 00550 *phandle = HandleToUlong(This->desc.u.bmp.hpal); 00551 hres = S_OK; 00552 break; 00553 case PICTYPE_METAFILE: 00554 hres = E_FAIL; 00555 break; 00556 case PICTYPE_ICON: 00557 case PICTYPE_ENHMETAFILE: 00558 default: 00559 FIXME("unimplemented for type %d. Returning 0 palette.\n", 00560 This->desc.picType); 00561 *phandle = 0; 00562 hres = S_OK; 00563 } 00564 00565 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle); 00566 return hres; 00567 } 00568 00569 /************************************************************************ 00570 * OLEPictureImpl_get_Type 00571 */ 00572 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface, 00573 short *ptype) 00574 { 00575 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00576 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType); 00577 00578 if(!ptype) 00579 return E_POINTER; 00580 00581 *ptype = This->desc.picType; 00582 return S_OK; 00583 } 00584 00585 /************************************************************************ 00586 * OLEPictureImpl_get_Width 00587 */ 00588 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface, 00589 OLE_XSIZE_HIMETRIC *pwidth) 00590 { 00591 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00592 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth); 00593 *pwidth = This->himetricWidth; 00594 return S_OK; 00595 } 00596 00597 /************************************************************************ 00598 * OLEPictureImpl_get_Height 00599 */ 00600 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface, 00601 OLE_YSIZE_HIMETRIC *pheight) 00602 { 00603 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00604 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight); 00605 *pheight = This->himetricHeight; 00606 return S_OK; 00607 } 00608 00609 /************************************************************************ 00610 * OLEPictureImpl_Render 00611 */ 00612 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc, 00613 LONG x, LONG y, LONG cx, LONG cy, 00614 OLE_XPOS_HIMETRIC xSrc, 00615 OLE_YPOS_HIMETRIC ySrc, 00616 OLE_XSIZE_HIMETRIC cxSrc, 00617 OLE_YSIZE_HIMETRIC cySrc, 00618 LPCRECT prcWBounds) 00619 { 00620 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00621 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n", 00622 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds); 00623 if(prcWBounds) 00624 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top, 00625 prcWBounds->right, prcWBounds->bottom); 00626 00627 if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){ 00628 return CTL_E_INVALIDPROPERTYVALUE; 00629 } 00630 00631 /* 00632 * While the documentation suggests this to be here (or after rendering?) 00633 * it does cause an endless recursion in my sample app. -MM 20010804 00634 OLEPicture_SendNotify(This,DISPID_PICT_RENDER); 00635 */ 00636 00637 switch(This->desc.picType) { 00638 case PICTYPE_UNINITIALIZED: 00639 case PICTYPE_NONE: 00640 /* nothing to do */ 00641 return S_OK; 00642 case PICTYPE_BITMAP: 00643 { 00644 HBITMAP hbmpOld; 00645 HDC hdcBmp; 00646 00647 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units. 00648 NB y-axis gets flipped */ 00649 00650 hdcBmp = CreateCompatibleDC(0); 00651 SetMapMode(hdcBmp, MM_ANISOTROPIC); 00652 SetWindowOrgEx(hdcBmp, 0, 0, NULL); 00653 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL); 00654 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL); 00655 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL); 00656 00657 if (This->hbmMask) { 00658 HDC hdcMask = CreateCompatibleDC(0); 00659 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask); 00660 00661 hbmpOld = SelectObject(hdcBmp, This->hbmXor); 00662 00663 SetMapMode(hdcMask, MM_ANISOTROPIC); 00664 SetWindowOrgEx(hdcMask, 0, 0, NULL); 00665 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL); 00666 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL); 00667 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL); 00668 00669 SetBkColor(hdc, RGB(255, 255, 255)); 00670 SetTextColor(hdc, RGB(0, 0, 0)); 00671 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND); 00672 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT); 00673 00674 SelectObject(hdcMask, hOldbm); 00675 DeleteDC(hdcMask); 00676 } else { 00677 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap); 00678 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY); 00679 } 00680 00681 SelectObject(hdcBmp, hbmpOld); 00682 DeleteDC(hdcBmp); 00683 } 00684 break; 00685 case PICTYPE_ICON: 00686 FIXME("Not quite correct implementation of rendering icons...\n"); 00687 DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL); 00688 break; 00689 00690 case PICTYPE_METAFILE: 00691 { 00692 POINT prevOrg, prevWndOrg; 00693 SIZE prevExt, prevWndExt; 00694 int oldmode; 00695 00696 /* Render the WMF to the appropriate location by setting the 00697 appropriate ratio between "device units" and "logical units" */ 00698 oldmode = SetMapMode(hdc, MM_ANISOTROPIC); 00699 /* For the "source rectangle" the y-axis must be inverted */ 00700 SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg); 00701 SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt); 00702 /* For the "destination rectangle" no inversion is necessary */ 00703 SetViewportOrgEx(hdc, x, y, &prevOrg); 00704 SetViewportExtEx(hdc, cx, cy, &prevExt); 00705 00706 if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta)) 00707 ERR("PlayMetaFile failed!\n"); 00708 00709 /* We're done, restore the DC to the previous settings for converting 00710 logical units to device units */ 00711 SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL); 00712 SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL); 00713 SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL); 00714 SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL); 00715 SetMapMode(hdc, oldmode); 00716 break; 00717 } 00718 00719 case PICTYPE_ENHMETAFILE: 00720 { 00721 RECT rc = { x, y, x + cx, y + cy }; 00722 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc); 00723 break; 00724 } 00725 00726 default: 00727 FIXME("type %d not implemented\n", This->desc.picType); 00728 return E_NOTIMPL; 00729 } 00730 return S_OK; 00731 } 00732 00733 /************************************************************************ 00734 * OLEPictureImpl_set_hPal 00735 */ 00736 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface, 00737 OLE_HANDLE hpal) 00738 { 00739 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00740 FIXME("(%p)->(%08x): stub\n", This, hpal); 00741 OLEPicture_SendNotify(This,DISPID_PICT_HPAL); 00742 return E_NOTIMPL; 00743 } 00744 00745 /************************************************************************ 00746 * OLEPictureImpl_get_CurDC 00747 */ 00748 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface, 00749 HDC *phdc) 00750 { 00751 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00752 TRACE("(%p), returning %p\n", This, This->hDCCur); 00753 if (phdc) *phdc = This->hDCCur; 00754 return S_OK; 00755 } 00756 00757 /************************************************************************ 00758 * OLEPictureImpl_SelectPicture 00759 */ 00760 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface, 00761 HDC hdcIn, 00762 HDC *phdcOut, 00763 OLE_HANDLE *phbmpOut) 00764 { 00765 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00766 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut); 00767 if (This->desc.picType == PICTYPE_BITMAP) { 00768 SelectObject(hdcIn,This->desc.u.bmp.hbitmap); 00769 00770 if (phdcOut) 00771 *phdcOut = This->hDCCur; 00772 This->hDCCur = hdcIn; 00773 if (phbmpOut) 00774 *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap); 00775 return S_OK; 00776 } else { 00777 FIXME("Don't know how to select picture type %d\n",This->desc.picType); 00778 return E_FAIL; 00779 } 00780 } 00781 00782 /************************************************************************ 00783 * OLEPictureImpl_get_KeepOriginalFormat 00784 */ 00785 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface, 00786 BOOL *pfKeep) 00787 { 00788 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00789 TRACE("(%p)->(%p)\n", This, pfKeep); 00790 if (!pfKeep) 00791 return E_POINTER; 00792 *pfKeep = This->keepOrigFormat; 00793 return S_OK; 00794 } 00795 00796 /************************************************************************ 00797 * OLEPictureImpl_put_KeepOriginalFormat 00798 */ 00799 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface, 00800 BOOL keep) 00801 { 00802 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00803 TRACE("(%p)->(%d)\n", This, keep); 00804 This->keepOrigFormat = keep; 00805 /* FIXME: what DISPID notification here? */ 00806 return S_OK; 00807 } 00808 00809 /************************************************************************ 00810 * OLEPictureImpl_PictureChanged 00811 */ 00812 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface) 00813 { 00814 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00815 TRACE("(%p)->()\n", This); 00816 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE); 00817 This->bIsDirty = TRUE; 00818 return S_OK; 00819 } 00820 00821 /************************************************************************ 00822 * OLEPictureImpl_SaveAsFile 00823 */ 00824 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface, 00825 IStream *pstream, 00826 BOOL SaveMemCopy, 00827 LONG *pcbSize) 00828 { 00829 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00830 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize); 00831 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize); 00832 } 00833 00834 /************************************************************************ 00835 * OLEPictureImpl_get_Attributes 00836 */ 00837 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface, 00838 DWORD *pdwAttr) 00839 { 00840 OLEPictureImpl *This = (OLEPictureImpl *)iface; 00841 TRACE("(%p)->(%p).\n", This, pdwAttr); 00842 00843 if(!pdwAttr) 00844 return E_POINTER; 00845 00846 *pdwAttr = 0; 00847 switch (This->desc.picType) { 00848 case PICTYPE_UNINITIALIZED: 00849 case PICTYPE_NONE: break; 00850 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */ 00851 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break; 00852 case PICTYPE_ENHMETAFILE: /* fall through */ 00853 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break; 00854 default:FIXME("Unknown pictype %d\n",This->desc.picType);break; 00855 } 00856 return S_OK; 00857 } 00858 00859 00860 /************************************************************************ 00861 * IConnectionPointContainer 00862 */ 00863 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface( 00864 IConnectionPointContainer* iface, 00865 REFIID riid, 00866 VOID** ppvoid) 00867 { 00868 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 00869 00870 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid); 00871 } 00872 00873 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef( 00874 IConnectionPointContainer* iface) 00875 { 00876 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 00877 00878 return IPicture_AddRef((IPicture *)This); 00879 } 00880 00881 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release( 00882 IConnectionPointContainer* iface) 00883 { 00884 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 00885 00886 return IPicture_Release((IPicture *)This); 00887 } 00888 00889 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints( 00890 IConnectionPointContainer* iface, 00891 IEnumConnectionPoints** ppEnum) 00892 { 00893 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 00894 00895 FIXME("(%p,%p), stub!\n",This,ppEnum); 00896 return E_NOTIMPL; 00897 } 00898 00899 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint( 00900 IConnectionPointContainer* iface, 00901 REFIID riid, 00902 IConnectionPoint **ppCP) 00903 { 00904 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 00905 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP); 00906 if (!ppCP) 00907 return E_POINTER; 00908 *ppCP = NULL; 00909 if (IsEqualGUID(riid,&IID_IPropertyNotifySink)) 00910 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP); 00911 FIXME("no connection point for %s\n",debugstr_guid(riid)); 00912 return CONNECT_E_NOCONNECTION; 00913 } 00914 00915 00916 /************************************************************************ 00917 * IPersistStream 00918 */ 00919 00920 /************************************************************************ 00921 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown) 00922 * 00923 * See Windows documentation for more details on IUnknown methods. 00924 */ 00925 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface( 00926 IPersistStream* iface, 00927 REFIID riid, 00928 VOID** ppvoid) 00929 { 00930 OLEPictureImpl *This = impl_from_IPersistStream(iface); 00931 00932 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid); 00933 } 00934 00935 /************************************************************************ 00936 * OLEPictureImpl_IPersistStream_AddRef (IUnknown) 00937 * 00938 * See Windows documentation for more details on IUnknown methods. 00939 */ 00940 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef( 00941 IPersistStream* iface) 00942 { 00943 OLEPictureImpl *This = impl_from_IPersistStream(iface); 00944 00945 return IPicture_AddRef((IPicture *)This); 00946 } 00947 00948 /************************************************************************ 00949 * OLEPictureImpl_IPersistStream_Release (IUnknown) 00950 * 00951 * See Windows documentation for more details on IUnknown methods. 00952 */ 00953 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release( 00954 IPersistStream* iface) 00955 { 00956 OLEPictureImpl *This = impl_from_IPersistStream(iface); 00957 00958 return IPicture_Release((IPicture *)This); 00959 } 00960 00961 /************************************************************************ 00962 * OLEPictureImpl_IPersistStream_GetClassID 00963 */ 00964 static HRESULT WINAPI OLEPictureImpl_GetClassID( 00965 IPersistStream* iface,CLSID* pClassID) 00966 { 00967 TRACE("(%p)\n", pClassID); 00968 *pClassID = CLSID_StdPicture; 00969 return S_OK; 00970 } 00971 00972 /************************************************************************ 00973 * OLEPictureImpl_IPersistStream_IsDirty 00974 */ 00975 static HRESULT WINAPI OLEPictureImpl_IsDirty( 00976 IPersistStream* iface) 00977 { 00978 OLEPictureImpl *This = impl_from_IPersistStream(iface); 00979 FIXME("(%p),stub!\n",This); 00980 return E_NOTIMPL; 00981 } 00982 00983 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) 00984 { 00985 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf; 00986 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1); 00987 HDC hdcref; 00988 00989 /* Does not matter whether this is a coreheader or not, we only use 00990 * components which are in both 00991 */ 00992 hdcref = GetDC(0); 00993 This->desc.u.bmp.hbitmap = CreateDIBitmap( 00994 hdcref, 00995 &(bi->bmiHeader), 00996 CBM_INIT, 00997 xbuf+bfh->bfOffBits, 00998 bi, 00999 DIB_RGB_COLORS 01000 ); 01001 ReleaseDC(0, hdcref); 01002 if (This->desc.u.bmp.hbitmap == 0) 01003 return E_FAIL; 01004 This->desc.picType = PICTYPE_BITMAP; 01005 OLEPictureImpl_SetBitmap(This); 01006 return S_OK; 01007 } 01008 01009 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src) 01010 { 01011 HRESULT hr; 01012 BITMAPINFOHEADER bih; 01013 HDC hdcref; 01014 UINT width, height; 01015 UINT stride, buffersize; 01016 LPBYTE bits=NULL; 01017 WICRect rc; 01018 IWICBitmapSource *real_source; 01019 UINT x, y; 01020 COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0); 01021 BOOL has_alpha=FALSE; 01022 01023 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source); 01024 if (FAILED(hr)) return hr; 01025 01026 hr = IWICBitmapSource_GetSize(real_source, &width, &height); 01027 if (FAILED(hr)) goto end; 01028 01029 bih.biSize = sizeof(bih); 01030 bih.biWidth = width; 01031 bih.biHeight = -height; 01032 bih.biPlanes = 1; 01033 bih.biBitCount = 32; 01034 bih.biCompression = BI_RGB; 01035 bih.biSizeImage = 0; 01036 bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */ 01037 bih.biYPelsPerMeter = 4085; 01038 bih.biClrUsed = 0; 01039 bih.biClrImportant = 0; 01040 01041 stride = 4 * width; 01042 buffersize = stride * height; 01043 01044 bits = HeapAlloc(GetProcessHeap(), 0, buffersize); 01045 if (!bits) 01046 { 01047 hr = E_OUTOFMEMORY; 01048 goto end; 01049 } 01050 01051 rc.X = 0; 01052 rc.Y = 0; 01053 rc.Width = width; 01054 rc.Height = height; 01055 hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits); 01056 if (FAILED(hr)) 01057 goto end; 01058 01059 hdcref = GetDC(0); 01060 This->desc.u.bmp.hbitmap = CreateDIBitmap( 01061 hdcref, 01062 &bih, 01063 CBM_INIT, 01064 bits, 01065 (BITMAPINFO*)&bih, 01066 DIB_RGB_COLORS); 01067 01068 if (This->desc.u.bmp.hbitmap == 0) 01069 { 01070 hr = E_FAIL; 01071 ReleaseDC(0, hdcref); 01072 goto end; 01073 } 01074 01075 This->desc.picType = PICTYPE_BITMAP; 01076 OLEPictureImpl_SetBitmap(This); 01077 01078 /* set transparent pixels to black, all others to white */ 01079 for(y = 0; y < height; y++){ 01080 for(x = 0; x < width; x++){ 01081 DWORD *pixel = (DWORD*)(bits + stride*y + 4*x); 01082 if((*pixel & 0x80000000) == 0) 01083 { 01084 has_alpha = TRUE; 01085 *pixel = black; 01086 } 01087 else 01088 *pixel = white; 01089 } 01090 } 01091 01092 if (has_alpha) 01093 { 01094 HDC hdcBmp, hdcXor, hdcMask; 01095 HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask; 01096 01097 This->hbmXor = CreateDIBitmap( 01098 hdcref, 01099 &bih, 01100 CBM_INIT, 01101 bits, 01102 (BITMAPINFO*)&bih, 01103 DIB_RGB_COLORS 01104 ); 01105 01106 This->hbmMask = CreateBitmap(width,-height,1,1,NULL); 01107 hdcBmp = CreateCompatibleDC(NULL); 01108 hdcXor = CreateCompatibleDC(NULL); 01109 hdcMask = CreateCompatibleDC(NULL); 01110 01111 hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap); 01112 hbmoldXor = SelectObject(hdcXor,This->hbmXor); 01113 hbmoldMask = SelectObject(hdcMask,This->hbmMask); 01114 01115 SetBkColor(hdcXor,black); 01116 BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY); 01117 BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND); 01118 01119 SelectObject(hdcBmp,hbmoldBmp); 01120 SelectObject(hdcXor,hbmoldXor); 01121 SelectObject(hdcMask,hbmoldMask); 01122 01123 DeleteDC(hdcBmp); 01124 DeleteDC(hdcXor); 01125 DeleteDC(hdcMask); 01126 } 01127 01128 ReleaseDC(0, hdcref); 01129 01130 end: 01131 HeapFree(GetProcessHeap(), 0, bits); 01132 IWICBitmapSource_Release(real_source); 01133 return hr; 01134 } 01135 01136 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread) 01137 { 01138 HRESULT hr; 01139 IWICImagingFactory *factory; 01140 IWICBitmapDecoder *decoder; 01141 IWICBitmapFrameDecode *framedecode; 01142 HRESULT initresult; 01143 IWICStream *stream; 01144 01145 initresult = CoInitialize(NULL); 01146 01147 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, 01148 &IID_IWICImagingFactory, (void**)&factory); 01149 if (SUCCEEDED(hr)) /* created factory */ 01150 { 01151 hr = IWICImagingFactory_CreateStream(factory, &stream); 01152 IWICImagingFactory_Release(factory); 01153 } 01154 01155 if (SUCCEEDED(hr)) /* created stream */ 01156 { 01157 hr = IWICStream_InitializeFromMemory(stream, xbuf, xread); 01158 01159 if (SUCCEEDED(hr)) /* initialized stream */ 01160 { 01161 hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER, 01162 &IID_IWICBitmapDecoder, (void**)&decoder); 01163 if (SUCCEEDED(hr)) /* created decoder */ 01164 { 01165 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad); 01166 01167 if (SUCCEEDED(hr)) /* initialized decoder */ 01168 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode); 01169 01170 IWICBitmapDecoder_Release(decoder); 01171 } 01172 } 01173 01174 IWICStream_Release(stream); 01175 } 01176 01177 if (SUCCEEDED(hr)) /* got framedecode */ 01178 { 01179 hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode); 01180 IWICBitmapFrameDecode_Release(framedecode); 01181 } 01182 01183 if (SUCCEEDED(initresult)) CoUninitialize(); 01184 return hr; 01185 } 01186 01187 /***************************************************** 01188 * start of Icon-specific code 01189 */ 01190 01191 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) 01192 { 01193 HICON hicon; 01194 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf; 01195 HDC hdcRef; 01196 int i; 01197 01198 /* 01199 FIXME("icon.idReserved=%d\n",cifd->idReserved); 01200 FIXME("icon.idType=%d\n",cifd->idType); 01201 FIXME("icon.idCount=%d\n",cifd->idCount); 01202 01203 for (i=0;i<cifd->idCount;i++) { 01204 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth); 01205 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight); 01206 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount); 01207 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved); 01208 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot); 01209 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot); 01210 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize); 01211 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset); 01212 } 01213 */ 01214 i=0; 01215 /* If we have more than one icon, try to find the best. 01216 * this currently means '32 pixel wide'. 01217 */ 01218 if (cifd->idCount!=1) { 01219 for (i=0;i<cifd->idCount;i++) { 01220 if (cifd->idEntries[i].bWidth == 32) 01221 break; 01222 } 01223 if (i==cifd->idCount) i=0; 01224 } 01225 01226 hicon = CreateIconFromResourceEx( 01227 xbuf+cifd->idEntries[i].dwDIBOffset, 01228 cifd->idEntries[i].dwDIBSize, 01229 TRUE, /* is icon */ 01230 0x00030000, 01231 cifd->idEntries[i].bWidth, 01232 cifd->idEntries[i].bHeight, 01233 0 01234 ); 01235 if (!hicon) { 01236 ERR("CreateIcon failed.\n"); 01237 return E_FAIL; 01238 } else { 01239 This->desc.picType = PICTYPE_ICON; 01240 This->desc.u.icon.hicon = hicon; 01241 This->origWidth = cifd->idEntries[i].bWidth; 01242 This->origHeight = cifd->idEntries[i].bHeight; 01243 hdcRef = CreateCompatibleDC(0); 01244 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX); 01245 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY); 01246 DeleteDC(hdcRef); 01247 return S_OK; 01248 } 01249 } 01250 01251 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This, 01252 const BYTE *data, ULONG size) 01253 { 01254 HENHMETAFILE hemf; 01255 ENHMETAHEADER hdr; 01256 01257 hemf = SetEnhMetaFileBits(size, data); 01258 if (!hemf) return E_FAIL; 01259 01260 GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr); 01261 01262 This->desc.picType = PICTYPE_ENHMETAFILE; 01263 This->desc.u.emf.hemf = hemf; 01264 01265 This->origWidth = 0; 01266 This->origHeight = 0; 01267 This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left; 01268 This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top; 01269 01270 return S_OK; 01271 } 01272 01273 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This, 01274 const BYTE *data, ULONG size) 01275 { 01276 const APM_HEADER *header = (const APM_HEADER *)data; 01277 HMETAFILE hmf; 01278 01279 if (size < sizeof(APM_HEADER)) 01280 return E_FAIL; 01281 if (header->key != 0x9ac6cdd7) 01282 return E_FAIL; 01283 01284 /* SetMetaFileBitsEx performs data check on its own */ 01285 hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header)); 01286 if (!hmf) return E_FAIL; 01287 01288 This->desc.picType = PICTYPE_METAFILE; 01289 This->desc.u.wmf.hmeta = hmf; 01290 This->desc.u.wmf.xExt = 0; 01291 This->desc.u.wmf.yExt = 0; 01292 01293 This->origWidth = 0; 01294 This->origHeight = 0; 01295 This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch); 01296 This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch); 01297 return S_OK; 01298 } 01299 01300 /************************************************************************ 01301 * BITMAP FORMAT FLAGS - 01302 * Flags that differentiate between different types of bitmaps. 01303 */ 01304 01305 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */ 01306 #define BITMAP_FORMAT_JPEG 0xd8ff 01307 #define BITMAP_FORMAT_GIF 0x4947 01308 #define BITMAP_FORMAT_PNG 0x5089 01309 #define BITMAP_FORMAT_APM 0xcdd7 01310 01311 /************************************************************************ 01312 * OLEPictureImpl_IPersistStream_Load (IUnknown) 01313 * 01314 * Loads the binary data from the IStream. Starts at current position. 01315 * There appears to be an 2 DWORD header: 01316 * DWORD magic; 01317 * DWORD len; 01318 * 01319 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF 01320 */ 01321 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { 01322 HRESULT hr = E_FAIL; 01323 BOOL headerisdata = FALSE; 01324 BOOL statfailed = FALSE; 01325 ULONG xread, toread; 01326 ULONG headerread; 01327 BYTE *xbuf; 01328 DWORD header[2]; 01329 WORD magic; 01330 STATSTG statstg; 01331 OLEPictureImpl *This = impl_from_IPersistStream(iface); 01332 01333 TRACE("(%p,%p)\n",This,pStm); 01334 01335 /**************************************************************************************** 01336 * Part 1: Load the data 01337 */ 01338 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find 01339 * out whether we do. 01340 * 01341 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a 01342 * compound file. This may explain most, if not all, of the cases of "no 01343 * header", and the header validation should take this into account. 01344 * At least in Visual Basic 6, resource streams, valid headers are 01345 * header[0] == "lt\0\0", 01346 * header[1] == length_of_stream. 01347 * 01348 * Also handle streams where we do not have a working "Stat" method by 01349 * reading all data until the end of the stream. 01350 */ 01351 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME); 01352 if (hr) { 01353 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr); 01354 statfailed = TRUE; 01355 /* we will read at least 8 byte ... just right below */ 01356 statstg.cbSize.QuadPart = 8; 01357 } 01358 01359 toread = 0; 01360 headerread = 0; 01361 headerisdata = FALSE; 01362 do { 01363 hr=IStream_Read(pStm,header,8,&xread); 01364 if (hr || xread!=8) { 01365 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread); 01366 return (hr?hr:E_FAIL); 01367 } 01368 headerread += xread; 01369 xread = 0; 01370 01371 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) { 01372 if (toread != 0 && toread != header[1]) 01373 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n", 01374 toread, header[1]); 01375 toread = header[1]; 01376 if (toread == 0) break; 01377 } else { 01378 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */ 01379 !memcmp(&(header[0]), "BM", 2) || /* BMP header */ 01380 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */ 01381 (header[0] == EMR_HEADER) || /* EMF header */ 01382 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */ 01383 (header[1]==0) 01384 ) {/* Found start of bitmap data */ 01385 headerisdata = TRUE; 01386 if (toread == 0) 01387 toread = statstg.cbSize.QuadPart-8; 01388 else toread -= 8; 01389 xread = 8; 01390 } else { 01391 FIXME("Unknown stream header magic: %08x\n", header[0]); 01392 toread = header[1]; 01393 } 01394 } 01395 } while (!headerisdata); 01396 01397 if (statfailed) { /* we don't know the size ... read all we get */ 01398 int sizeinc = 4096; 01399 int origsize = sizeinc; 01400 ULONG nread = 42; 01401 01402 TRACE("Reading all data from stream.\n"); 01403 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize); 01404 if (headerisdata) 01405 memcpy (xbuf, header, 8); 01406 while (1) { 01407 while (xread < origsize) { 01408 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread); 01409 xread+=nread; 01410 if (hr || !nread) 01411 break; 01412 } 01413 if (!nread || hr) /* done, or error */ 01414 break; 01415 if (xread == origsize) { 01416 origsize += sizeinc; 01417 sizeinc = 2*sizeinc; /* exponential increase */ 01418 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize); 01419 } 01420 } 01421 if (hr) 01422 TRACE("hr in no-stat loader case is %08x\n", hr); 01423 TRACE("loaded %d bytes.\n", xread); 01424 This->datalen = xread; 01425 This->data = xbuf; 01426 } else { 01427 This->datalen = toread+(headerisdata?8:0); 01428 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen); 01429 if (!xbuf) 01430 return E_OUTOFMEMORY; 01431 01432 if (headerisdata) 01433 memcpy (xbuf, header, 8); 01434 01435 while (xread < This->datalen) { 01436 ULONG nread; 01437 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread); 01438 xread+=nread; 01439 if (hr || !nread) 01440 break; 01441 } 01442 if (xread != This->datalen) 01443 ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen); 01444 } 01445 if (This->datalen == 0) { /* Marks the "NONE" picture */ 01446 This->desc.picType = PICTYPE_NONE; 01447 return S_OK; 01448 } 01449 01450 01451 /**************************************************************************************** 01452 * Part 2: Process the loaded data 01453 */ 01454 01455 magic = xbuf[0] + (xbuf[1]<<8); 01456 This->loadtime_format = magic; 01457 01458 switch (magic) { 01459 case BITMAP_FORMAT_GIF: /* GIF */ 01460 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread); 01461 break; 01462 case BITMAP_FORMAT_JPEG: /* JPEG */ 01463 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread); 01464 break; 01465 case BITMAP_FORMAT_BMP: /* Bitmap */ 01466 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread); 01467 break; 01468 case BITMAP_FORMAT_PNG: /* PNG */ 01469 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread); 01470 break; 01471 case BITMAP_FORMAT_APM: /* APM */ 01472 hr = OLEPictureImpl_LoadAPM(This, xbuf, xread); 01473 break; 01474 case 0x0000: { /* ICON , first word is dwReserved */ 01475 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread); 01476 break; 01477 } 01478 default: 01479 { 01480 unsigned int i; 01481 01482 /* let's see if it's a EMF */ 01483 hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread); 01484 if (hr == S_OK) break; 01485 01486 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread); 01487 hr=E_FAIL; 01488 for (i=0;i<xread+8;i++) { 01489 if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]); 01490 else MESSAGE("%02x ",xbuf[i-8]); 01491 if (i % 10 == 9) MESSAGE("\n"); 01492 } 01493 MESSAGE("\n"); 01494 break; 01495 } 01496 } 01497 This->bIsDirty = FALSE; 01498 01499 /* FIXME: this notify is not really documented */ 01500 if (hr==S_OK) 01501 OLEPicture_SendNotify(This,DISPID_PICT_TYPE); 01502 return hr; 01503 } 01504 01505 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength) 01506 { 01507 int iSuccess = 0; 01508 HDC hDC; 01509 BITMAPINFO * pInfoBitmap; 01510 int iNumPaletteEntries; 01511 unsigned char * pPixelData; 01512 BITMAPFILEHEADER * pFileHeader; 01513 BITMAPINFO * pInfoHeader; 01514 01515 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 01516 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 01517 01518 /* Find out bitmap size and padded length */ 01519 hDC = GetDC(0); 01520 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); 01521 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); 01522 01523 /* Fetch bitmap palette & pixel data */ 01524 01525 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage); 01526 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS); 01527 01528 /* Calculate the total length required for the BMP data */ 01529 if (pInfoBitmap->bmiHeader.biClrUsed != 0) { 01530 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed; 01531 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256; 01532 } else { 01533 if (pInfoBitmap->bmiHeader.biBitCount <= 8) 01534 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount; 01535 else 01536 iNumPaletteEntries = 0; 01537 } 01538 *pLength = 01539 sizeof(BITMAPFILEHEADER) + 01540 sizeof(BITMAPINFOHEADER) + 01541 iNumPaletteEntries * sizeof(RGBQUAD) + 01542 pInfoBitmap->bmiHeader.biSizeImage; 01543 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength); 01544 01545 /* Fill the BITMAPFILEHEADER */ 01546 pFileHeader = *ppBuffer; 01547 pFileHeader->bfType = BITMAP_FORMAT_BMP; 01548 pFileHeader->bfSize = *pLength; 01549 pFileHeader->bfOffBits = 01550 sizeof(BITMAPFILEHEADER) + 01551 sizeof(BITMAPINFOHEADER) + 01552 iNumPaletteEntries * sizeof(RGBQUAD); 01553 01554 /* Fill the BITMAPINFOHEADER and the palette data */ 01555 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER)); 01556 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD)); 01557 memcpy( 01558 (unsigned char *)(*ppBuffer) + 01559 sizeof(BITMAPFILEHEADER) + 01560 sizeof(BITMAPINFOHEADER) + 01561 iNumPaletteEntries * sizeof(RGBQUAD), 01562 pPixelData, pInfoBitmap->bmiHeader.biSizeImage); 01563 iSuccess = 1; 01564 01565 HeapFree(GetProcessHeap(), 0, pPixelData); 01566 HeapFree(GetProcessHeap(), 0, pInfoBitmap); 01567 return iSuccess; 01568 } 01569 01570 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) 01571 { 01572 ICONINFO infoIcon; 01573 int iSuccess = 0; 01574 01575 *ppBuffer = NULL; *pLength = 0; 01576 if (GetIconInfo(hIcon, &infoIcon)) { 01577 HDC hDC; 01578 BITMAPINFO * pInfoBitmap; 01579 unsigned char * pIconData = NULL; 01580 unsigned int iDataSize = 0; 01581 01582 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 01583 01584 /* Find out icon size */ 01585 hDC = GetDC(0); 01586 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); 01587 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); 01588 if (1) { 01589 /* Auxiliary pointers */ 01590 CURSORICONFILEDIR * pIconDir; 01591 CURSORICONFILEDIRENTRY * pIconEntry; 01592 BITMAPINFOHEADER * pIconBitmapHeader; 01593 unsigned int iOffsetPalette; 01594 unsigned int iOffsetColorData; 01595 unsigned int iOffsetMaskData; 01596 01597 unsigned int iLengthScanLineMask; 01598 unsigned int iNumEntriesPalette; 01599 01600 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2; 01601 /* 01602 FIXME("DEBUG: bitmap size is %d x %d\n", 01603 pInfoBitmap->bmiHeader.biWidth, 01604 pInfoBitmap->bmiHeader.biHeight); 01605 FIXME("DEBUG: bitmap bpp is %d\n", 01606 pInfoBitmap->bmiHeader.biBitCount); 01607 FIXME("DEBUG: bitmap nplanes is %d\n", 01608 pInfoBitmap->bmiHeader.biPlanes); 01609 FIXME("DEBUG: bitmap biSizeImage is %u\n", 01610 pInfoBitmap->bmiHeader.biSizeImage); 01611 */ 01612 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */ 01613 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER); 01614 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize); 01615 01616 /* Fill out the CURSORICONFILEDIR */ 01617 pIconDir = (CURSORICONFILEDIR *)pIconData; 01618 pIconDir->idType = 1; 01619 pIconDir->idCount = 1; 01620 01621 /* Fill out the CURSORICONFILEDIRENTRY */ 01622 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); 01623 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth; 01624 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight; 01625 pIconEntry->bColorCount = 01626 (pInfoBitmap->bmiHeader.biBitCount < 8) 01627 ? 1 << pInfoBitmap->bmiHeader.biBitCount 01628 : 0; 01629 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes; 01630 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount; 01631 pIconEntry->dwDIBSize = 0; 01632 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY); 01633 01634 /* Fill out the BITMAPINFOHEADER */ 01635 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); 01636 *pIconBitmapHeader = pInfoBitmap->bmiHeader; 01637 01638 /* Find out whether a palette exists for the bitmap */ 01639 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB) 01640 || (pInfoBitmap->bmiHeader.biBitCount == 24) 01641 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) { 01642 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed; 01643 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; 01644 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32) 01645 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) { 01646 iNumEntriesPalette = 3; 01647 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) { 01648 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount; 01649 } else { 01650 iNumEntriesPalette = 0; 01651 } 01652 01653 /* Add bitmap size and header size to icon data size. */ 01654 iOffsetPalette = iDataSize; 01655 iDataSize += iNumEntriesPalette * sizeof(DWORD); 01656 iOffsetColorData = iDataSize; 01657 iDataSize += pIconBitmapHeader->biSizeImage; 01658 iOffsetMaskData = iDataSize; 01659 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask; 01660 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask; 01661 pIconBitmapHeader->biHeight *= 2; 01662 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize); 01663 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); 01664 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); 01665 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); 01666 01667 /* Get the actual bitmap data from the icon bitmap */ 01668 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight, 01669 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS); 01670 if (iNumEntriesPalette > 0) { 01671 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors, 01672 iNumEntriesPalette * sizeof(RGBQUAD)); 01673 } 01674 01675 /* Reset all values so that GetDIBits call succeeds */ 01676 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData); 01677 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 01678 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); 01679 /* 01680 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS) 01681 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, 01682 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) { 01683 01684 printf("ERROR: unable to get bitmap mask (error %u)\n", 01685 GetLastError()); 01686 01687 } 01688 */ 01689 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); 01690 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS); 01691 01692 /* Write out everything produced so far to the stream */ 01693 *ppBuffer = pIconData; *pLength = iDataSize; 01694 iSuccess = 1; 01695 } else { 01696 /* 01697 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n", 01698 GetLastError()); 01699 */ 01700 } 01701 /* 01702 Remarks (from MSDN entry on GetIconInfo): 01703 01704 GetIconInfo creates bitmaps for the hbmMask and hbmColor 01705 members of ICONINFO. The calling application must manage 01706 these bitmaps and delete them when they are no longer 01707 necessary. 01708 */ 01709 if (hDC) ReleaseDC(0, hDC); 01710 DeleteObject(infoIcon.hbmMask); 01711 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor); 01712 HeapFree(GetProcessHeap(), 0, pInfoBitmap); 01713 } else { 01714 printf("ERROR: Unable to get icon information (error %u)\n", 01715 GetLastError()); 01716 } 01717 return iSuccess; 01718 } 01719 01720 static HRESULT WINAPI OLEPictureImpl_Save( 01721 IPersistStream* iface,IStream*pStm,BOOL fClearDirty) 01722 { 01723 HRESULT hResult = E_NOTIMPL; 01724 void * pIconData; 01725 unsigned int iDataSize; 01726 ULONG dummy; 01727 int iSerializeResult = 0; 01728 OLEPictureImpl *This = impl_from_IPersistStream(iface); 01729 01730 TRACE("%p %p %d\n", This, pStm, fClearDirty); 01731 01732 switch (This->desc.picType) { 01733 case PICTYPE_ICON: 01734 if (This->bIsDirty || !This->data) { 01735 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) { 01736 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty); 01737 hResult = E_FAIL; 01738 break; 01739 } 01740 HeapFree(GetProcessHeap(), 0, This->data); 01741 This->data = pIconData; 01742 This->datalen = iDataSize; 01743 } 01744 if (This->loadtime_magic != 0xdeadbeef) { 01745 DWORD header[2]; 01746 01747 header[0] = This->loadtime_magic; 01748 header[1] = This->datalen; 01749 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); 01750 } 01751 IStream_Write(pStm, This->data, This->datalen, &dummy); 01752 01753 hResult = S_OK; 01754 break; 01755 case PICTYPE_BITMAP: 01756 if (This->bIsDirty) { 01757 switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) { 01758 case BITMAP_FORMAT_BMP: 01759 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize); 01760 break; 01761 case BITMAP_FORMAT_JPEG: 01762 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty); 01763 break; 01764 case BITMAP_FORMAT_GIF: 01765 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty); 01766 break; 01767 case BITMAP_FORMAT_PNG: 01768 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty); 01769 break; 01770 default: 01771 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty); 01772 break; 01773 } 01774 if (iSerializeResult) { 01775 /* 01776 if (This->loadtime_magic != 0xdeadbeef) { 01777 */ 01778 if (1) { 01779 DWORD header[2]; 01780 01781 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c; 01782 header[1] = iDataSize; 01783 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); 01784 } 01785 IStream_Write(pStm, pIconData, iDataSize, &dummy); 01786 01787 HeapFree(GetProcessHeap(), 0, This->data); 01788 This->data = pIconData; 01789 This->datalen = iDataSize; 01790 hResult = S_OK; 01791 } 01792 } else { 01793 /* 01794 if (This->loadtime_magic != 0xdeadbeef) { 01795 */ 01796 if (1) { 01797 DWORD header[2]; 01798 01799 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c; 01800 header[1] = This->datalen; 01801 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); 01802 } 01803 IStream_Write(pStm, This->data, This->datalen, &dummy); 01804 hResult = S_OK; 01805 } 01806 break; 01807 case PICTYPE_METAFILE: 01808 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty); 01809 break; 01810 case PICTYPE_ENHMETAFILE: 01811 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty); 01812 break; 01813 default: 01814 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty); 01815 break; 01816 } 01817 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE; 01818 return hResult; 01819 } 01820 01821 static HRESULT WINAPI OLEPictureImpl_GetSizeMax( 01822 IPersistStream* iface,ULARGE_INTEGER*pcbSize) 01823 { 01824 OLEPictureImpl *This = impl_from_IPersistStream(iface); 01825 FIXME("(%p,%p),stub!\n",This,pcbSize); 01826 return E_NOTIMPL; 01827 } 01828 01829 01830 /************************************************************************ 01831 * IDispatch 01832 */ 01833 01834 /************************************************************************ 01835 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown) 01836 * 01837 * See Windows documentation for more details on IUnknown methods. 01838 */ 01839 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface( 01840 IDispatch* iface, 01841 REFIID riid, 01842 VOID** ppvoid) 01843 { 01844 OLEPictureImpl *This = impl_from_IDispatch(iface); 01845 01846 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid); 01847 } 01848 01849 /************************************************************************ 01850 * OLEPictureImpl_IDispatch_AddRef (IUnknown) 01851 * 01852 * See Windows documentation for more details on IUnknown methods. 01853 */ 01854 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef( 01855 IDispatch* iface) 01856 { 01857 OLEPictureImpl *This = impl_from_IDispatch(iface); 01858 01859 return IPicture_AddRef((IPicture *)This); 01860 } 01861 01862 /************************************************************************ 01863 * OLEPictureImpl_IDispatch_Release (IUnknown) 01864 * 01865 * See Windows documentation for more details on IUnknown methods. 01866 */ 01867 static ULONG WINAPI OLEPictureImpl_IDispatch_Release( 01868 IDispatch* iface) 01869 { 01870 OLEPictureImpl *This = impl_from_IDispatch(iface); 01871 01872 return IPicture_Release((IPicture *)This); 01873 } 01874 01875 /************************************************************************ 01876 * OLEPictureImpl_GetTypeInfoCount (IDispatch) 01877 * 01878 * See Windows documentation for more details on IDispatch methods. 01879 */ 01880 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount( 01881 IDispatch* iface, 01882 unsigned int* pctinfo) 01883 { 01884 TRACE("(%p)\n", pctinfo); 01885 01886 *pctinfo = 1; 01887 01888 return S_OK; 01889 } 01890 01891 /************************************************************************ 01892 * OLEPictureImpl_GetTypeInfo (IDispatch) 01893 * 01894 * See Windows documentation for more details on IDispatch methods. 01895 */ 01896 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo( 01897 IDispatch* iface, 01898 UINT iTInfo, 01899 LCID lcid, 01900 ITypeInfo** ppTInfo) 01901 { 01902 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0}; 01903 ITypeLib *tl; 01904 HRESULT hres; 01905 01906 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo); 01907 01908 if (iTInfo != 0) 01909 return E_FAIL; 01910 01911 hres = LoadTypeLib(stdole2tlb, &tl); 01912 if (FAILED(hres)) 01913 { 01914 ERR("Could not load stdole2.tlb\n"); 01915 return hres; 01916 } 01917 01918 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo); 01919 if (FAILED(hres)) 01920 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres); 01921 01922 return hres; 01923 } 01924 01925 /************************************************************************ 01926 * OLEPictureImpl_GetIDsOfNames (IDispatch) 01927 * 01928 * See Windows documentation for more details on IDispatch methods. 01929 */ 01930 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames( 01931 IDispatch* iface, 01932 REFIID riid, 01933 LPOLESTR* rgszNames, 01934 UINT cNames, 01935 LCID lcid, 01936 DISPID* rgDispId) 01937 { 01938 ITypeInfo * pTInfo; 01939 HRESULT hres; 01940 01941 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid), 01942 rgszNames, cNames, (int)lcid, rgDispId); 01943 01944 if (cNames == 0) 01945 { 01946 return E_INVALIDARG; 01947 } 01948 else 01949 { 01950 /* retrieve type information */ 01951 hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo); 01952 01953 if (FAILED(hres)) 01954 { 01955 ERR("GetTypeInfo failed.\n"); 01956 return hres; 01957 } 01958 01959 /* convert names to DISPIDs */ 01960 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId); 01961 ITypeInfo_Release(pTInfo); 01962 01963 return hres; 01964 } 01965 } 01966 01967 /************************************************************************ 01968 * OLEPictureImpl_Invoke (IDispatch) 01969 * 01970 * See Windows documentation for more details on IDispatch methods. 01971 */ 01972 static HRESULT WINAPI OLEPictureImpl_Invoke( 01973 IDispatch* iface, 01974 DISPID dispIdMember, 01975 REFIID riid, 01976 LCID lcid, 01977 WORD wFlags, 01978 DISPPARAMS* pDispParams, 01979 VARIANT* pVarResult, 01980 EXCEPINFO* pExepInfo, 01981 UINT* puArgErr) 01982 { 01983 OLEPictureImpl *This = impl_from_IDispatch(iface); 01984 01985 /* validate parameters */ 01986 01987 if (!IsEqualIID(riid, &IID_NULL)) 01988 { 01989 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid)); 01990 return DISP_E_UNKNOWNNAME; 01991 } 01992 01993 if (!pDispParams) 01994 { 01995 ERR("null pDispParams not allowed\n"); 01996 return DISP_E_PARAMNOTOPTIONAL; 01997 } 01998 01999 if (wFlags & DISPATCH_PROPERTYGET) 02000 { 02001 if (pDispParams->cArgs != 0) 02002 { 02003 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs); 02004 return DISP_E_BADPARAMCOUNT; 02005 } 02006 if (!pVarResult) 02007 { 02008 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n"); 02009 return DISP_E_PARAMNOTOPTIONAL; 02010 } 02011 } 02012 else if (wFlags & DISPATCH_PROPERTYPUT) 02013 { 02014 if (pDispParams->cArgs != 1) 02015 { 02016 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs); 02017 return DISP_E_BADPARAMCOUNT; 02018 } 02019 } 02020 02021 switch (dispIdMember) 02022 { 02023 case DISPID_PICT_HANDLE: 02024 if (wFlags & DISPATCH_PROPERTYGET) 02025 { 02026 TRACE("DISPID_PICT_HANDLE\n"); 02027 V_VT(pVarResult) = VT_I4; 02028 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult)); 02029 } 02030 break; 02031 case DISPID_PICT_HPAL: 02032 if (wFlags & DISPATCH_PROPERTYGET) 02033 { 02034 TRACE("DISPID_PICT_HPAL\n"); 02035 V_VT(pVarResult) = VT_I4; 02036 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult)); 02037 } 02038 else if (wFlags & DISPATCH_PROPERTYPUT) 02039 { 02040 VARIANTARG vararg; 02041 HRESULT hr; 02042 TRACE("DISPID_PICT_HPAL\n"); 02043 02044 VariantInit(&vararg); 02045 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4); 02046 if (FAILED(hr)) 02047 return hr; 02048 02049 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg)); 02050 02051 VariantClear(&vararg); 02052 return hr; 02053 } 02054 break; 02055 case DISPID_PICT_TYPE: 02056 if (wFlags & DISPATCH_PROPERTYGET) 02057 { 02058 TRACE("DISPID_PICT_TYPE\n"); 02059 V_VT(pVarResult) = VT_I2; 02060 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult)); 02061 } 02062 break; 02063 case DISPID_PICT_WIDTH: 02064 if (wFlags & DISPATCH_PROPERTYGET) 02065 { 02066 TRACE("DISPID_PICT_WIDTH\n"); 02067 V_VT(pVarResult) = VT_I4; 02068 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult)); 02069 } 02070 break; 02071 case DISPID_PICT_HEIGHT: 02072 if (wFlags & DISPATCH_PROPERTYGET) 02073 { 02074 TRACE("DISPID_PICT_HEIGHT\n"); 02075 V_VT(pVarResult) = VT_I4; 02076 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult)); 02077 } 02078 break; 02079 } 02080 02081 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags); 02082 return DISP_E_MEMBERNOTFOUND; 02083 } 02084 02085 02086 static const IPictureVtbl OLEPictureImpl_VTable = 02087 { 02088 OLEPictureImpl_QueryInterface, 02089 OLEPictureImpl_AddRef, 02090 OLEPictureImpl_Release, 02091 OLEPictureImpl_get_Handle, 02092 OLEPictureImpl_get_hPal, 02093 OLEPictureImpl_get_Type, 02094 OLEPictureImpl_get_Width, 02095 OLEPictureImpl_get_Height, 02096 OLEPictureImpl_Render, 02097 OLEPictureImpl_set_hPal, 02098 OLEPictureImpl_get_CurDC, 02099 OLEPictureImpl_SelectPicture, 02100 OLEPictureImpl_get_KeepOriginalFormat, 02101 OLEPictureImpl_put_KeepOriginalFormat, 02102 OLEPictureImpl_PictureChanged, 02103 OLEPictureImpl_SaveAsFile, 02104 OLEPictureImpl_get_Attributes 02105 }; 02106 02107 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable = 02108 { 02109 OLEPictureImpl_IDispatch_QueryInterface, 02110 OLEPictureImpl_IDispatch_AddRef, 02111 OLEPictureImpl_IDispatch_Release, 02112 OLEPictureImpl_GetTypeInfoCount, 02113 OLEPictureImpl_GetTypeInfo, 02114 OLEPictureImpl_GetIDsOfNames, 02115 OLEPictureImpl_Invoke 02116 }; 02117 02118 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable = 02119 { 02120 OLEPictureImpl_IPersistStream_QueryInterface, 02121 OLEPictureImpl_IPersistStream_AddRef, 02122 OLEPictureImpl_IPersistStream_Release, 02123 OLEPictureImpl_GetClassID, 02124 OLEPictureImpl_IsDirty, 02125 OLEPictureImpl_Load, 02126 OLEPictureImpl_Save, 02127 OLEPictureImpl_GetSizeMax 02128 }; 02129 02130 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable = 02131 { 02132 OLEPictureImpl_IConnectionPointContainer_QueryInterface, 02133 OLEPictureImpl_IConnectionPointContainer_AddRef, 02134 OLEPictureImpl_IConnectionPointContainer_Release, 02135 OLEPictureImpl_EnumConnectionPoints, 02136 OLEPictureImpl_FindConnectionPoint 02137 }; 02138 02139 /*********************************************************************** 02140 * OleCreatePictureIndirect (OLEAUT32.419) 02141 */ 02142 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid, 02143 BOOL fOwn, LPVOID *ppvObj ) 02144 { 02145 OLEPictureImpl* newPict = NULL; 02146 HRESULT hr = S_OK; 02147 02148 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj); 02149 02150 /* 02151 * Sanity check 02152 */ 02153 if (ppvObj==0) 02154 return E_POINTER; 02155 02156 *ppvObj = NULL; 02157 02158 /* 02159 * Try to construct a new instance of the class. 02160 */ 02161 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn); 02162 02163 if (newPict == NULL) 02164 return E_OUTOFMEMORY; 02165 02166 /* 02167 * Make sure it supports the interface required by the caller. 02168 */ 02169 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj); 02170 02171 /* 02172 * Release the reference obtained in the constructor. If 02173 * the QueryInterface was unsuccessful, it will free the class. 02174 */ 02175 IPicture_Release((IPicture*)newPict); 02176 02177 return hr; 02178 } 02179 02180 02181 /*********************************************************************** 02182 * OleLoadPicture (OLEAUT32.418) 02183 */ 02184 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode, 02185 REFIID riid, LPVOID *ppvObj ) 02186 { 02187 LPPERSISTSTREAM ps; 02188 IPicture *newpic; 02189 HRESULT hr; 02190 02191 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n", 02192 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj); 02193 02194 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic); 02195 if (hr) 02196 return hr; 02197 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps); 02198 if (hr) { 02199 ERR("Could not get IPersistStream iface from Ole Picture?\n"); 02200 IPicture_Release(newpic); 02201 *ppvObj = NULL; 02202 return hr; 02203 } 02204 hr = IPersistStream_Load(ps,lpstream); 02205 IPersistStream_Release(ps); 02206 if (FAILED(hr)) 02207 { 02208 ERR("IPersistStream_Load failed\n"); 02209 IPicture_Release(newpic); 02210 *ppvObj = NULL; 02211 return hr; 02212 } 02213 hr = IPicture_QueryInterface(newpic,riid,ppvObj); 02214 if (hr) 02215 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid)); 02216 IPicture_Release(newpic); 02217 return hr; 02218 } 02219 02220 /*********************************************************************** 02221 * OleLoadPictureEx (OLEAUT32.401) 02222 */ 02223 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode, 02224 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj ) 02225 { 02226 LPPERSISTSTREAM ps; 02227 IPicture *newpic; 02228 HRESULT hr; 02229 02230 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n", 02231 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj); 02232 02233 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic); 02234 if (hr) 02235 return hr; 02236 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps); 02237 if (hr) { 02238 ERR("Could not get IPersistStream iface from Ole Picture?\n"); 02239 IPicture_Release(newpic); 02240 *ppvObj = NULL; 02241 return hr; 02242 } 02243 hr = IPersistStream_Load(ps,lpstream); 02244 IPersistStream_Release(ps); 02245 if (FAILED(hr)) 02246 { 02247 ERR("IPersistStream_Load failed\n"); 02248 IPicture_Release(newpic); 02249 *ppvObj = NULL; 02250 return hr; 02251 } 02252 hr = IPicture_QueryInterface(newpic,riid,ppvObj); 02253 if (hr) 02254 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid)); 02255 IPicture_Release(newpic); 02256 return hr; 02257 } 02258 02259 /*********************************************************************** 02260 * OleLoadPicturePath (OLEAUT32.424) 02261 */ 02262 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller, 02263 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid, 02264 LPVOID *ppvRet ) 02265 { 02266 static const WCHAR file[] = { 'f','i','l','e',':',0 }; 02267 IPicture *ipicture; 02268 HANDLE hFile; 02269 DWORD dwFileSize; 02270 HGLOBAL hGlobal = NULL; 02271 DWORD dwBytesRead = 0; 02272 IStream *stream; 02273 BOOL bRead; 02274 IPersistStream *pStream; 02275 HRESULT hRes; 02276 HRESULT init_res; 02277 WCHAR *file_candidate; 02278 WCHAR path_buf[MAX_PATH]; 02279 02280 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n", 02281 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved, 02282 debugstr_guid(riid), ppvRet); 02283 02284 if (!szURLorPath || !ppvRet) 02285 return E_INVALIDARG; 02286 02287 *ppvRet = NULL; 02288 02289 /* Convert file URLs to DOS paths. */ 02290 if (strncmpW(szURLorPath, file, 5) == 0) { 02291 DWORD size; 02292 hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf, 02293 sizeof(path_buf)/sizeof(WCHAR), &size, 0); 02294 if (FAILED(hRes)) 02295 return hRes; 02296 02297 file_candidate = path_buf; 02298 } 02299 else 02300 file_candidate = szURLorPath; 02301 02302 /* Handle candidate DOS paths separately. */ 02303 if (file_candidate[1] == ':') { 02304 hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING, 02305 0, NULL); 02306 if (hFile == INVALID_HANDLE_VALUE) 02307 return E_UNEXPECTED; 02308 02309 dwFileSize = GetFileSize(hFile, NULL); 02310 if (dwFileSize != INVALID_FILE_SIZE ) 02311 { 02312 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize); 02313 if ( hGlobal) 02314 { 02315 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL); 02316 if (!bRead) 02317 { 02318 GlobalFree(hGlobal); 02319 hGlobal = 0; 02320 } 02321 } 02322 } 02323 CloseHandle(hFile); 02324 02325 if (!hGlobal) 02326 return E_UNEXPECTED; 02327 02328 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream); 02329 if (FAILED(hRes)) 02330 { 02331 GlobalFree(hGlobal); 02332 return hRes; 02333 } 02334 } else { 02335 IMoniker *pmnk; 02336 IBindCtx *pbc; 02337 02338 hRes = CreateBindCtx(0, &pbc); 02339 if (SUCCEEDED(hRes)) 02340 { 02341 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk); 02342 if (SUCCEEDED(hRes)) 02343 { 02344 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream); 02345 IMoniker_Release(pmnk); 02346 } 02347 IBindCtx_Release(pbc); 02348 } 02349 if (FAILED(hRes)) 02350 return hRes; 02351 } 02352 02353 init_res = CoInitialize(NULL); 02354 02355 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER, 02356 &IID_IPicture, (LPVOID*)&ipicture); 02357 if (SUCCEEDED(hRes)) { 02358 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream); 02359 02360 if (SUCCEEDED(hRes)) { 02361 hRes = IPersistStream_Load(pStream, stream); 02362 02363 if (SUCCEEDED(hRes)) { 02364 hRes = IPicture_QueryInterface(ipicture, riid, ppvRet); 02365 02366 if (FAILED(hRes)) 02367 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid)); 02368 } 02369 IPersistStream_Release(pStream); 02370 } 02371 IPicture_Release(ipicture); 02372 } 02373 02374 IStream_Release(stream); 02375 02376 if (SUCCEEDED(init_res)) 02377 CoUninitialize(); 02378 02379 return hRes; 02380 } 02381 02382 /******************************************************************************* 02383 * StdPic ClassFactory 02384 */ 02385 typedef struct 02386 { 02387 /* IUnknown fields */ 02388 const IClassFactoryVtbl *lpVtbl; 02389 LONG ref; 02390 } IClassFactoryImpl; 02391 02392 static HRESULT WINAPI 02393 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { 02394 IClassFactoryImpl *This = (IClassFactoryImpl *)iface; 02395 02396 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj); 02397 return E_NOINTERFACE; 02398 } 02399 02400 static ULONG WINAPI 02401 SPCF_AddRef(LPCLASSFACTORY iface) { 02402 IClassFactoryImpl *This = (IClassFactoryImpl *)iface; 02403 return InterlockedIncrement(&This->ref); 02404 } 02405 02406 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) { 02407 IClassFactoryImpl *This = (IClassFactoryImpl *)iface; 02408 /* static class, won't be freed */ 02409 return InterlockedDecrement(&This->ref); 02410 } 02411 02412 static HRESULT WINAPI SPCF_CreateInstance( 02413 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj 02414 ) { 02415 /* Creates an uninitialized picture */ 02416 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj); 02417 02418 } 02419 02420 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { 02421 IClassFactoryImpl *This = (IClassFactoryImpl *)iface; 02422 FIXME("(%p)->(%d),stub!\n",This,dolock); 02423 return S_OK; 02424 } 02425 02426 static const IClassFactoryVtbl SPCF_Vtbl = { 02427 SPCF_QueryInterface, 02428 SPCF_AddRef, 02429 SPCF_Release, 02430 SPCF_CreateInstance, 02431 SPCF_LockServer 02432 }; 02433 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 }; 02434 02435 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; } Generated on Wed May 23 2012 04:23:33 for ReactOS by
1.7.6.1
|