ReactOS  0.4.15-dev-1203-g0e5a4d5
datacache.c
Go to the documentation of this file.
1 /*
2  * OLE 2 Data cache
3  *
4  * Copyright 1999 Francis Beaudet
5  * Copyright 2000 Abey George
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * NOTES:
22  * The OLE2 data cache supports a whole whack of
23  * interfaces including:
24  * IDataObject, IPersistStorage, IViewObject2,
25  * IOleCache2 and IOleCacheControl.
26  *
27  * Most of the implementation details are taken from: Inside OLE
28  * second edition by Kraig Brockschmidt,
29  *
30  * NOTES
31  * - This implementation of the datacache will let your application
32  * load documents that have embedded OLE objects in them and it will
33  * also retrieve the metafile representation of those objects.
34  * - This implementation of the datacache will also allow your
35  * application to save new documents with OLE objects in them.
36  * - The main thing that it doesn't do is allow you to activate
37  * or modify the OLE objects in any way.
38  * - I haven't found any good documentation on the real usage of
39  * the streams created by the data cache. In particular, How to
40  * determine what the XXX stands for in the stream name
41  * "\002OlePresXXX". It appears to just be a counter.
42  * - Also, I don't know the real content of the presentation stream
43  * header. I was able to figure-out where the extent of the object
44  * was stored and the aspect, but that's about it.
45  */
46 
47 #include <stdarg.h>
48 #include <string.h>
49 
50 #define COBJMACROS
51 #define NONAMELESSUNION
52 
53 #include "windef.h"
54 #include "winbase.h"
55 #include "wingdi.h"
56 #include "winuser.h"
57 #include "winerror.h"
58 #include "ole2.h"
59 #include "compobj_private.h"
60 #include "wine/list.h"
61 #include "wine/debug.h"
62 
64 
65 /****************************************************************************
66  * PresentationDataHeader
67  *
68  * This structure represents the header of the \002OlePresXXX stream in
69  * the OLE object storage.
70  */
71 typedef struct PresentationDataHeader
72 {
73  /* clipformat:
74  * - standard clipformat:
75  * DWORD length = 0xffffffff;
76  * DWORD cfFormat;
77  * - or custom clipformat:
78  * DWORD length;
79  * CHAR format_name[length]; (null-terminated)
80  */
81  DWORD tdSize; /* This is actually a truncated DVTARGETDEVICE, if tdSize > sizeof(DWORD)
82  then there are tdSize - sizeof(DWORD) more bytes before dvAspect */
83  DVASPECT dvAspect;
86  DWORD unknown7; /* 0 */
89  DWORD dwSize;
91 
92 #define STREAM_NUMBER_NOT_SET -2
93 #define STREAM_NUMBER_CONTENTS -1 /* CONTENTS stream */
94 
95 typedef struct DataCacheEntry
96 {
97  struct list entry;
98  /* format of this entry */
99  FORMATETC fmtetc;
100  /* cached data */
101  STGMEDIUM stgmedium;
102  /* connection ID */
104  /* dirty flag */
106  /* stream number that the entry was loaded from.
107  This is used to defer loading until the data is actually needed. */
109  /* stream number that the entry will be saved to.
110  This may differ from above if cache entries have been Uncache()d for example. */
112  /* sink id set when object is running */
114  /* Advise sink flags */
117 
118 /****************************************************************************
119  * DataCache
120  */
121 struct DataCache
122 {
123  /*
124  * List all interface here
125  */
132 
133  /* The sink that is connected to a remote object.
134  The other interfaces are not available by QI'ing the sink and vice-versa */
136 
137  /*
138  * Reference count of this object
139  */
141 
142  /*
143  * IUnknown implementation of the outer object.
144  */
146 
147  /*
148  * The user of this object can setup ONE advise sink
149  * connection with the object. These parameters describe
150  * that connection.
151  */
155 
157  /* Is the clsid one of the CLSID_Picture classes */
159 
161 
162  /* list of cache entries */
163  struct list cache_list;
164  /* last id assigned to an entry */
166  /* dirty flag */
168  /* running object set by OnRun */
170 };
171 
172 typedef struct DataCache DataCache;
173 
174 /*
175  * Here, I define utility macros to help with the casting of the
176  * "this" parameter.
177  * There is a version to accommodate all of the VTables implemented
178  * by this object.
179  */
180 
182 {
184 }
185 
186 static inline DataCache *impl_from_IUnknown( IUnknown *iface )
187 {
189 }
190 
192 {
194 }
195 
197 {
199 }
200 
201 static inline DataCache *impl_from_IOleCache2( IOleCache2 *iface )
202 {
204 }
205 
207 {
209 }
210 
212 {
214 }
215 
216 const char *debugstr_formatetc(const FORMATETC *formatetc)
217 {
218  return wine_dbg_sprintf("{ cfFormat = 0x%x, ptd = %p, dwAspect = %d, lindex = %d, tymed = %d }",
219  formatetc->cfFormat, formatetc->ptd, formatetc->dwAspect,
220  formatetc->lindex, formatetc->tymed);
221 }
222 
223 /***********************************************************************
224  * bitmap_info_size
225  *
226  * Return the size of the bitmap info structure including color table.
227  */
228 static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
229 {
230  unsigned int colors, size, masks = 0;
231 
232  if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
233  {
234  const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
235  colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
236  return sizeof(BITMAPCOREHEADER) + colors *
237  ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
238  }
239  else /* assume BITMAPINFOHEADER */
240  {
241  colors = info->bmiHeader.biClrUsed;
242  if (colors > 256) /* buffer overflow otherwise */
243  colors = 256;
244  if (!colors && (info->bmiHeader.biBitCount <= 8))
245  colors = 1 << info->bmiHeader.biBitCount;
246  if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
247  size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
248  return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
249  }
250 }
251 
253 {
254  list_remove(&cache_entry->entry);
255  CoTaskMemFree(cache_entry->fmtetc.ptd);
256  ReleaseStgMedium(&cache_entry->stgmedium);
257  if(cache_entry->sink_id)
258  IDataObject_DUnadvise(cache->running_object, cache_entry->sink_id);
259 
261 }
262 
263 static void DataCache_Destroy(
264  DataCache* ptrToDestroy)
265 {
266  DataCacheEntry *cache_entry, *next_cache_entry;
267 
268  TRACE("()\n");
269 
270  if (ptrToDestroy->sinkInterface != NULL)
271  {
272  IAdviseSink_Release(ptrToDestroy->sinkInterface);
273  ptrToDestroy->sinkInterface = NULL;
274  }
275 
276  LIST_FOR_EACH_ENTRY_SAFE(cache_entry, next_cache_entry, &ptrToDestroy->cache_list, DataCacheEntry, entry)
277  DataCacheEntry_Destroy(ptrToDestroy, cache_entry);
278 
279  if (ptrToDestroy->presentationStorage != NULL)
280  {
281  IStorage_Release(ptrToDestroy->presentationStorage);
282  ptrToDestroy->presentationStorage = NULL;
283  }
284 
285  /*
286  * Free the datacache pointer.
287  */
288  HeapFree(GetProcessHeap(), 0, ptrToDestroy);
289 }
290 
291 static DataCacheEntry *DataCache_GetEntryForFormatEtc(DataCache *This, const FORMATETC *formatetc)
292 {
294  FORMATETC fmt = *formatetc;
295 
296  if (fmt.cfFormat == CF_BITMAP)
297  {
298  fmt.cfFormat = CF_DIB;
299  fmt.tymed = TYMED_HGLOBAL;
300  }
301 
303  {
304  /* FIXME: also compare DVTARGETDEVICEs */
305  if ((fmt.cfFormat == cache_entry->fmtetc.cfFormat) &&
306  (fmt.dwAspect == cache_entry->fmtetc.dwAspect) &&
307  (fmt.lindex == cache_entry->fmtetc.lindex) &&
308  ((fmt.tymed == cache_entry->fmtetc.tymed) || !cache_entry->fmtetc.cfFormat)) /* tymed is ignored for view caching */
309  return cache_entry;
310  }
311  return NULL;
312 }
313 
314 /* Returns the cache entry associated with a static CLSID.
315  This will be first in the list with connection id == 1 */
317 {
319  struct list *head = list_head( &cache->cache_list );
320  HRESULT hr = E_FAIL;
321 
322  *cache_entry = NULL;
323 
324  if (head)
325  {
327  if (entry->id == 1)
328  {
329  *cache_entry = entry;
330  hr = S_OK;
331  }
332  }
333 
334  return hr;
335 }
336 
337 /* checks that the clipformat and tymed are valid and returns an error if they
338 * aren't and CACHE_S_NOTSUPPORTED if they are valid, but can't be rendered by
339 * DataCache_Draw */
340 static HRESULT check_valid_formatetc( const FORMATETC *fmt )
341 {
342  /* DVASPECT_ICON must be CF_METAFILEPICT */
343  if (fmt->dwAspect == DVASPECT_ICON && fmt->cfFormat != CF_METAFILEPICT)
344  return DV_E_FORMATETC;
345 
346  if (!fmt->cfFormat ||
347  (fmt->cfFormat == CF_METAFILEPICT && fmt->tymed == TYMED_MFPICT) ||
348  (fmt->cfFormat == CF_BITMAP && fmt->tymed == TYMED_GDI) ||
349  (fmt->cfFormat == CF_DIB && fmt->tymed == TYMED_HGLOBAL) ||
350  (fmt->cfFormat == CF_ENHMETAFILE && fmt->tymed == TYMED_ENHMF))
351  return S_OK;
352  else if (fmt->tymed == TYMED_HGLOBAL)
354  else
355  {
356  WARN("invalid clipformat/tymed combination: %d/%d\n", fmt->cfFormat, fmt->tymed);
357  return DV_E_TYMED;
358  }
359 }
360 
361 static BOOL init_cache_entry(DataCacheEntry *entry, const FORMATETC *fmt, DWORD advf,
362  DWORD id)
363 {
364  HRESULT hr;
365 
366  hr = copy_formatetc(&entry->fmtetc, fmt);
367  if (FAILED(hr)) return FALSE;
368 
369  entry->stgmedium.tymed = TYMED_NULL;
370  entry->stgmedium.pUnkForRelease = NULL;
371  entry->id = id;
372  entry->dirty = TRUE;
373  entry->load_stream_num = STREAM_NUMBER_NOT_SET;
374  entry->save_stream_num = STREAM_NUMBER_NOT_SET;
375  entry->sink_id = 0;
376  entry->advise_flags = advf;
377 
378  return TRUE;
379 }
380 
381 static HRESULT DataCache_CreateEntry(DataCache *This, const FORMATETC *formatetc, DWORD advf,
382  BOOL automatic, DataCacheEntry **cache_entry)
383 {
384  HRESULT hr;
385  DWORD id = automatic ? 1 : This->last_cache_id;
387 
388  hr = check_valid_formatetc( formatetc );
389  if (FAILED(hr))
390  return hr;
392  TRACE("creating unsupported format %d\n", formatetc->cfFormat);
393 
394  entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
395  if (!entry)
396  return E_OUTOFMEMORY;
397 
398  if (!init_cache_entry(entry, formatetc, advf, id))
399  goto fail;
400 
401  if (automatic)
402  list_add_head(&This->cache_list, &entry->entry);
403  else
404  {
405  list_add_tail(&This->cache_list, &entry->entry);
406  This->last_cache_id++;
407  }
408 
409  if (cache_entry) *cache_entry = entry;
410  return hr;
411 
412 fail:
414  return E_OUTOFMEMORY;
415 }
416 
417 /************************************************************************
418  * DataCache_FireOnViewChange
419  *
420  * This method will fire an OnViewChange notification to the advise
421  * sink registered with the datacache.
422  *
423  * See IAdviseSink::OnViewChange for more details.
424  */
426  DataCache* this,
427  DWORD aspect,
428  LONG lindex)
429 {
430  TRACE("(%p, %x, %d)\n", this, aspect, lindex);
431 
432  /*
433  * The sink supplies a filter when it registers
434  * we make sure we only send the notifications when that
435  * filter matches.
436  */
437  if ((this->sinkAspects & aspect) != 0)
438  {
439  if (this->sinkInterface != NULL)
440  {
441  IAdviseSink_OnViewChange(this->sinkInterface,
442  aspect,
443  lindex);
444 
445  /*
446  * Some sinks want to be unregistered automatically when
447  * the first notification goes out.
448  */
449  if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
450  {
451  IAdviseSink_Release(this->sinkInterface);
452 
453  this->sinkInterface = NULL;
454  this->sinkAspects = 0;
455  this->sinkAdviseFlag = 0;
456  }
457  }
458  }
459 }
460 
461 static HRESULT read_clipformat(IStream *stream, CLIPFORMAT *clipformat)
462 {
463  DWORD length;
464  HRESULT hr;
465  ULONG read;
466 
467  *clipformat = 0;
468 
469  hr = IStream_Read(stream, &length, sizeof(length), &read);
470  if (hr != S_OK || read != sizeof(length))
471  return DV_E_CLIPFORMAT;
472  if (!length) {
473  /* No clipboard format present */
474  return S_OK;
475  }
476  if (length == -1)
477  {
478  DWORD cf;
479  hr = IStream_Read(stream, &cf, sizeof(cf), &read);
480  if (hr != S_OK || read != sizeof(cf))
481  return DV_E_CLIPFORMAT;
482  *clipformat = cf;
483  }
484  else
485  {
486  char *format_name = HeapAlloc(GetProcessHeap(), 0, length);
487  if (!format_name)
488  return E_OUTOFMEMORY;
489  hr = IStream_Read(stream, format_name, length, &read);
490  if (hr != S_OK || read != length || format_name[length - 1] != '\0')
491  {
492  HeapFree(GetProcessHeap(), 0, format_name);
493  return DV_E_CLIPFORMAT;
494  }
495  *clipformat = RegisterClipboardFormatA(format_name);
496  HeapFree(GetProcessHeap(), 0, format_name);
497  }
498  return S_OK;
499 }
500 
501 static HRESULT write_clipformat(IStream *stream, CLIPFORMAT clipformat)
502 {
503  DWORD length;
504  HRESULT hr;
505  char format_name[256];
506 
507  if (clipformat == 0)
508  length = 0;
509  else if (clipformat < 0xc000)
510  length = -1;
511  else
512  {
513  length = GetClipboardFormatNameA(clipformat, format_name, sizeof(format_name));
514  /* If there is a clipboard format name, we need to include its terminating \0 */
515  if (length) length++;
516  }
517  hr = IStream_Write(stream, &length, sizeof(length), NULL);
518  if (FAILED(hr) || clipformat == 0)
519  return hr;
520 
521  if (clipformat < 0xc000)
522  {
523  DWORD cf = clipformat;
524  hr = IStream_Write(stream, &cf, sizeof(cf), NULL);
525  }
526  else
527  {
528  hr = IStream_Write(stream, format_name, length, NULL);
529  }
530  return hr;
531 }
532 
533 static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
534 
535 static HRESULT open_pres_stream( IStorage *stg, int stream_number, IStream **stm )
536 {
537  WCHAR pres[] = {2,'O','l','e','P','r','e','s',
538  '0' + (stream_number / 100) % 10,
539  '0' + (stream_number / 10) % 10,
540  '0' + stream_number % 10, 0};
541  const WCHAR *name = pres;
542 
543  if (stream_number == STREAM_NUMBER_NOT_SET) return E_FAIL;
544  if (stream_number == STREAM_NUMBER_CONTENTS) name = CONTENTS;
545 
546  return IStorage_OpenStream( stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
547 }
548 
549 static HRESULT synthesize_emf( HMETAFILEPICT data, STGMEDIUM *med )
550 {
551  METAFILEPICT *pict;
552  HRESULT hr = E_FAIL;
553  UINT size;
554  void *bits;
555 
556  if (!(pict = GlobalLock( data ))) return hr;
557 
558  size = GetMetaFileBitsEx( pict->hMF, 0, NULL );
559  if ((bits = HeapAlloc( GetProcessHeap(), 0, size )))
560  {
561  GetMetaFileBitsEx( pict->hMF, size, bits );
562  med->u.hEnhMetaFile = SetWinMetaFileBits( size, bits, NULL, pict );
563  HeapFree( GetProcessHeap(), 0, bits );
564  med->tymed = TYMED_ENHMF;
565  med->pUnkForRelease = NULL;
566  hr = S_OK;
567  }
568 
569  GlobalUnlock( data );
570  return hr;
571 }
572 #include <pshpack2.h>
574 {
581 };
582 #include <poppack.h>
583 
585 {
586  HRESULT hr;
587  STATSTG stat;
588  ULARGE_INTEGER current_pos;
589  void *bits;
590  METAFILEPICT *mfpict;
591  HGLOBAL hmfpict;
593  CLIPFORMAT clipformat;
594  static const LARGE_INTEGER offset_zero;
595  ULONG read;
596  struct meta_placeable mf_place;
597 
598  hr = IStream_Stat( stm, &stat, STATFLAG_NONAME );
599  if (FAILED( hr )) return hr;
600 
601  if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
602  {
603  hr = read_clipformat( stm, &clipformat );
604  if (hr != S_OK) return hr;
605  hr = IStream_Read( stm, &header, sizeof(header), &read );
606  if (hr != S_OK) return hr;
607  }
608  else
609  {
610  hr = IStream_Read( stm, &mf_place, sizeof(mf_place), &read );
611  if (hr != S_OK) return hr;
612  }
613 
614  hr = IStream_Seek( stm, offset_zero, STREAM_SEEK_CUR, &current_pos );
615  if (FAILED( hr )) return hr;
616  stat.cbSize.QuadPart -= current_pos.QuadPart;
617 
618  hmfpict = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) );
619  if (!hmfpict) return E_OUTOFMEMORY;
620  mfpict = GlobalLock( hmfpict );
621 
622  bits = HeapAlloc( GetProcessHeap(), 0, stat.cbSize.u.LowPart);
623  if (!bits)
624  {
625  GlobalFree( hmfpict );
626  return E_OUTOFMEMORY;
627  }
628 
629  hr = IStream_Read( stm, bits, stat.cbSize.u.LowPart, &read );
630 
631  if (SUCCEEDED( hr ))
632  {
633  mfpict->mm = MM_ANISOTROPIC;
634  /* FIXME: get this from the stream */
635  if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
636  {
637  mfpict->xExt = header.dwObjectExtentX;
638  mfpict->yExt = header.dwObjectExtentY;
639  }
640  else
641  {
642  mfpict->xExt = ((mf_place.bounding_box[2] - mf_place.bounding_box[0])
643  * 2540) / mf_place.inch;
644  mfpict->yExt = ((mf_place.bounding_box[3] - mf_place.bounding_box[1])
645  * 2540) / mf_place.inch;
646  }
647  mfpict->hMF = SetMetaFileBitsEx( stat.cbSize.u.LowPart, bits );
648  if (!mfpict->hMF)
649  hr = E_FAIL;
650  }
651 
652  GlobalUnlock( hmfpict );
653  if (SUCCEEDED( hr ))
654  {
655  cache_entry->stgmedium.tymed = TYMED_MFPICT;
656  cache_entry->stgmedium.u.hMetaFilePict = hmfpict;
657  }
658  else
659  GlobalFree( hmfpict );
660 
661  HeapFree( GetProcessHeap(), 0, bits );
662 
663  return hr;
664 }
665 
667 {
668  HRESULT hr;
669  STATSTG stat;
670  BYTE *dib;
671  HGLOBAL hglobal;
672  ULONG read, info_size, bi_size;
675  CLIPFORMAT cf;
677  ULARGE_INTEGER current_pos;
678  static const LARGE_INTEGER offset_zero;
679 
680  hr = IStream_Stat( stm, &stat, STATFLAG_NONAME );
681  if (FAILED( hr )) return hr;
682 
683  if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
684  {
685  hr = read_clipformat( stm, &cf );
686  if (hr != S_OK) return hr;
687  hr = IStream_Read( stm, &pres, sizeof(pres), &read );
688  if (hr != S_OK) return hr;
689  }
690  else
691  {
692  hr = IStream_Read( stm, &file, sizeof(BITMAPFILEHEADER), &read );
693  if (hr != S_OK) return hr;
694  }
695 
696  hr = IStream_Seek( stm, offset_zero, STREAM_SEEK_CUR, &current_pos );
697  if (FAILED( hr )) return hr;
698  stat.cbSize.QuadPart -= current_pos.QuadPart;
699 
700  hglobal = GlobalAlloc( GMEM_MOVEABLE, stat.cbSize.u.LowPart );
701  if (!hglobal) return E_OUTOFMEMORY;
702  dib = GlobalLock( hglobal );
703 
704  /* read first DWORD of BITMAPINFOHEADER */
705  hr = IStream_Read( stm, dib, sizeof(DWORD), &read );
706  if (hr != S_OK) goto fail;
707  bi_size = *(DWORD *)dib;
708  if (stat.cbSize.QuadPart < bi_size) goto fail;
709 
710  /* read rest of BITMAPINFOHEADER */
711  hr = IStream_Read( stm, dib + sizeof(DWORD), bi_size - sizeof(DWORD), &read );
712  if (hr != S_OK) goto fail;
713 
714  info_size = bitmap_info_size( (BITMAPINFO *)dib, DIB_RGB_COLORS );
715  if (stat.cbSize.QuadPart < info_size) goto fail;
716  if (info_size > bi_size)
717  {
718  hr = IStream_Read( stm, dib + bi_size, info_size - bi_size, &read );
719  if (hr != S_OK) goto fail;
720  }
721  stat.cbSize.QuadPart -= info_size;
722 
723  /* set Stream pointer to beginning of bitmap bits */
724  if (cache_entry->load_stream_num == STREAM_NUMBER_CONTENTS && file.bfOffBits)
725  {
727 
728  skip.QuadPart = file.bfOffBits - sizeof(file) - info_size;
729  if (stat.cbSize.QuadPart < skip.QuadPart) goto fail;
730  hr = IStream_Seek( stm, skip, STREAM_SEEK_CUR, NULL );
731  if (hr != S_OK) goto fail;
732  stat.cbSize.QuadPart -= skip.QuadPart;
733  }
734 
735  hr = IStream_Read( stm, dib + info_size, stat.cbSize.u.LowPart, &read );
736  if (hr != S_OK) goto fail;
737 
738  if (bi_size >= sizeof(*info))
739  {
741  if (info->biXPelsPerMeter == 0 || info->biYPelsPerMeter == 0)
742  {
743  HDC hdc = GetDC( 0 );
744  info->biXPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSX ), 10000, 254 );
745  info->biYPelsPerMeter = MulDiv( GetDeviceCaps( hdc, LOGPIXELSY ), 10000, 254 );
746  ReleaseDC( 0, hdc );
747  }
748  }
749 
750  GlobalUnlock( hglobal );
751 
752  cache_entry->stgmedium.tymed = TYMED_HGLOBAL;
753  cache_entry->stgmedium.u.hGlobal = hglobal;
754 
755  return hr;
756 
757 fail:
758  GlobalUnlock( hglobal );
759  GlobalFree( hglobal );
760  return hr;
761 
762 }
763 
765 {
766  HRESULT hr;
767 
768  if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
769  {
770  STGMEDIUM stgmed;
771 
772  hr = load_mf_pict( cache_entry, stm );
773  if (SUCCEEDED( hr ))
774  {
775  hr = synthesize_emf( cache_entry->stgmedium.u.hMetaFilePict, &stgmed );
776  ReleaseStgMedium( &cache_entry->stgmedium );
777  }
778  if (SUCCEEDED( hr ))
779  cache_entry->stgmedium = stgmed;
780  }
781  else
782  {
783  STATSTG stat;
784  BYTE *data;
785  ULONG read, size_bits;
786 
787  hr = IStream_Stat( stm, &stat, STATFLAG_NONAME );
788 
789  if (SUCCEEDED( hr ))
790  {
791  data = HeapAlloc( GetProcessHeap(), 0, stat.cbSize.u.LowPart );
792  if (!data) return E_OUTOFMEMORY;
793 
794  hr = IStream_Read( stm, data, stat.cbSize.u.LowPart, &read );
795  if (hr != S_OK)
796  {
797  HeapFree( GetProcessHeap(), 0, data );
798  return hr;
799  }
800 
801  if (read <= sizeof(DWORD) + sizeof(ENHMETAHEADER))
802  {
803  HeapFree( GetProcessHeap(), 0, data );
804  return E_FAIL;
805  }
806  size_bits = read - sizeof(DWORD) - sizeof(ENHMETAHEADER);
807  cache_entry->stgmedium.u.hEnhMetaFile = SetEnhMetaFileBits( size_bits, data + (read - size_bits) );
808  cache_entry->stgmedium.tymed = TYMED_ENHMF;
809  cache_entry->stgmedium.pUnkForRelease = NULL;
810 
811  HeapFree( GetProcessHeap(), 0, data );
812  }
813  }
814 
815  return hr;
816 }
817 
818 /************************************************************************
819  * DataCacheEntry_LoadData
820  *
821  * This method will read information for the requested presentation
822  * into the given structure.
823  *
824  * Param:
825  * This - The entry to load the data from.
826  *
827  * Returns:
828  * This method returns a metafile handle if it is successful.
829  * it will return 0 if not.
830  */
832 {
833  HRESULT hr;
834  IStream *stm;
835 
836  if (!stg) return OLE_E_BLANK;
837  hr = open_pres_stream( stg, cache_entry->load_stream_num, &stm );
838  if (FAILED(hr)) return hr;
839 
840  switch (cache_entry->fmtetc.cfFormat)
841  {
842  case CF_METAFILEPICT:
843  hr = load_mf_pict( cache_entry, stm );
844  break;
845 
846  case CF_DIB:
847  hr = load_dib( cache_entry, stm );
848  break;
849 
850  case CF_ENHMETAFILE:
851  hr = load_emf( cache_entry, stm );
852  break;
853 
854  default:
855  FIXME( "Unimplemented clip format %x\n", cache_entry->fmtetc.cfFormat );
856  hr = E_NOTIMPL;
857  }
858 
859  IStream_Release( stm );
860  return hr;
861 }
862 
864 {
865  if (entry->fmtetc.ptd)
866  FIXME("ptd not serialized\n");
867  header->tdSize = sizeof(header->tdSize);
868  header->dvAspect = entry->fmtetc.dwAspect;
869  header->lindex = entry->fmtetc.lindex;
870  header->advf = entry->advise_flags;
871  header->unknown7 = 0;
872  header->dwObjectExtentX = 0;
873  header->dwObjectExtentY = 0;
874  header->dwSize = 0;
875 }
876 
878 {
879  HRESULT hr = S_OK;
880  int data_size = 0;
881  BITMAPINFO *bmi = NULL;
882 
883  if (entry->stgmedium.tymed != TYMED_NULL)
884  {
885  data_size = GlobalSize(entry->stgmedium.u.hGlobal);
886  bmi = GlobalLock(entry->stgmedium.u.hGlobal);
887  }
888 
889  if (!contents)
890  {
892 
894  hr = write_clipformat(stream, entry->fmtetc.cfFormat);
895  if (FAILED(hr)) goto end;
896  if (data_size)
897  {
898  header.dwSize = data_size;
899  /* Size in units of 0.01mm (ie. MM_HIMETRIC) */
900  if (bmi->bmiHeader.biXPelsPerMeter != 0 && bmi->bmiHeader.biYPelsPerMeter != 0)
901  {
902  header.dwObjectExtentX = MulDiv(bmi->bmiHeader.biWidth, 100000, bmi->bmiHeader.biXPelsPerMeter);
903  header.dwObjectExtentY = MulDiv(bmi->bmiHeader.biHeight, 100000, bmi->bmiHeader.biYPelsPerMeter);
904  }
905  else
906  {
907  HDC hdc = GetDC(0);
908  header.dwObjectExtentX = MulDiv(bmi->bmiHeader.biWidth, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
909  header.dwObjectExtentY = MulDiv(bmi->bmiHeader.biHeight, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
910  ReleaseDC(0, hdc);
911  }
912  }
913  hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
914  if (hr == S_OK && data_size)
915  hr = IStream_Write(stream, bmi, data_size, NULL);
916  }
917  else if(data_size)
918  {
919  BITMAPFILEHEADER bmp_fhdr;
920 
921  bmp_fhdr.bfType = 0x4d42;
922  bmp_fhdr.bfSize = data_size + sizeof(BITMAPFILEHEADER);
923  bmp_fhdr.bfReserved1 = bmp_fhdr.bfReserved2 = 0;
924  bmp_fhdr.bfOffBits = bitmap_info_size(bmi, DIB_RGB_COLORS) + sizeof(BITMAPFILEHEADER);
925  hr = IStream_Write(stream, &bmp_fhdr, sizeof(BITMAPFILEHEADER), NULL);
926  if (hr == S_OK)
927  hr = IStream_Write(stream, bmi, data_size, NULL);
928  }
929 
930 end:
931  if (bmi) GlobalUnlock(entry->stgmedium.u.hGlobal);
932  return hr;
933 }
934 
936 {
937  HRESULT hr = S_OK;
938  int data_size = 0;
939  void *data = NULL;
940  METAFILEPICT *mfpict = NULL;
941 
942  if (!contents)
943  {
945 
947  hr = write_clipformat(stream, entry->fmtetc.cfFormat);
948  if (FAILED(hr)) return hr;
949  if (entry->stgmedium.tymed != TYMED_NULL)
950  {
951  mfpict = GlobalLock(entry->stgmedium.u.hMetaFilePict);
952  if (!mfpict)
953  return DV_E_STGMEDIUM;
954  data_size = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
955  header.dwObjectExtentX = mfpict->xExt;
956  header.dwObjectExtentY = mfpict->yExt;
957  header.dwSize = data_size;
958  data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
959  if (!data)
960  {
961  GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
962  return E_OUTOFMEMORY;
963  }
964  GetMetaFileBitsEx(mfpict->hMF, header.dwSize, data);
965  GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
966  }
967  hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
968  if (hr == S_OK && data_size)
969  hr = IStream_Write(stream, data, data_size, NULL);
971  }
972  else if (entry->stgmedium.tymed != TYMED_NULL)
973  {
974  struct meta_placeable meta_place_rec;
975  WORD *check;
976 
977  mfpict = GlobalLock(entry->stgmedium.u.hMetaFilePict);
978  if (!mfpict)
979  return DV_E_STGMEDIUM;
980  data_size = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
981  data = HeapAlloc(GetProcessHeap(), 0, data_size);
982  if (!data)
983  {
984  GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
985  return E_OUTOFMEMORY;
986  }
987  GetMetaFileBitsEx(mfpict->hMF, data_size, data);
988 
989  /* units are in 1/8th of a point (1 point is 1/72th of an inch) */
990  meta_place_rec.key = 0x9ac6cdd7;
991  meta_place_rec.hwmf = 0;
992  meta_place_rec.inch = 576;
993  meta_place_rec.bounding_box[0] = 0;
994  meta_place_rec.bounding_box[1] = 0;
995  meta_place_rec.bounding_box[2] = 0;
996  meta_place_rec.bounding_box[3] = 0;
997  meta_place_rec.checksum = 0;
998  meta_place_rec.reserved = 0;
999 
1000  /* These values are rounded down so MulDiv won't do the right thing */
1001  meta_place_rec.bounding_box[2] = (LONGLONG)mfpict->xExt * meta_place_rec.inch / 2540;
1002  meta_place_rec.bounding_box[3] = (LONGLONG)mfpict->yExt * meta_place_rec.inch / 2540;
1003  GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
1004 
1005  for (check = (WORD *)&meta_place_rec; check != &meta_place_rec.checksum; check++)
1006  meta_place_rec.checksum ^= *check;
1007  hr = IStream_Write(stream, &meta_place_rec, sizeof(struct meta_placeable), NULL);
1008  if (hr == S_OK && data_size)
1009  hr = IStream_Write(stream, data, data_size, NULL);
1010  HeapFree(GetProcessHeap(), 0, data);
1011  }
1012 
1013  return hr;
1014 }
1015 
1017 {
1018  HRESULT hr = S_OK;
1019  int data_size = 0;
1020  BYTE *data;
1021 
1022  if (!contents)
1023  {
1025  METAFILEPICT *mfpict;
1026  HDC hdc = GetDC(0);
1027 
1029  hr = write_clipformat(stream, entry->fmtetc.cfFormat);
1030  if (FAILED(hr))
1031  {
1032  ReleaseDC(0, hdc);
1033  return hr;
1034  }
1035  data_size = GetWinMetaFileBits(entry->stgmedium.u.hEnhMetaFile, 0, NULL, MM_ANISOTROPIC, hdc);
1036  header.dwSize = data_size;
1037  data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
1038  if (!data)
1039  {
1040  ReleaseDC(0, hdc);
1041  return E_OUTOFMEMORY;
1042  }
1043  GetWinMetaFileBits(entry->stgmedium.u.hEnhMetaFile, header.dwSize, data, MM_ANISOTROPIC, hdc);
1044  ReleaseDC(0, hdc);
1045  mfpict = (METAFILEPICT *)data;
1046  header.dwObjectExtentX = mfpict->xExt;
1047  header.dwObjectExtentY = mfpict->yExt;
1048  hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
1049  if (hr == S_OK && data_size)
1050  hr = IStream_Write(stream, data, data_size, NULL);
1051  HeapFree(GetProcessHeap(), 0, data);
1052  }
1053  else if (entry->stgmedium.tymed != TYMED_NULL)
1054  {
1055  data_size = GetEnhMetaFileBits(entry->stgmedium.u.hEnhMetaFile, 0, NULL);
1056  data = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) + sizeof(ENHMETAHEADER) + data_size);
1057  if (!data) return E_OUTOFMEMORY;
1058  *((DWORD *)data) = sizeof(ENHMETAHEADER);
1059  GetEnhMetaFileBits(entry->stgmedium.u.hEnhMetaFile, data_size, data + sizeof(DWORD) + sizeof(ENHMETAHEADER));
1060  memcpy(data + sizeof(DWORD), data + sizeof(DWORD) + sizeof(ENHMETAHEADER), sizeof(ENHMETAHEADER));
1061  data_size += sizeof(DWORD) + sizeof(ENHMETAHEADER);
1062  hr = IStream_Write(stream, data, data_size, NULL);
1063  HeapFree(GetProcessHeap(), 0, data);
1064  }
1065 
1066  return hr;
1067 }
1068 
1070 {
1071  HRESULT hr;
1073 
1075  hr = write_clipformat(stream, entry->fmtetc.cfFormat);
1076  if (SUCCEEDED(hr))
1077  hr = IStream_Write(stream, &header, FIELD_OFFSET(PresentationDataHeader, unknown7), NULL);
1078 
1079  return hr;
1080 }
1081 
1083  BOOL contents, IStream **stream)
1084 {
1085  WCHAR pres[] = {2,'O','l','e','P','r','e','s',
1086  '0' + (cache_entry->save_stream_num / 100) % 10,
1087  '0' + (cache_entry->save_stream_num / 10) % 10,
1088  '0' + cache_entry->save_stream_num % 10, 0};
1089  const WCHAR *name;
1090 
1091  if (contents)
1092  name = CONTENTS;
1093  else
1094  name = pres;
1095 
1096  return IStorage_CreateStream(storage, name,
1098  0, 0, stream);
1099 }
1100 
1102  BOOL same_as_load)
1103 {
1104  HRESULT hr;
1105  IStream *stream;
1106  BOOL contents = (cache_entry->id == 1);
1107 
1108  TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->save_stream_num, debugstr_formatetc(&cache_entry->fmtetc));
1109 
1110  hr = create_stream(cache_entry, storage, contents, &stream);
1111  if (FAILED(hr))
1112  return hr;
1113 
1114  switch (cache_entry->fmtetc.cfFormat)
1115  {
1116  case CF_DIB:
1117  hr = save_dib(cache_entry, contents, stream);
1118  break;
1119  case CF_METAFILEPICT:
1120  hr = save_mfpict(cache_entry, contents, stream);
1121  break;
1122  case CF_ENHMETAFILE:
1123  hr = save_emf(cache_entry, contents, stream);
1124  break;
1125  case 0:
1127  break;
1128  default:
1129  FIXME("got unsupported clipboard format %x\n", cache_entry->fmtetc.cfFormat);
1130  }
1131 
1132  IStream_Release(stream);
1133  return hr;
1134 }
1135 
1136 /* helper for copying STGMEDIUM of type bitmap, MF, EMF or HGLOBAL.
1137 * does no checking of whether src_stgm has a supported tymed, so this should be
1138 * done in the caller */
1139 static HRESULT copy_stg_medium(CLIPFORMAT cf, STGMEDIUM *dest_stgm,
1140  const STGMEDIUM *src_stgm)
1141 {
1142  if (src_stgm->tymed == TYMED_MFPICT)
1143  {
1144  const METAFILEPICT *src_mfpict = GlobalLock(src_stgm->u.hMetaFilePict);
1145  METAFILEPICT *dest_mfpict;
1146 
1147  if (!src_mfpict)
1148  return DV_E_STGMEDIUM;
1149  dest_stgm->u.hMetaFilePict = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
1150  dest_mfpict = GlobalLock(dest_stgm->u.hMetaFilePict);
1151  if (!dest_mfpict)
1152  {
1153  GlobalUnlock(src_stgm->u.hMetaFilePict);
1154  return E_OUTOFMEMORY;
1155  }
1156  *dest_mfpict = *src_mfpict;
1157  dest_mfpict->hMF = CopyMetaFileW(src_mfpict->hMF, NULL);
1158  GlobalUnlock(src_stgm->u.hMetaFilePict);
1159  GlobalUnlock(dest_stgm->u.hMetaFilePict);
1160  }
1161  else if (src_stgm->tymed != TYMED_NULL)
1162  {
1163  dest_stgm->u.hGlobal = OleDuplicateData(src_stgm->u.hGlobal, cf,
1164  GMEM_MOVEABLE);
1165  if (!dest_stgm->u.hGlobal)
1166  return E_OUTOFMEMORY;
1167  }
1168  dest_stgm->tymed = src_stgm->tymed;
1169  dest_stgm->pUnkForRelease = src_stgm->pUnkForRelease;
1170  if (dest_stgm->pUnkForRelease)
1171  IUnknown_AddRef(dest_stgm->pUnkForRelease);
1172  return S_OK;
1173 }
1174 
1175 static HRESULT synthesize_dib( HBITMAP bm, STGMEDIUM *med )
1176 {
1177  HDC hdc = GetDC( 0 );
1179  BITMAPINFO *bmi;
1180  HRESULT hr = E_FAIL;
1181  DWORD header_size;
1182 
1183  memset( &header, 0, sizeof(header) );
1184  header.biSize = sizeof(header);
1185  if (!GetDIBits( hdc, bm, 0, 0, NULL, (BITMAPINFO *)&header, DIB_RGB_COLORS )) goto done;
1186 
1187  header_size = bitmap_info_size( (BITMAPINFO *)&header, DIB_RGB_COLORS );
1188  if (!(med->u.hGlobal = GlobalAlloc( GMEM_MOVEABLE, header_size + header.biSizeImage ))) goto done;
1189  bmi = GlobalLock( med->u.hGlobal );
1190  memset( bmi, 0, header_size );
1191  memcpy( bmi, &header, header.biSize );
1192  GetDIBits( hdc, bm, 0, abs(header.biHeight), (char *)bmi + header_size, bmi, DIB_RGB_COLORS );
1193  GlobalUnlock( med->u.hGlobal );
1194  med->tymed = TYMED_HGLOBAL;
1195  med->pUnkForRelease = NULL;
1196  hr = S_OK;
1197 
1198 done:
1199  ReleaseDC( 0, hdc );
1200  return hr;
1201 }
1202 
1203 static HRESULT synthesize_bitmap( HGLOBAL dib, STGMEDIUM *med )
1204 {
1205  HRESULT hr = E_FAIL;
1206  BITMAPINFO *bmi;
1207  HDC hdc = GetDC( 0 );
1208 
1209  if ((bmi = GlobalLock( dib )))
1210  {
1211  /* FIXME: validate data size */
1212  med->u.hBitmap = CreateDIBitmap( hdc, &bmi->bmiHeader, CBM_INIT,
1213  (char *)bmi + bitmap_info_size( bmi, DIB_RGB_COLORS ),
1214  bmi, DIB_RGB_COLORS );
1215  GlobalUnlock( dib );
1216  med->tymed = TYMED_GDI;
1217  med->pUnkForRelease = NULL;
1218  hr = S_OK;
1219  }
1220  ReleaseDC( 0, hdc );
1221  return hr;
1222 }
1223 
1225  const FORMATETC *formatetc,
1226  STGMEDIUM *stgmedium,
1227  BOOL fRelease)
1228 {
1229  STGMEDIUM copy;
1230  HRESULT hr;
1231 
1232  if ((!cache_entry->fmtetc.cfFormat && !formatetc->cfFormat) ||
1233  (cache_entry->fmtetc.tymed == TYMED_NULL && formatetc->tymed == TYMED_NULL) ||
1234  stgmedium->tymed == TYMED_NULL)
1235  {
1236  WARN("invalid formatetc\n");
1237  return DV_E_FORMATETC;
1238  }
1239 
1240  cache_entry->dirty = TRUE;
1241  ReleaseStgMedium(&cache_entry->stgmedium);
1242 
1243  if (formatetc->cfFormat == CF_BITMAP)
1244  {
1245  hr = synthesize_dib( stgmedium->u.hBitmap, &copy );
1246  if (FAILED(hr)) return hr;
1247  if (fRelease) ReleaseStgMedium(stgmedium);
1248  stgmedium = &copy;
1249  fRelease = TRUE;
1250  }
1251  else if (formatetc->cfFormat == CF_METAFILEPICT && cache_entry->fmtetc.cfFormat == CF_ENHMETAFILE)
1252  {
1253  hr = synthesize_emf( stgmedium->u.hMetaFilePict, &copy );
1254  if (FAILED(hr)) return hr;
1255  if (fRelease) ReleaseStgMedium(stgmedium);
1256  stgmedium = &copy;
1257  fRelease = TRUE;
1258  }
1259 
1260  if (fRelease)
1261  {
1262  cache_entry->stgmedium = *stgmedium;
1263  return S_OK;
1264  }
1265  else
1266  return copy_stg_medium(cache_entry->fmtetc.cfFormat, &cache_entry->stgmedium, stgmedium);
1267 }
1268 
1269 static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, IStorage *stg, FORMATETC *fmt, STGMEDIUM *stgmedium)
1270 {
1271  if (cache_entry->stgmedium.tymed == TYMED_NULL && cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET)
1272  {
1274  if (FAILED(hr))
1275  return hr;
1276  }
1277  if (cache_entry->stgmedium.tymed == TYMED_NULL)
1278  return OLE_E_BLANK;
1279 
1280  if (fmt->cfFormat == CF_BITMAP)
1281  return synthesize_bitmap( cache_entry->stgmedium.u.hGlobal, stgmedium );
1282 
1283  return copy_stg_medium(cache_entry->fmtetc.cfFormat, stgmedium, &cache_entry->stgmedium);
1284 }
1285 
1287 {
1288  ReleaseStgMedium(&cache_entry->stgmedium);
1289  return S_OK;
1290 }
1291 
1292 static inline DWORD tymed_from_cf( DWORD cf )
1293 {
1294  switch( cf )
1295  {
1296  case CF_BITMAP: return TYMED_GDI;
1297  case CF_METAFILEPICT: return TYMED_MFPICT;
1298  case CF_ENHMETAFILE: return TYMED_ENHMF;
1299  case CF_DIB:
1300  default: return TYMED_HGLOBAL;
1301  }
1302 }
1303 
1304 /****************************************************************
1305  * create_automatic_entry
1306  *
1307  * Creates an appropriate cache entry for one of the CLSID_Picture_
1308  * classes. The connection id of the entry is one. Any pre-existing
1309  * automatic entry is re-assigned a new connection id, and moved to
1310  * the end of the list.
1311  */
1313 {
1314  static const struct data
1315  {
1316  const CLSID *clsid;
1317  FORMATETC fmt;
1318  } data[] =
1319  {
1320  { &CLSID_Picture_Dib, { CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } },
1321  { &CLSID_Picture_Metafile, { CF_METAFILEPICT, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT } },
1322  { &CLSID_Picture_EnhMetafile, { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF } },
1323  { NULL }
1324  };
1325  const struct data *ptr = data;
1326  struct list *head;
1328 
1329  if (IsEqualCLSID( &cache->clsid, clsid )) return S_OK;
1330 
1331  /* move and reassign any pre-existing automatic entry */
1332  if ((head = list_head( &cache->cache_list )))
1333  {
1335  if (entry->id == 1)
1336  {
1337  list_remove( &entry->entry );
1338  entry->id = cache->last_cache_id++;
1339  list_add_tail( &cache->cache_list, &entry->entry );
1340  }
1341  }
1342 
1343  while (ptr->clsid)
1344  {
1345  if (IsEqualCLSID( clsid, ptr->clsid ))
1346  {
1347  cache->clsid_static = TRUE;
1348  return DataCache_CreateEntry( cache, &ptr->fmt, 0, TRUE, NULL );
1349  }
1350  ptr++;
1351  }
1352  cache->clsid_static = FALSE;
1353  return S_OK;
1354 }
1355 
1356 /*********************************************************
1357  * Method implementation for the non delegating IUnknown
1358  * part of the DataCache class.
1359  */
1360 
1361 /************************************************************************
1362  * DataCache_NDIUnknown_QueryInterface (IUnknown)
1363  *
1364  * This version of QueryInterface will not delegate its implementation
1365  * to the outer unknown.
1366  */
1368  IUnknown* iface,
1369  REFIID riid,
1370  void** ppvObject)
1371 {
1372  DataCache *this = impl_from_IUnknown(iface);
1373 
1374  if ( ppvObject==0 )
1375  return E_INVALIDARG;
1376 
1377  *ppvObject = 0;
1378 
1379  if (IsEqualIID(&IID_IUnknown, riid))
1380  {
1381  if (this->outer_unk == iface) /* non-aggregated, return IUnknown from IOleCache2 */
1382  *ppvObject = &this->IOleCache2_iface;
1383  else
1384  *ppvObject = iface;
1385  }
1386  else if (IsEqualIID(&IID_IDataObject, riid))
1387  {
1388  *ppvObject = &this->IDataObject_iface;
1389  }
1390  else if ( IsEqualIID(&IID_IPersistStorage, riid) ||
1392  {
1393  *ppvObject = &this->IPersistStorage_iface;
1394  }
1395  else if ( IsEqualIID(&IID_IViewObject, riid) ||
1397  {
1398  *ppvObject = &this->IViewObject2_iface;
1399  }
1400  else if ( IsEqualIID(&IID_IOleCache, riid) ||
1402  {
1403  *ppvObject = &this->IOleCache2_iface;
1404  }
1405  else if ( IsEqualIID(&IID_IOleCacheControl, riid) )
1406  {
1407  *ppvObject = &this->IOleCacheControl_iface;
1408  }
1409 
1410  if ((*ppvObject)==0)
1411  {
1412  WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
1413  return E_NOINTERFACE;
1414  }
1415 
1416  IUnknown_AddRef((IUnknown*)*ppvObject);
1417 
1418  return S_OK;
1419 }
1420 
1421 /************************************************************************
1422  * DataCache_NDIUnknown_AddRef (IUnknown)
1423  *
1424  * This version of QueryInterface will not delegate its implementation
1425  * to the outer unknown.
1426  */
1428  IUnknown* iface)
1429 {
1430  DataCache *this = impl_from_IUnknown(iface);
1431  return InterlockedIncrement(&this->ref);
1432 }
1433 
1434 /************************************************************************
1435  * DataCache_NDIUnknown_Release (IUnknown)
1436  *
1437  * This version of QueryInterface will not delegate its implementation
1438  * to the outer unknown.
1439  */
1441  IUnknown* iface)
1442 {
1443  DataCache *this = impl_from_IUnknown(iface);
1444  ULONG ref;
1445 
1446  ref = InterlockedDecrement(&this->ref);
1447 
1448  if (ref == 0) DataCache_Destroy(this);
1449 
1450  return ref;
1451 }
1452 
1453 /*********************************************************
1454  * Method implementation for the IDataObject
1455  * part of the DataCache class.
1456  */
1457 
1458 /************************************************************************
1459  * DataCache_IDataObject_QueryInterface (IUnknown)
1460  */
1462  IDataObject* iface,
1463  REFIID riid,
1464  void** ppvObject)
1465 {
1466  DataCache *this = impl_from_IDataObject(iface);
1467 
1468  return IUnknown_QueryInterface(this->outer_unk, riid, ppvObject);
1469 }
1470 
1471 /************************************************************************
1472  * DataCache_IDataObject_AddRef (IUnknown)
1473  */
1475  IDataObject* iface)
1476 {
1477  DataCache *this = impl_from_IDataObject(iface);
1478 
1479  return IUnknown_AddRef(this->outer_unk);
1480 }
1481 
1482 /************************************************************************
1483  * DataCache_IDataObject_Release (IUnknown)
1484  */
1486  IDataObject* iface)
1487 {
1488  DataCache *this = impl_from_IDataObject(iface);
1489 
1490  return IUnknown_Release(this->outer_unk);
1491 }
1492 
1493 /************************************************************************
1494  * DataCache_GetData
1495  *
1496  * Get Data from a source dataobject using format pformatetcIn->cfFormat
1497  */
1499  IDataObject* iface,
1500  LPFORMATETC pformatetcIn,
1501  STGMEDIUM* pmedium)
1502 {
1505 
1506  TRACE("(%p, %s, %p)\n", iface, debugstr_formatetc(pformatetcIn), pmedium);
1507 
1508  memset(pmedium, 0, sizeof(*pmedium));
1509 
1511  if (!cache_entry)
1512  return OLE_E_BLANK;
1513 
1514  return DataCacheEntry_GetData(cache_entry, This->presentationStorage, pformatetcIn, pmedium);
1515 }
1516 
1518  IDataObject* iface,
1519  LPFORMATETC pformatetc,
1520  STGMEDIUM* pmedium)
1521 {
1522  FIXME("stub\n");
1523  return E_NOTIMPL;
1524 }
1525 
1527 {
1528  DataCache *This = impl_from_IDataObject( iface );
1530 
1531  TRACE( "(%p)->(%s)\n", iface, debugstr_formatetc( fmt ) );
1533 
1534  return cache_entry ? S_OK : S_FALSE;
1535 }
1536 
1537 /************************************************************************
1538  * DataCache_EnumFormatEtc (IDataObject)
1539  *
1540  * The data cache doesn't implement this method.
1541  */
1543  IDataObject* iface,
1544  LPFORMATETC pformatectIn,
1545  LPFORMATETC pformatetcOut)
1546 {
1547  TRACE("()\n");
1548  return E_NOTIMPL;
1549 }
1550 
1551 /************************************************************************
1552  * DataCache_IDataObject_SetData (IDataObject)
1553  *
1554  * This method is delegated to the IOleCache2 implementation.
1555  */
1557  IDataObject* iface,
1558  LPFORMATETC pformatetc,
1559  STGMEDIUM* pmedium,
1560  BOOL fRelease)
1561 {
1562  IOleCache2* oleCache = NULL;
1563  HRESULT hres;
1564 
1565  TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1566 
1567  hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1568 
1569  if (FAILED(hres))
1570  return E_UNEXPECTED;
1571 
1572  hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1573 
1574  IOleCache2_Release(oleCache);
1575 
1576  return hres;
1577 }
1578 
1579 /************************************************************************
1580  * DataCache_EnumFormatEtc (IDataObject)
1581  *
1582  * The data cache doesn't implement this method.
1583  */
1585  IDataObject* iface,
1586  DWORD dwDirection,
1587  IEnumFORMATETC** ppenumFormatEtc)
1588 {
1589  TRACE("()\n");
1590  return E_NOTIMPL;
1591 }
1592 
1593 /************************************************************************
1594  * DataCache_DAdvise (IDataObject)
1595  *
1596  * The data cache doesn't support connections.
1597  */
1599  IDataObject* iface,
1600  FORMATETC* pformatetc,
1601  DWORD advf,
1602  IAdviseSink* pAdvSink,
1603  DWORD* pdwConnection)
1604 {
1605  TRACE("()\n");
1606  return OLE_E_ADVISENOTSUPPORTED;
1607 }
1608 
1609 /************************************************************************
1610  * DataCache_DUnadvise (IDataObject)
1611  *
1612  * The data cache doesn't support connections.
1613  */
1615  IDataObject* iface,
1616  DWORD dwConnection)
1617 {
1618  TRACE("()\n");
1619  return OLE_E_NOCONNECTION;
1620 }
1621 
1622 /************************************************************************
1623  * DataCache_EnumDAdvise (IDataObject)
1624  *
1625  * The data cache doesn't support connections.
1626  */
1628  IDataObject* iface,
1629  IEnumSTATDATA** ppenumAdvise)
1630 {
1631  TRACE("()\n");
1632  return OLE_E_ADVISENOTSUPPORTED;
1633 }
1634 
1635 /*********************************************************
1636  * Method implementation for the IDataObject
1637  * part of the DataCache class.
1638  */
1639 
1640 /************************************************************************
1641  * DataCache_IPersistStorage_QueryInterface (IUnknown)
1642  */
1644  IPersistStorage* iface,
1645  REFIID riid,
1646  void** ppvObject)
1647 {
1648  DataCache *this = impl_from_IPersistStorage(iface);
1649 
1650  return IUnknown_QueryInterface(this->outer_unk, riid, ppvObject);
1651 }
1652 
1653 /************************************************************************
1654  * DataCache_IPersistStorage_AddRef (IUnknown)
1655  */
1657  IPersistStorage* iface)
1658 {
1659  DataCache *this = impl_from_IPersistStorage(iface);
1660 
1661  return IUnknown_AddRef(this->outer_unk);
1662 }
1663 
1664 /************************************************************************
1665  * DataCache_IPersistStorage_Release (IUnknown)
1666  */
1668  IPersistStorage* iface)
1669 {
1670  DataCache *this = impl_from_IPersistStorage(iface);
1671 
1672  return IUnknown_Release(this->outer_unk);
1673 }
1674 
1675 /************************************************************************
1676  * DataCache_GetClassID (IPersistStorage)
1677  *
1678  */
1680 {
1682 
1683  TRACE( "(%p, %p) returning %s\n", iface, clsid, debugstr_guid(&This->clsid) );
1684  *clsid = This->clsid;
1685 
1686  return S_OK;
1687 }
1688 
1689 /************************************************************************
1690  * DataCache_IsDirty (IPersistStorage)
1691  */
1693  IPersistStorage* iface)
1694 {
1697 
1698  TRACE("(%p)\n", iface);
1699 
1700  if (This->dirty)
1701  return S_OK;
1702 
1704  if (cache_entry->dirty)
1705  return S_OK;
1706 
1707  return S_FALSE;
1708 }
1709 
1710 /************************************************************************
1711  * DataCache_InitNew (IPersistStorage)
1712  *
1713  * The data cache implementation of IPersistStorage_InitNew simply stores
1714  * the storage pointer.
1715  */
1717  IPersistStorage* iface,
1718  IStorage* pStg)
1719 {
1721  CLSID clsid;
1722  HRESULT hr;
1723 
1724  TRACE("(%p, %p)\n", iface, pStg);
1725 
1726  if (This->presentationStorage != NULL)
1727  return CO_E_ALREADYINITIALIZED;
1728 
1729  This->presentationStorage = pStg;
1730 
1731  IStorage_AddRef(This->presentationStorage);
1732  This->dirty = TRUE;
1733  ReadClassStg( pStg, &clsid );
1735  if (FAILED(hr))
1736  {
1737  IStorage_Release( pStg );
1738  This->presentationStorage = NULL;
1739  return hr;
1740  }
1741  This->clsid = clsid;
1742 
1743  return S_OK;
1744 }
1745 
1746 
1747 static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, DWORD advf, int stream_number )
1748 {
1750  HRESULT hr = S_OK;
1751 
1752  TRACE( "loading entry with formatetc: %s\n", debugstr_formatetc( fmt ) );
1753 
1755  if (!cache_entry)
1757  if (SUCCEEDED( hr ))
1758  {
1760  cache_entry->load_stream_num = stream_number;
1761  cache_entry->save_stream_num = stream_number;
1762  cache_entry->dirty = FALSE;
1763  }
1764  return hr;
1765 }
1766 
1768 {
1769  HRESULT hr;
1770  IStream *stm;
1772  ULONG actual_read;
1773  CLIPFORMAT clipformat;
1774  FORMATETC fmtetc;
1775  int stream_number = 0;
1776 
1777  do
1778  {
1779  hr = open_pres_stream( stg, stream_number, &stm );
1780  if (FAILED(hr)) break;
1781 
1782  hr = read_clipformat( stm, &clipformat );
1783 
1784  if (hr == S_OK) hr = IStream_Read( stm, &header, sizeof(header), &actual_read );
1785 
1786  if (hr == S_OK && actual_read == sizeof(header))
1787  {
1788  fmtetc.cfFormat = clipformat;
1789  fmtetc.ptd = NULL; /* FIXME */
1790  fmtetc.dwAspect = header.dvAspect;
1791  fmtetc.lindex = header.lindex;
1792  fmtetc.tymed = tymed_from_cf( clipformat );
1793 
1794  add_cache_entry( cache, &fmtetc, header.advf, stream_number );
1795  }
1796  IStream_Release( stm );
1797  stream_number++;
1798  } while (hr == S_OK);
1799 
1800  return S_OK;
1801 }
1802 
1804 {
1805  HRESULT hr;
1806  IStream *stm;
1808 
1809  hr = open_pres_stream( stg, STREAM_NUMBER_CONTENTS, &stm );
1810  if (FAILED( hr )) return hr;
1811 
1813  if (hr == S_OK)
1814  {
1815  cache_entry->load_stream_num = STREAM_NUMBER_CONTENTS;
1816  cache_entry->save_stream_num = STREAM_NUMBER_CONTENTS;
1817  cache_entry->dirty = FALSE;
1818  }
1819 
1820  IStream_Release( stm );
1821  return hr;
1822 }
1823 
1824 /************************************************************************
1825  * DataCache_Load (IPersistStorage)
1826  *
1827  * The data cache implementation of IPersistStorage_Load doesn't
1828  * actually load anything. Instead, it holds on to the storage pointer
1829  * and it will load the presentation information when the
1830  * IDataObject_GetData or IViewObject2_Draw methods are called.
1831  */
1833 {
1835  HRESULT hr;
1836  CLSID clsid;
1837  DataCacheEntry *entry, *cursor2;
1838 
1839  TRACE("(%p, %p)\n", iface, stg);
1840 
1841  IPersistStorage_HandsOffStorage( iface );
1842 
1843  LIST_FOR_EACH_ENTRY_SAFE( entry, cursor2, &This->cache_list, DataCacheEntry, entry )
1845  This->clsid = CLSID_NULL;
1846 
1847  ReadClassStg( stg, &clsid );
1849  if (FAILED( hr )) return hr;
1850 
1851  This->clsid = clsid;
1852 
1853  if (This->clsid_static)
1854  {
1855  hr = parse_contents_stream( This, stg );
1856  if (FAILED(hr)) hr = parse_pres_streams( This, stg );
1857  }
1858  else
1859  hr = parse_pres_streams( This, stg );
1860 
1861  if (SUCCEEDED( hr ))
1862  {
1863  This->dirty = FALSE;
1864  This->presentationStorage = stg;
1865  IStorage_AddRef( This->presentationStorage );
1866  }
1867 
1868  return hr;
1869 }
1870 
1871 /************************************************************************
1872  * DataCache_Save (IPersistStorage)
1873  *
1874  * Until we actually connect to a running object and retrieve new
1875  * information to it, we never have to save anything. However, it is
1876  * our responsibility to copy the information when saving to a new
1877  * storage.
1878  */
1879 static HRESULT WINAPI DataCache_Save(IPersistStorage* iface, IStorage *stg, BOOL same_as_load)
1880 {
1883  HRESULT hr = S_OK;
1884  int stream_number = 0;
1885 
1886  TRACE("(%p, %p, %d)\n", iface, stg, same_as_load);
1887 
1888  /* assign stream numbers to the cache entries */
1890  {
1891  if (cache_entry->save_stream_num != stream_number)
1892  {
1893  cache_entry->dirty = TRUE; /* needs to be written out again */
1894  cache_entry->save_stream_num = stream_number;
1895  }
1896  stream_number++;
1897  }
1898 
1899  /* write out the cache entries */
1901  {
1902  if (!same_as_load || cache_entry->dirty)
1903  {
1904  hr = DataCacheEntry_Save(cache_entry, stg, same_as_load);
1905  if (FAILED(hr))
1906  break;
1907 
1908  if (same_as_load) cache_entry->dirty = FALSE;
1909  }
1910  }
1911 
1912  if (same_as_load) This->dirty = FALSE;
1913  return hr;
1914 }
1915 
1916 /************************************************************************
1917  * DataCache_SaveCompleted (IPersistStorage)
1918  *
1919  * This method is called to tell the cache to release the storage
1920  * pointer it's currently holding.
1921  */
1923  IPersistStorage* iface,
1924  IStorage* pStgNew)
1925 {
1926  TRACE("(%p, %p)\n", iface, pStgNew);
1927 
1928  if (pStgNew)
1929  {
1930  IPersistStorage_HandsOffStorage(iface);
1931 
1932  DataCache_Load(iface, pStgNew);
1933  }
1934 
1935  return S_OK;
1936 }
1937 
1938 /************************************************************************
1939  * DataCache_HandsOffStorage (IPersistStorage)
1940  *
1941  * This method is called to tell the cache to release the storage
1942  * pointer it's currently holding.
1943  */
1945  IPersistStorage* iface)
1946 {
1947  DataCache *this = impl_from_IPersistStorage(iface);
1948 
1949  TRACE("(%p)\n", iface);
1950 
1951  if (this->presentationStorage != NULL)
1952  {
1953  IStorage_Release(this->presentationStorage);
1954  this->presentationStorage = NULL;
1955  }
1956 
1957  return S_OK;
1958 }
1959 
1960 /*********************************************************
1961  * Method implementation for the IViewObject2
1962  * part of the DataCache class.
1963  */
1964 
1965 /************************************************************************
1966  * DataCache_IViewObject2_QueryInterface (IUnknown)
1967  */
1969  IViewObject2* iface,
1970  REFIID riid,
1971  void** ppvObject)
1972 {
1973  DataCache *this = impl_from_IViewObject2(iface);
1974 
1975  return IUnknown_QueryInterface(this->outer_unk, riid, ppvObject);
1976 }
1977 
1978 /************************************************************************
1979  * DataCache_IViewObject2_AddRef (IUnknown)
1980  */
1982  IViewObject2* iface)
1983 {
1984  DataCache *this = impl_from_IViewObject2(iface);
1985 
1986  return IUnknown_AddRef(this->outer_unk);
1987 }
1988 
1989 /************************************************************************
1990  * DataCache_IViewObject2_Release (IUnknown)
1991  */
1993  IViewObject2* iface)
1994 {
1995  DataCache *this = impl_from_IViewObject2(iface);
1996 
1997  return IUnknown_Release(this->outer_unk);
1998 }
1999 
2000 /************************************************************************
2001  * DataCache_Draw (IViewObject2)
2002  *
2003  * This method will draw the cached representation of the object
2004  * to the given device context.
2005  */
2007  IViewObject2* iface,
2008  DWORD dwDrawAspect,
2009  LONG lindex,
2010  void* pvAspect,
2011  DVTARGETDEVICE* ptd,
2012  HDC hdcTargetDev,
2013  HDC hdcDraw,
2014  LPCRECTL lprcBounds,
2015  LPCRECTL lprcWBounds,
2016  BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2017  ULONG_PTR dwContinue)
2018 {
2020  HRESULT hres;
2022 
2023  TRACE("(%p, %x, %d, %p, %p, %p, %p, %p, %p, %lx)\n",
2024  iface,
2025  dwDrawAspect,
2026  lindex,
2027  pvAspect,
2028  hdcTargetDev,
2029  hdcDraw,
2030  lprcBounds,
2031  lprcWBounds,
2032  pfnContinue,
2033  dwContinue);
2034 
2035  if (lprcBounds==NULL)
2036  return E_INVALIDARG;
2037 
2039  {
2040  /* FIXME: compare ptd too */
2041  if ((cache_entry->fmtetc.dwAspect != dwDrawAspect) ||
2042  (cache_entry->fmtetc.lindex != lindex))
2043  continue;
2044 
2045  /* if the data hasn't been loaded yet, do it now */
2046  if ((cache_entry->stgmedium.tymed == TYMED_NULL) && (cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET))
2047  {
2048  hres = DataCacheEntry_LoadData(cache_entry, This->presentationStorage);
2049  if (FAILED(hres))
2050  continue;
2051  }
2052 
2053  /* no data */
2054  if (cache_entry->stgmedium.tymed == TYMED_NULL)
2055  continue;
2056 
2057  if (pfnContinue && !pfnContinue(dwContinue)) return E_ABORT;
2058 
2059  switch (cache_entry->fmtetc.cfFormat)
2060  {
2061  case CF_METAFILEPICT:
2062  {
2063  /*
2064  * We have to be careful not to modify the state of the
2065  * DC.
2066  */
2067  INT prevMapMode;
2068  SIZE oldWindowExt;
2069  SIZE oldViewportExt;
2070  POINT oldViewportOrg;
2071  METAFILEPICT *mfpict;
2072 
2073  if ((cache_entry->stgmedium.tymed != TYMED_MFPICT) ||
2074  !((mfpict = GlobalLock(cache_entry->stgmedium.u.hMetaFilePict))))
2075  continue;
2076 
2077  prevMapMode = SetMapMode(hdcDraw, mfpict->mm);
2078 
2079  SetWindowExtEx(hdcDraw,
2080  mfpict->xExt,
2081  mfpict->yExt,
2082  &oldWindowExt);
2083 
2084  SetViewportExtEx(hdcDraw,
2085  lprcBounds->right - lprcBounds->left,
2086  lprcBounds->bottom - lprcBounds->top,
2087  &oldViewportExt);
2088 
2089  SetViewportOrgEx(hdcDraw,
2090  lprcBounds->left,
2091  lprcBounds->top,
2092  &oldViewportOrg);
2093 
2094  PlayMetaFile(hdcDraw, mfpict->hMF);
2095 
2096  SetWindowExtEx(hdcDraw,
2097  oldWindowExt.cx,
2098  oldWindowExt.cy,
2099  NULL);
2100 
2101  SetViewportExtEx(hdcDraw,
2102  oldViewportExt.cx,
2103  oldViewportExt.cy,
2104  NULL);
2105 
2106  SetViewportOrgEx(hdcDraw,
2107  oldViewportOrg.x,
2108  oldViewportOrg.y,
2109  NULL);
2110 
2111  SetMapMode(hdcDraw, prevMapMode);
2112 
2113  GlobalUnlock(cache_entry->stgmedium.u.hMetaFilePict);
2114 
2115  return S_OK;
2116  }
2117  case CF_DIB:
2118  {
2119  BITMAPINFO *info;
2120  BYTE *bits;
2121 
2122  if ((cache_entry->stgmedium.tymed != TYMED_HGLOBAL) ||
2123  !((info = GlobalLock( cache_entry->stgmedium.u.hGlobal ))))
2124  continue;
2125 
2127  StretchDIBits( hdcDraw, lprcBounds->left, lprcBounds->top,
2128  lprcBounds->right - lprcBounds->left, lprcBounds->bottom - lprcBounds->top,
2129  0, 0, info->bmiHeader.biWidth, info->bmiHeader.biHeight,
2131 
2132  GlobalUnlock( cache_entry->stgmedium.u.hGlobal );
2133  return S_OK;
2134  }
2135  }
2136  }
2137 
2138  WARN("no data could be found to be drawn\n");
2139 
2140  return OLE_E_BLANK;
2141 }
2142 
2144  IViewObject2* iface,
2145  DWORD dwDrawAspect,
2146  LONG lindex,
2147  void* pvAspect,
2148  DVTARGETDEVICE* ptd,
2149  HDC hicTargetDevice,
2150  LOGPALETTE** ppColorSet)
2151 {
2152  FIXME("stub\n");
2153  return E_NOTIMPL;
2154 }
2155 
2157  IViewObject2* iface,
2158  DWORD dwDrawAspect,
2159  LONG lindex,
2160  void* pvAspect,
2161  DWORD* pdwFreeze)
2162 {
2163  FIXME("stub\n");
2164  return E_NOTIMPL;
2165 }
2166 
2168  IViewObject2* iface,
2169  DWORD dwFreeze)
2170 {
2171  FIXME("stub\n");
2172  return E_NOTIMPL;
2173 }
2174 
2175 /************************************************************************
2176  * DataCache_SetAdvise (IViewObject2)
2177  *
2178  * This sets-up an advisory sink with the data cache. When the object's
2179  * view changes, this sink is called.
2180  */
2182  IViewObject2* iface,
2183  DWORD aspects,
2184  DWORD advf,
2185  IAdviseSink* pAdvSink)
2186 {
2187  DataCache *this = impl_from_IViewObject2(iface);
2188 
2189  TRACE("(%p, %x, %x, %p)\n", iface, aspects, advf, pAdvSink);
2190 
2191  /*
2192  * A call to this function removes the previous sink
2193  */
2194  if (this->sinkInterface != NULL)
2195  {
2196  IAdviseSink_Release(this->sinkInterface);
2197  this->sinkInterface = NULL;
2198  this->sinkAspects = 0;
2199  this->sinkAdviseFlag = 0;
2200  }
2201 
2202  /*
2203  * Now, setup the new one.
2204  */
2205  if (pAdvSink!=NULL)
2206  {
2207  this->sinkInterface = pAdvSink;
2208  this->sinkAspects = aspects;
2209  this->sinkAdviseFlag = advf;
2210 
2211  IAdviseSink_AddRef(this->sinkInterface);
2212  }
2213 
2214  /*
2215  * When the ADVF_PRIMEFIRST flag is set, we have to advise the
2216  * sink immediately.
2217  */
2218  if (advf & ADVF_PRIMEFIRST)
2219  {
2220  DataCache_FireOnViewChange(this, aspects, -1);
2221  }
2222 
2223  return S_OK;
2224 }
2225 
2226 /************************************************************************
2227  * DataCache_GetAdvise (IViewObject2)
2228  *
2229  * This method queries the current state of the advise sink
2230  * installed on the data cache.
2231  */
2233  IViewObject2* iface,
2234  DWORD* pAspects,
2235  DWORD* pAdvf,
2236  IAdviseSink** ppAdvSink)
2237 {
2238  DataCache *this = impl_from_IViewObject2(iface);
2239 
2240  TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
2241 
2242  /*
2243  * Just copy all the requested values.
2244  */
2245  if (pAspects!=NULL)
2246  *pAspects = this->sinkAspects;
2247 
2248  if (pAdvf!=NULL)
2249  *pAdvf = this->sinkAdviseFlag;
2250 
2251  if (ppAdvSink!=NULL)
2252  {
2253  if (this->sinkInterface != NULL)
2254  IAdviseSink_QueryInterface(this->sinkInterface,
2255  &IID_IAdviseSink,
2256  (void**)ppAdvSink);
2257  else *ppAdvSink = NULL;
2258  }
2259 
2260  return S_OK;
2261 }
2262 
2263 /************************************************************************
2264  * DataCache_GetExtent (IViewObject2)
2265  *
2266  * This method retrieves the "natural" size of this cached object.
2267  */
2269  IViewObject2* iface,
2270  DWORD dwDrawAspect,
2271  LONG lindex,
2272  DVTARGETDEVICE* ptd,
2273  LPSIZEL lpsizel)
2274 {
2276  HRESULT hres = E_FAIL;
2278 
2279  TRACE("(%p, %x, %d, %p, %p)\n",
2280  iface, dwDrawAspect, lindex, ptd, lpsizel);
2281 
2282  if (lpsizel==NULL)
2283  return E_POINTER;
2284 
2285  lpsizel->cx = 0;
2286  lpsizel->cy = 0;
2287 
2288  if (lindex!=-1)
2289  FIXME("Unimplemented flag lindex = %d\n", lindex);
2290 
2291  /*
2292  * Right now, we support only the callback from
2293  * the default handler.
2294  */
2295  if (ptd!=NULL)
2296  FIXME("Unimplemented ptd = %p\n", ptd);
2297 
2299  {
2300  /* FIXME: compare ptd too */
2301  if ((cache_entry->fmtetc.dwAspect != dwDrawAspect) ||
2302  (cache_entry->fmtetc.lindex != lindex))
2303  continue;
2304 
2305  /* if the data hasn't been loaded yet, do it now */
2306  if ((cache_entry->stgmedium.tymed == TYMED_NULL) && (cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET))
2307  {
2308  hres = DataCacheEntry_LoadData(cache_entry, This->presentationStorage);
2309  if (FAILED(hres))
2310  continue;
2311  }
2312 
2313  /* no data */
2314  if (cache_entry->stgmedium.tymed == TYMED_NULL)
2315  continue;
2316 
2317 
2318  switch (cache_entry->fmtetc.cfFormat)
2319  {
2320  case CF_METAFILEPICT:
2321  {
2322  METAFILEPICT *mfpict;
2323 
2324  if ((cache_entry->stgmedium.tymed != TYMED_MFPICT) ||
2325  !((mfpict = GlobalLock(cache_entry->stgmedium.u.hMetaFilePict))))
2326  continue;
2327 
2328  lpsizel->cx = mfpict->xExt;
2329  lpsizel->cy = mfpict->yExt;
2330 
2331  GlobalUnlock(cache_entry->stgmedium.u.hMetaFilePict);
2332 
2333  return S_OK;
2334  }
2335  case CF_DIB:
2336  {
2338  LONG x_pels_m, y_pels_m;
2339 
2340 
2341  if ((cache_entry->stgmedium.tymed != TYMED_HGLOBAL) ||
2342  !((info = GlobalLock( cache_entry->stgmedium.u.hGlobal ))))
2343  continue;
2344 
2345  x_pels_m = info->biXPelsPerMeter;
2346  y_pels_m = info->biYPelsPerMeter;
2347 
2348  /* Size in units of 0.01mm (ie. MM_HIMETRIC) */
2349  if (x_pels_m != 0 && y_pels_m != 0)
2350  {
2351  lpsizel->cx = info->biWidth * 100000 / x_pels_m;
2352  lpsizel->cy = info->biHeight * 100000 / y_pels_m;
2353  }
2354  else
2355  {
2356  HDC hdc = GetDC( 0 );
2357  lpsizel->cx = info->biWidth * 2540 / GetDeviceCaps( hdc, LOGPIXELSX );
2358  lpsizel->cy = info->biHeight * 2540 / GetDeviceCaps( hdc, LOGPIXELSY );
2359 
2360  ReleaseDC( 0, hdc );
2361  }
2362 
2363  GlobalUnlock( cache_entry->stgmedium.u.hGlobal );
2364 
2365  return S_OK;
2366  }
2367  }
2368  }
2369 
2370  WARN("no data could be found to get the extents from\n");
2371 
2372  /*
2373  * This method returns OLE_E_BLANK when it fails.
2374  */
2375  return OLE_E_BLANK;
2376 }
2377 
2378 
2379 /*********************************************************
2380  * Method implementation for the IOleCache2
2381  * part of the DataCache class.
2382  */
2383 
2384 /************************************************************************
2385  * DataCache_IOleCache2_QueryInterface (IUnknown)
2386  */
2388  IOleCache2* iface,
2389  REFIID riid,
2390  void** ppvObject)
2391 {
2392  DataCache *this = impl_from_IOleCache2(iface);
2393 
2394  return IUnknown_QueryInterface(this->outer_unk, riid, ppvObject);
2395 }
2396 
2397 /************************************************************************
2398  * DataCache_IOleCache2_AddRef (IUnknown)
2399  */
2401  IOleCache2* iface)
2402 {
2403  DataCache *this = impl_from_IOleCache2(iface);
2404 
2405  return IUnknown_AddRef(this->outer_unk);
2406 }
2407 
2408 /************************************************************************
2409  * DataCache_IOleCache2_Release (IUnknown)
2410  */
2412  IOleCache2* iface)
2413 {
2414  DataCache *this = impl_from_IOleCache2(iface);
2415 
2416  return IUnknown_Release(this->outer_unk);
2417 }
2418 
2419 /*****************************************************************************
2420  * setup_sink
2421  *
2422  * Set up the sink connection to the running object.
2423  */
2425 {
2426  HRESULT hr = S_FALSE;
2427  DWORD flags;
2428 
2429  /* Clear the ADVFCACHE_* bits. Native also sets the two highest bits for some reason. */
2430  flags = cache_entry->advise_flags & ~(ADVFCACHE_NOHANDLER | ADVFCACHE_FORCEBUILTIN | ADVFCACHE_ONSAVE);
2431 
2432  if(This->running_object)
2433  if(!(flags & ADVF_NODATA))
2434  hr = IDataObject_DAdvise(This->running_object, &cache_entry->fmtetc, flags,
2435  &This->IAdviseSink_iface, &cache_entry->sink_id);
2436  return hr;
2437 }
2438 
2440  IOleCache2* iface,
2441  FORMATETC* pformatetc,
2442  DWORD advf,
2443  DWORD* pdwConnection)
2444 {
2447  HRESULT hr;
2448  FORMATETC fmt_cpy;
2449 
2450  TRACE("(%p, 0x%x, %p)\n", pformatetc, advf, pdwConnection);
2451 
2452  if (!pformatetc || !pdwConnection)
2453  return E_INVALIDARG;
2454 
2455  TRACE("pformatetc = %s\n", debugstr_formatetc(pformatetc));
2456 
2457  fmt_cpy = *pformatetc; /* No need for a deep copy */
2458  if (fmt_cpy.cfFormat == CF_BITMAP && fmt_cpy.tymed == TYMED_GDI)
2459  {
2460  fmt_cpy.cfFormat = CF_DIB;
2461  fmt_cpy.tymed = TYMED_HGLOBAL;
2462  }
2463 
2464  /* View caching DVASPECT_ICON gets converted to CF_METAFILEPICT */
2465  if (fmt_cpy.dwAspect == DVASPECT_ICON && fmt_cpy.cfFormat == 0)
2466  {
2467  fmt_cpy.cfFormat = CF_METAFILEPICT;
2468  fmt_cpy.tymed = TYMED_MFPICT;
2469  }
2470 
2471  *pdwConnection = 0;
2472 
2474  if (cache_entry)
2475  {
2476  TRACE("found an existing cache entry\n");
2477  *pdwConnection = cache_entry->id;
2478  return CACHE_S_SAMECACHE;
2479  }
2480 
2481  if (This->clsid_static && fmt_cpy.dwAspect != DVASPECT_ICON) return DV_E_FORMATETC;
2482 
2483  hr = DataCache_CreateEntry(This, &fmt_cpy, advf, FALSE, &cache_entry);
2484 
2485  if (SUCCEEDED(hr))
2486  {
2487  *pdwConnection = cache_entry->id;
2489  }
2490 
2491  return hr;
2492 }
2493 
2495  IOleCache2* iface,
2496  DWORD dwConnection)
2497 {
2500 
2501  TRACE("(%d)\n", dwConnection);
2502 
2504  if (cache_entry->id == dwConnection)
2505  {
2507  return S_OK;
2508  }
2509 
2510  WARN("no connection found for %d\n", dwConnection);
2511 
2512  return OLE_E_NOCONNECTION;
2513 }
2514 
2516  IEnumSTATDATA **enum_stat)
2517 {
2518  DataCache *This = impl_from_IOleCache2( iface );
2520  int i = 0, count = 0;
2521  STATDATA *data;
2522  HRESULT hr;
2523 
2524  TRACE( "(%p, %p)\n", This, enum_stat );
2525 
2527  {
2528  count++;
2529  if (cache_entry->fmtetc.cfFormat == CF_DIB)
2530  count++;
2531  }
2532 
2533  data = CoTaskMemAlloc( count * sizeof(*data) );
2534  if (!data) return E_OUTOFMEMORY;
2535 
2537  {
2538  if (i == count) goto fail;
2539  hr = copy_formatetc( &data[i].formatetc, &cache_entry->fmtetc );
2540  if (FAILED(hr)) goto fail;
2541  data[i].advf = cache_entry->advise_flags;
2542  data[i].pAdvSink = NULL;
2543  data[i].dwConnection = cache_entry->id;
2544  i++;
2545 
2546  if (cache_entry->fmtetc.cfFormat == CF_DIB)
2547  {
2548  if (i == count) goto fail;
2549  hr = copy_formatetc( &data[i].formatetc, &cache_entry->fmtetc );
2550  if (FAILED(hr)) goto fail;
2551  data[i].formatetc.cfFormat = CF_BITMAP;
2552  data[i].formatetc.tymed = TYMED_GDI;
2553  data[i].advf = cache_entry->advise_flags;
2554  data[i].pAdvSink = NULL;
2555  data[i].dwConnection = cache_entry->id;
2556  i++;
2557  }
2558  }
2559 
2560  hr = EnumSTATDATA_Construct( NULL, 0, i, data, FALSE, enum_stat );
2561  if (SUCCEEDED(hr)) return hr;
2562 
2563 fail:
2564  while (i--) CoTaskMemFree( data[i].formatetc.ptd );
2565  CoTaskMemFree( data );
2566  return hr;
2567 }
2568 
2570 {
2571  TRACE( "(%p %p)\n", iface, data );
2572  return IOleCache2_UpdateCache( iface, data, UPDFCACHE_ALLBUTNODATACACHE, NULL );
2573 }
2574 
2576  IOleCache2* iface,
2577  FORMATETC* pformatetc,
2578  STGMEDIUM* pmedium,
2579  BOOL fRelease)
2580 {
2583  HRESULT hr;
2584 
2585  TRACE("(%p, %p, %s)\n", pformatetc, pmedium, fRelease ? "TRUE" : "FALSE");
2586  TRACE("formatetc = %s\n", debugstr_formatetc(pformatetc));
2587 
2589  if (cache_entry)
2590  {
2591  hr = DataCacheEntry_SetData(cache_entry, pformatetc, pmedium, fRelease);
2592 
2593  if (SUCCEEDED(hr))
2594  DataCache_FireOnViewChange(This, cache_entry->fmtetc.dwAspect,
2595  cache_entry->fmtetc.lindex);
2596 
2597  return hr;
2598  }
2599  WARN("cache entry not found\n");
2600 
2601  return OLE_E_BLANK;
2602 }
2603 
2605 {
2606  BOOL is_blank = entry->stgmedium.tymed == TYMED_NULL;
2607 
2608  if ((mode & UPDFCACHE_ONLYIFBLANK) && !is_blank) return FALSE;
2609 
2610  if ((mode & UPDFCACHE_NODATACACHE) && (entry->advise_flags & ADVF_NODATA)) return TRUE;
2611  if ((mode & UPDFCACHE_ONSAVECACHE) && (entry->advise_flags & ADVFCACHE_ONSAVE)) return TRUE;
2612  if ((mode & UPDFCACHE_ONSTOPCACHE) && (entry->advise_flags & ADVF_DATAONSTOP)) return TRUE;
2613  if ((mode & UPDFCACHE_NORMALCACHE) && (entry->advise_flags == 0)) return TRUE;
2614  if ((mode & UPDFCACHE_IFBLANK) && (is_blank && !(entry->advise_flags & ADVF_NODATA))) return TRUE;
2615 
2616  return FALSE;
2617 }
2618 
2620  DWORD mode, void *reserved )
2621 {
2624  STGMEDIUM med;
2625  HRESULT hr = S_OK;
2626  CLIPFORMAT view_list[] = { CF_METAFILEPICT, CF_ENHMETAFILE, CF_DIB, CF_BITMAP };
2627  FORMATETC fmt;
2628  int i, slots = 0;
2629  BOOL done_one = FALSE;
2630 
2631  TRACE( "(%p %p %08x %p)\n", iface, data, mode, reserved );
2632 
2634  {
2635  slots++;
2636 
2637  if (!entry_updatable( cache_entry, mode ))
2638  {
2639  done_one = TRUE;
2640  continue;
2641  }
2642 
2643  fmt = cache_entry->fmtetc;
2644 
2645  if (fmt.cfFormat)
2646  {
2647  hr = IDataObject_GetData( data, &fmt, &med );
2648  if (hr != S_OK && fmt.cfFormat == CF_DIB)
2649  {
2650  fmt.cfFormat = CF_BITMAP;
2651  fmt.tymed = TYMED_GDI;
2652  hr = IDataObject_GetData( data, &fmt, &med );
2653  }
2654  if (hr != S_OK && fmt.cfFormat == CF_ENHMETAFILE)
2655  {
2656  fmt.cfFormat = CF_METAFILEPICT;
2657  fmt.tymed = TYMED_MFPICT;
2658  hr = IDataObject_GetData( data, &fmt, &med );
2659  }
2660  if (hr == S_OK)
2661  {
2663  if (hr != S_OK) ReleaseStgMedium( &med );
2664  else done_one = TRUE;
2665  }
2666  }
2667  else
2668  {
2669  for (i = 0; i < ARRAY_SIZE(view_list); i++)
2670  {
2671  fmt.cfFormat = view_list[i];
2672  fmt.tymed = tymed_from_cf( fmt.cfFormat );
2673  hr = IDataObject_QueryGetData( data, &fmt );
2674  if (hr == S_OK)
2675  {
2676  hr = IDataObject_GetData( data, &fmt, &med );
2677  if (hr == S_OK)
2678  {
2679  if (fmt.cfFormat == CF_BITMAP)
2680  {
2681  cache_entry->fmtetc.cfFormat = CF_DIB;
2682  cache_entry->fmtetc.tymed = TYMED_HGLOBAL;
2683  }
2684  else
2685  {
2686  cache_entry->fmtetc.cfFormat = fmt.cfFormat;
2687  cache_entry->fmtetc.tymed = fmt.tymed;
2688  }
2690  if (hr != S_OK) ReleaseStgMedium( &med );
2691  else done_one = TRUE;
2692  break;
2693  }
2694  }
2695  }
2696  }
2697  }
2698 
2699  return (!slots || done_one) ? S_OK : CACHE_E_NOCACHE_UPDATED;
2700 }
2701 
2703  IOleCache2* iface,
2704  DWORD dwDiscardOptions)
2705 {
2708  HRESULT hr = S_OK;
2709 
2710  TRACE("(%d)\n", dwDiscardOptions);
2711 
2712  if (dwDiscardOptions == DISCARDCACHE_SAVEIFDIRTY)
2713  hr = DataCache_Save(&This->IPersistStorage_iface, This->presentationStorage, TRUE);
2714 
2716  {
2718  if (FAILED(hr))
2719  break;
2720  }
2721 
2722  return hr;
2723 }
2724 
2725 
2726 /*********************************************************
2727  * Method implementation for the IOleCacheControl
2728  * part of the DataCache class.
2729  */
2730 
2731 /************************************************************************
2732  * DataCache_IOleCacheControl_QueryInterface (IUnknown)
2733  */
2735  IOleCacheControl* iface,
2736  REFIID riid,
2737  void** ppvObject)
2738 {
2739  DataCache *this = impl_from_IOleCacheControl(iface);
2740 
2741  return IUnknown_QueryInterface(this->outer_unk, riid, ppvObject);
2742 }
2743 
2744 /************************************************************************
2745  * DataCache_IOleCacheControl_AddRef (IUnknown)
2746  */
2748  IOleCacheControl* iface)
2749 {
2750  DataCache *this = impl_from_IOleCacheControl(iface);
2751 
2752  return IUnknown_AddRef(this->outer_unk);
2753 }
2754 
2755 /************************************************************************
2756  * DataCache_IOleCacheControl_Release (IUnknown)
2757  */
2759  IOleCacheControl* iface)
2760 {
2761  DataCache *this = impl_from_IOleCacheControl(iface);
2762 
2763  return IUnknown_Release(this->outer_unk);
2764 }
2765 
2766 /************************************************************************
2767  * DataCache_OnRun (IOleCacheControl)
2768  */
2770 {
2773 
2774  TRACE("(%p)->(%p)\n", iface, data_obj);
2775 
2776  if(This->running_object) return S_OK;
2777 
2778  /* No reference is taken on the data object */
2779  This->running_object = data_obj;
2780 
2782  {
2784  }
2785 
2786  return S_OK;
2787 }
2788 
2789 /************************************************************************
2790  * DataCache_OnStop (IOleCacheControl)
2791  */
2793 {
2796 
2797  TRACE("(%p)\n", iface);
2798 
2799  if(!This->running_object) return S_OK;
2800 
2802  {
2803  if(cache_entry->sink_id)
2804  {
2805  IDataObject_DUnadvise(This->running_object, cache_entry->sink_id);
2806  cache_entry->sink_id = 0;
2807  }
2808  }
2809 
2810  /* No ref taken in OnRun, so no Release call here */
2811  This->running_object = NULL;
2812  return S_OK;
2813 }
2814 
2815 /************************************************************************
2816  * IAdviseSink methods.
2817  * This behaves as an internal object to the data cache. QI'ing its ptr doesn't
2818  * give access to the cache's other interfaces. We don't maintain a ref count,
2819  * the object exists as long as the cache is around.
2820  */
2822 {
2823  *obj = NULL;
2824  if (IsEqualIID(&IID_IUnknown, iid) ||
2825  IsEqualIID(&IID_IAdviseSink, iid))
2826  {
2827  *obj = iface;
2828  }
2829 
2830  if(*obj)
2831  {
2832  IAdviseSink_AddRef(iface);
2833  return S_OK;
2834  }
2835  return E_NOINTERFACE;
2836 }
2837 
2839 {
2840  return 2;
2841 }
2842 
2844 {
2845  return 1;
2846 }
2847 
2848 static void WINAPI DataCache_OnDataChange(IAdviseSink *iface, FORMATETC *fmt, STGMEDIUM *med)
2849 {
2851  TRACE("(%p)->(%s, %p)\n", This, debugstr_formatetc(fmt), med);
2852  IOleCache2_SetData(&This->IOleCache2_iface, fmt, med, FALSE);
2853 }
2854 
2856 {
2857  FIXME("stub\n");
2858 }
2859 
2861 {
2862  FIXME("stub\n");
2863 }
2864 
2866 {
2867  FIXME("stub\n");
2868 }
2869 
2871 {
2872  FIXME("stub\n");
2873 }
2874 
2875 /*
2876  * Virtual function tables for the DataCache class.
2877  */
2878 static const IUnknownVtbl DataCache_NDIUnknown_VTable =
2879 {
2883 };
2884 
2885 static const IDataObjectVtbl DataCache_IDataObject_VTable =
2886 {
2899 };
2900 
2901 static const IPersistStorageVtbl DataCache_IPersistStorage_VTable =
2902 {
2913 };
2914 
2915 static const IViewObject2Vtbl DataCache_IViewObject2_VTable =
2916 {
2927 };
2928 
2929 static const IOleCache2Vtbl DataCache_IOleCache2_VTable =
2930 {
2941 };
2942 
2943 static const IOleCacheControlVtbl DataCache_IOleCacheControl_VTable =
2944 {
2950 };
2951 
2952 static const IAdviseSinkVtbl DataCache_IAdviseSink_VTable =
2953 {
2962 };
2963 
2964 /*********************************************************
2965  * Method implementation for DataCache class.
2966  */
2968  REFCLSID clsid,
2969  LPUNKNOWN pUnkOuter)
2970 {
2971  DataCache* newObject = 0;
2972 
2973  /*
2974  * Allocate space for the object.
2975  */
2976  newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
2977 
2978  if (newObject==0)
2979  return newObject;
2980 
2981  /*
2982  * Initialize the virtual function table.
2983  */
2984  newObject->IDataObject_iface.lpVtbl = &DataCache_IDataObject_VTable;
2985  newObject->IUnknown_inner.lpVtbl = &DataCache_NDIUnknown_VTable;
2988  newObject->IOleCache2_iface.lpVtbl = &DataCache_IOleCache2_VTable;
2990  newObject->IAdviseSink_iface.lpVtbl = &DataCache_IAdviseSink_VTable;
2991  newObject->outer_unk = pUnkOuter ? pUnkOuter : &newObject->IUnknown_inner;
2992  newObject->ref = 1;
2993 
2994  /*
2995  * Initialize the other members of the structure.
2996  */
2997  newObject->sinkAspects = 0;
2998  newObject->sinkAdviseFlag = 0;
2999  newObject->sinkInterface = 0;
3000  newObject->clsid = CLSID_NULL;
3001  newObject->clsid_static = FALSE;
3002  newObject->presentationStorage = NULL;
3003  list_init(&newObject->cache_list);
3004  newObject->last_cache_id = 2;
3005  newObject->dirty = FALSE;
3006  newObject->running_object = NULL;
3007 
3008  create_automatic_entry( newObject, clsid );
3009  newObject->clsid = *clsid;
3010 
3011  return newObject;
3012 }
3013 
3014 /******************************************************************************
3015  * CreateDataCache [OLE32.@]
3016  *
3017  * Creates a data cache to allow an object to render one or more of its views,
3018  * whether running or not.
3019  *
3020  * PARAMS
3021  * pUnkOuter [I] Outer unknown for the object.
3022  * rclsid [I]
3023  * riid [I] IID of interface to return.
3024  * ppvObj [O] Address where the data cache object will be stored on return.
3025  *
3026  * RETURNS
3027  * Success: S_OK.
3028  * Failure: HRESULT code.
3029  *
3030  * NOTES
3031  * The following interfaces are supported by the returned data cache object:
3032  * IOleCache, IOleCache2, IOleCacheControl, IPersistStorage, IDataObject,
3033  * IViewObject and IViewObject2.
3034  */
3036  LPUNKNOWN pUnkOuter,
3037  REFCLSID rclsid,
3038  REFIID riid,
3039  LPVOID* ppvObj)
3040 {
3041  DataCache* newCache = NULL;
3042  HRESULT hr = S_OK;
3043 
3044  TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
3045 
3046  /*
3047  * Sanity check
3048  */
3049  if (ppvObj==0)
3050  return E_POINTER;
3051 
3052  *ppvObj = 0;
3053 
3054  /*
3055  * If this cache is constructed for aggregation, make sure
3056  * the caller is requesting the IUnknown interface.
3057  * This is necessary because it's the only time the non-delegating
3058  * IUnknown pointer can be returned to the outside.
3059  */
3060  if ( pUnkOuter && !IsEqualIID(&IID_IUnknown, riid) )
3061  return E_INVALIDARG;
3062 
3063  /*
3064  * Try to construct a new instance of the class.
3065  */
3066  newCache = DataCache_Construct(rclsid,
3067  pUnkOuter);
3068 
3069  if (newCache == 0)
3070  return E_OUTOFMEMORY;
3071 
3072  hr = IUnknown_QueryInterface(&newCache->IUnknown_inner, riid, ppvObj);
3073  IUnknown_Release(&newCache->IUnknown_inner);
3074 
3075  return hr;
3076 }
static IClassFactory * cf
Definition: cache.c:48
static ULONG WINAPI DataCache_IViewObject2_Release(IViewObject2 *iface)
Definition: datacache.c:1992
#define abs(i)
Definition: fconv.c:206
static ULONG WINAPI DataCache_IOleCacheControl_Release(IOleCacheControl *iface)
Definition: datacache.c:2758
HMETAFILE WINAPI SetMetaFileBitsEx(_In_ UINT cbBuffer, _In_reads_bytes_(cbBuffer) CONST BYTE *lpData)
CLSID clsid
Definition: datacache.c:156
static DataCache * impl_from_IViewObject2(IViewObject2 *iface)
Definition: datacache.c:196
int WINAPI StretchDIBits(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ const VOID *, _In_ const BITMAPINFO *, _In_ UINT, _In_ DWORD)
HMETAFILE hMF
Definition: wingdi.h:2607
static HRESULT WINAPI DataCache_EnumDAdvise(IDataObject *iface, IEnumSTATDATA **ppenumAdvise)
Definition: datacache.c:1627
#define max(a, b)
Definition: svc.c:63
#define LOGPIXELSX
Definition: wingdi.h:717
BOOL WINAPI SetViewportOrgEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
Definition: coord.c:655
struct tagENHMETAHEADER ENHMETAHEADER
#define REFIID
Definition: guiddef.h:118
static HRESULT WINAPI DataCache_InitCache(IOleCache2 *iface, IDataObject *data)
Definition: datacache.c:2569
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
const GUID IID_IViewObject
BOOL WINAPI SetWindowExtEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPSIZE)
BOOL dirty
Definition: datacache.c:167
#define E_NOINTERFACE
Definition: winerror.h:2364
#define DV_E_STGMEDIUM
Definition: winerror.h:2635
static HRESULT WINAPI DataCache_GetAdvise(IViewObject2 *iface, DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
Definition: datacache.c:2232
static HRESULT parse_contents_stream(DataCache *cache, IStorage *stg)
Definition: datacache.c:1803
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
IUnknown * outer_unk
Definition: datacache.c:145
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1475
long y
Definition: polytest.cpp:48
FORMATETC fmtetc
Definition: datacache.c:99
#define CF_ENHMETAFILE
Definition: constants.h:409
HRESULT hr
Definition: shlfolder.c:183
static const IOleCacheControlVtbl DataCache_IOleCacheControl_VTable
Definition: datacache.c:2943
static HRESULT WINAPI DataCache_DiscardCache(IOleCache2 *iface, DWORD dwDiscardOptions)
Definition: datacache.c:2702
static DataCache * impl_from_IDataObject(IDataObject *iface)
Definition: datacache.c:181
static HRESULT load_mf_pict(DataCacheEntry *cache_entry, IStream *stm)
Definition: datacache.c:584
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:922
int load_stream_num
Definition: datacache.c:108
static DataCache * impl_from_IOleCache2(IOleCache2 *iface)
Definition: datacache.c:201
long x
Definition: polytest.cpp:48
static ULONG WINAPI DataCache_IAdviseSink_AddRef(IAdviseSink *iface)
Definition: datacache.c:2838
static HRESULT WINAPI DataCache_Save(IPersistStorage *iface, IStorage *stg, BOOL same_as_load)
Definition: datacache.c:1879
static HRESULT WINAPI DataCache_GetClassID(IPersistStorage *iface, CLSID *clsid)
Definition: datacache.c:1679
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
struct outqueuenode * head
Definition: adnsresfilter.c:66
HDC WINAPI GetDC(_In_opt_ HWND)
static HRESULT save_dib(DataCacheEntry *entry, BOOL contents, IStream *stream)
Definition: datacache.c:877
#define TRUE
Definition: types.h:120
static void WINAPI DataCache_OnClose(IAdviseSink *iface)
Definition: datacache.c:2870
REFIID riid
Definition: precomp.h:44
static void DataCache_Destroy(DataCache *ptrToDestroy)
Definition: datacache.c:263
#define REFCLSID
Definition: guiddef.h:117
LONG biXPelsPerMeter
Definition: amvideo.idl:37
GLuint GLuint GLsizei count
Definition: gl.h:1545
const GUID IID_IPersist
Definition: proxy.cpp:14
const GUID IID_IOleCacheControl
#define WARN(fmt,...)
Definition: debug.h:112
struct list entry
Definition: datacache.c:97
static HRESULT save_mfpict(DataCacheEntry *entry, BOOL contents, IStream *stream)
Definition: datacache.c:935
#define STGM_CREATE
Definition: objbase.h:925
IAdviseSink IAdviseSink_iface
Definition: datacache.c:135
static HDC
Definition: imagelist.c:92
int save_stream_num
Definition: datacache.c:111
#define CALLBACK
Definition: compat.h:35
const char * fmt
Definition: wsprintf.c:30
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
static HRESULT WINAPI DataCache_HandsOffStorage(IPersistStorage *iface)
Definition: datacache.c:1944
static HRESULT WINAPI DataCache_SetAdvise(IViewObject2 *iface, DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
Definition: datacache.c:2181
long bottom
Definition: polytest.cpp:53
HENHMETAFILE WINAPI SetEnhMetaFileBits(_In_ UINT nSize, _In_reads_bytes_(nSize) const BYTE *pb)
static HRESULT add_cache_entry(DataCache *This, const FORMATETC *fmt, DWORD advf, int stream_number)
Definition: datacache.c:1747
static ULONG WINAPI DataCache_IAdviseSink_Release(IAdviseSink *iface)
Definition: datacache.c:2843
static HRESULT WINAPI DataCache_IAdviseSink_QueryInterface(IAdviseSink *iface, REFIID iid, void **obj)
Definition: datacache.c:2821
static HRESULT create_stream(DataCacheEntry *cache_entry, IStorage *storage, BOOL contents, IStream **stream)
Definition: datacache.c:1082
static ULONG WINAPI DataCache_NDIUnknown_Release(IUnknown *iface)
Definition: datacache.c:1440
const GUID IID_IDataObject
static HRESULT WINAPI DataCache_GetData(IDataObject *iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
Definition: datacache.c:1498
#define DV_E_CLIPFORMAT
Definition: winerror.h:2639
IViewObject2 IViewObject2_iface
Definition: datacache.c:129
const GUID IID_IPersistStorage
GLuint GLuint end
Definition: gl.h:1545
static HRESULT WINAPI DataCache_GetExtent(IViewObject2 *iface, DWORD dwDrawAspect, LONG lindex, DVTARGETDEVICE *ptd, LPSIZEL lpsizel)
Definition: datacache.c:2268
HANDLE WINAPI OleDuplicateData(HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags)
Definition: ole2impl.c:425
#define CF_METAFILEPICT
Definition: constants.h:398
IPersistStorage IPersistStorage_iface
Definition: datacache.c:128
Definition: svc_auth_des.c:77
LONG biYPelsPerMeter
Definition: amvideo.idl:38
#define E_FAIL
Definition: ddrawi.h:102
static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(IOleCacheControl *iface, REFIID riid, void **ppvObject)
Definition: datacache.c:2734
#define STREAM_NUMBER_CONTENTS
Definition: datacache.c:93
#define DWORD
Definition: nt_native.h:44
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
int32_t INT
Definition: typedefs.h:58
Definition: send.c:48
#define BI_BITFIELDS
Definition: mmreg.h:507
const CLSID CLSID_Picture_Dib
static DataCacheEntry * DataCache_GetEntryForFormatEtc(DataCache *This, const FORMATETC *formatetc)
Definition: datacache.c:291
HENHMETAFILE WINAPI SetWinMetaFileBits(_In_ UINT nSize, _In_reads_bytes_(nSize) const BYTE *lpMeta16Data, _In_opt_ HDC hdcRef, _In_opt_ const METAFILEPICT *lpMFP)
static void WINAPI DataCache_OnSave(IAdviseSink *iface)
Definition: datacache.c:2865
static HRESULT write_clipformat(IStream *stream, CLIPFORMAT clipformat)
Definition: datacache.c:501
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
struct _test_info info[]
Definition: SetCursorPos.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:65
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
static DataCache * impl_from_IOleCacheControl(IOleCacheControl *iface)
Definition: datacache.c:206
#define CBM_INIT
Definition: wingdi.h:364
const GUID IID_IAdviseSink
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
static HRESULT load_emf(DataCacheEntry *cache_entry, IStream *stm)
Definition: datacache.c:764
static HRESULT WINAPI DataCache_Freeze(IViewObject2 *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
Definition: datacache.c:2156
static HRESULT save_view_cache(DataCacheEntry *entry, IStream *stream)
Definition: datacache.c:1069
long right
Definition: polytest.cpp:53
#define OLE_E_NOCONNECTION
Definition: winerror.h:2618
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
UINT WINAPI GetEnhMetaFileBits(_In_ HENHMETAFILE hEMF, _In_ UINT nSize, _Out_writes_bytes_opt_(nSize) LPBYTE lpData)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static HRESULT WINAPI DataCache_IDataObject_QueryInterface(IDataObject *iface, REFIID riid, void **ppvObject)
Definition: datacache.c:1461
static void WINAPI DataCache_OnDataChange(IAdviseSink *iface, FORMATETC *fmt, STGMEDIUM *med)
Definition: datacache.c:2848
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
const char * debugstr_formatetc(const FORMATETC *formatetc)
Definition: datacache.c:216
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
int WINAPI SetMapMode(_In_ HDC, _In_ int)
static const IDataObjectVtbl DataCache_IDataObject_VTable
Definition: datacache.c:2885
static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(IOleCache2 *iface, REFIID riid, void **ppvObject)
Definition: datacache.c:2387
static LPUNKNOWN
Definition: ndr_ole.c:49
IDataObject IDataObject_iface
Definition: datacache.c:127
long top
Definition: polytest.cpp:53
GLenum GLint ref
Definition: glext.h:6028
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define FIXME(fmt,...)
Definition: debug.h:111
static PVOID ptr
Definition: dispmode.c:27
r reserved
Definition: btrfs.c:2940
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
#define CF_BITMAP
Definition: constants.h:397
static HRESULT copy_formatetc(FORMATETC *dst, const FORMATETC *src)
smooth NULL
Definition: ftsmooth.c:416
WORD bounding_box[4]
Definition: datacache.c:577
LONG cx
Definition: windef.h:334
DWORD last_cache_id
Definition: datacache.c:165
static HRESULT WINAPI DataCache_EnumCache(IOleCache2 *iface, IEnumSTATDATA **enum_stat)
Definition: datacache.c:2515
static void DataCacheEntry_Destroy(DataCache *cache, DataCacheEntry *cache_entry)
Definition: datacache.c:252
static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(IDataObject *iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
Definition: datacache.c:1542
GLuint index
Definition: glext.h:6031
static const IPersistStorageVtbl DataCache_IPersistStorage_VTable
Definition: datacache.c:2901
static HRESULT WINAPI DataCache_SaveCompleted(IPersistStorage *iface, IStorage *pStgNew)
Definition: datacache.c:1922
static HRESULT WINAPI DataCache_OnRun(IOleCacheControl *iface, IDataObject *data_obj)
Definition: datacache.c:2769
#define debugstr_guid
Definition: kernel32.h:35
long left
Definition: polytest.cpp:53
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static ULONG WINAPI DataCache_IViewObject2_AddRef(IViewObject2 *iface)
Definition: datacache.c:1981
#define STGM_READ
Definition: objbase.h:916
static ULONG WINAPI DataCache_IDataObject_Release(IDataObject *iface)
Definition: datacache.c:1485
int64_t LONGLONG
Definition: typedefs.h:68
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
static HRESULT WINAPI DataCache_OnStop(IOleCacheControl *iface)
Definition: datacache.c:2792
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
HRESULT hres
Definition: protocol.c:465
#define CO_E_ALREADYINITIALIZED
Definition: winerror.h:2804
#define DV_E_FORMATETC
Definition: winerror.h:2633
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static HRESULT WINAPI DataCache_DAdvise(IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
Definition: datacache.c:1598
ULONG RGBQUAD
Definition: precomp.h:50
static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, IStorage *stg, FORMATETC *fmt, STGMEDIUM *stgmedium)
Definition: datacache.c:1269
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define CLSID_NULL
Definition: guiddef.h:99
LONG HRESULT
Definition: typedefs.h:79
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
struct PresentationDataHeader PresentationDataHeader
static HRESULT copy_stg_medium(CLIPFORMAT cf, STGMEDIUM *dest_stgm, const STGMEDIUM *src_stgm)
Definition: datacache.c:1139
const GUID IID_IUnknown
const CLSID CLSID_Picture_EnhMetafile
struct list cache_list
Definition: datacache.c:163
static HRESULT synthesize_bitmap(HGLOBAL dib, STGMEDIUM *med)
Definition: datacache.c:1203
static int bitmap_info_size(const BITMAPINFO *info, WORD coloruse)
Definition: datacache.c:228
#define WINAPI
Definition: msvc.h:6
const char file[]
Definition: icontest.c:11
BOOL clsid_static
Definition: datacache.c:158
unsigned short WORD
Definition: ntddk_ex.h:93
WINE_DEFAULT_DEBUG_CHANNEL(ole)
unsigned long DWORD
Definition: ntddk_ex.h:95
static BOOL entry_updatable(DataCacheEntry *entry, DWORD mode)
Definition: datacache.c:2604
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
static DataCache * DataCache_Construct(REFCLSID clsid, LPUNKNOWN pUnkOuter)
Definition: datacache.c:2967
static HRESULT WINAPI DataCache_IsDirty(IPersistStorage *iface)
Definition: datacache.c:1692
void check(CONTEXT *pContext)
Definition: NtContinue.c:68
static HRESULT setup_sink(DataCache *This, DataCacheEntry *cache_entry)
Definition: datacache.c:2424
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
#define DV_E_TYMED
Definition: winerror.h:2638
static void WINAPI DataCache_OnViewChange(IAdviseSink *iface, DWORD aspect, LONG index)
Definition: datacache.c:2855
HBITMAP WINAPI CreateDIBitmap(_In_ HDC hdc, _In_opt_ const BITMAPINFOHEADER *pbmih, _In_ DWORD fdwInit, _In_opt_ const VOID *pvInit, _In_opt_ const BITMAPINFO *pbmi, _In_ UINT uUsage)
static HRESULT WINAPI DataCache_Uncache(IOleCache2 *iface, DWORD dwConnection)
Definition: datacache.c:2494
REFCLSID clsid
Definition: msctf.c:82
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
#define InterlockedDecrement
Definition: armddk.h:52
Definition: parse.h:22
static HRESULT WINAPI DataCache_Load(IPersistStorage *iface, IStorage *stg)
Definition: datacache.c:1832
HDC hdc
Definition: main.c:9
static HRESULT WINAPI DataCache_GetColorSet(IViewObject2 *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
Definition: datacache.c:2143
GLuint GLuint stream
Definition: glext.h:7522
static DWORD tymed_from_cf(DWORD cf)
Definition: datacache.c:1292
#define MM_ANISOTROPIC
Definition: wingdi.h:866
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
static HRESULT WINAPI DataCache_Draw(IViewObject2 *iface, DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, BOOL(CALLBACK *pfnContinue)(ULONG_PTR dwContinue), ULONG_PTR dwContinue)
Definition: datacache.c:2006
Definition: stat.h:55
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(IViewObject2 *iface, REFIID riid, void **ppvObject)
Definition: datacache.c:1968
Definition: _list.h:228
REFIID LPVOID * ppvObject
Definition: precomp.h:44
static HRESULT check_valid_formatetc(const FORMATETC *fmt)
Definition: datacache.c:340
#define E_ABORT
Definition: winerror.h:2366
GLenum mode
Definition: glext.h:6217
#define STGM_READWRITE
Definition: objbase.h:918
static ULONG WINAPI DataCache_IOleCache2_Release(IOleCache2 *iface)
Definition: datacache.c:2411
DWORD advise_flags
Definition: datacache.c:115
unsigned char BYTE
Definition: xxhash.c:193
UINT WINAPI RegisterClipboardFormatA(_In_ LPCSTR)
static ULONG WINAPI DataCache_IOleCache2_AddRef(IOleCache2 *iface)
Definition: datacache.c:2400
static ULONG WINAPI DataCache_NDIUnknown_AddRef(IUnknown *iface)
Definition: datacache.c:1427
static HRESULT read_clipformat(IStream *stream, CLIPFORMAT *clipformat)
Definition: datacache.c:461
DWORD sinkAdviseFlag
Definition: datacache.c:153
static HRESULT synthesize_dib(HBITMAP bm, STGMEDIUM *med)
Definition: datacache.c:1175
static const IUnknownVtbl DataCache_NDIUnknown_VTable
Definition: datacache.c:2878
static HRESULT get_static_entry(DataCache *cache, DataCacheEntry **cache_entry)
Definition: datacache.c:316
static ULONG WINAPI DataCache_IDataObject_AddRef(IDataObject *iface)
Definition: datacache.c:1474
HRESULT WINAPI CreateDataCache(LPUNKNOWN pUnkOuter, REFCLSID rclsid, REFIID riid, LPVOID *ppvObj)
Definition: datacache.c:3035
#define OLE_E_ADVISENOTSUPPORTED
Definition: winerror.h:2617
static ULONG WINAPI DataCache_IPersistStorage_AddRef(IPersistStorage *iface)
Definition: datacache.c:1656
const GUID IID_IOleCache2
DWORD sinkAspects
Definition: datacache.c:152
_CRTIMP int __cdecl stat(const char *_Filename, struct stat *_Stat)
Definition: stat.h:345
static HRESULT WINAPI DataCache_Cache(IOleCache2 *iface, FORMATETC *pformatetc, DWORD advf, DWORD *pdwConnection)
Definition: datacache.c:2439
struct DataCacheEntry DataCacheEntry
#define S_OK
Definition: intsafe.h:51
#define CACHE_S_SAMECACHE
Definition: winerror.h:2707
static DataCache * impl_from_IPersistStorage(IPersistStorage *iface)
Definition: datacache.c:191
#define CACHE_E_NOCACHE_UPDATED
Definition: winerror.h:2712
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
#define InterlockedIncrement
Definition: armddk.h:53
const CLSID CLSID_Picture_Metafile
LONG ref
Definition: datacache.c:140
#define CACHE_S_FORMATETC_NOTSUPPORTED
Definition: winerror.h:2706
const GUID IID_IViewObject2
static const IViewObject2Vtbl DataCache_IViewObject2_VTable
Definition: datacache.c:2915
static HRESULT DataCache_CreateEntry(DataCache *This, const FORMATETC *formatetc, DWORD advf, BOOL automatic, DataCacheEntry **cache_entry)
Definition: datacache.c:381
static HRESULT WINAPI DataCache_InitNew(IPersistStorage *iface, IStorage *pStg)
Definition: datacache.c:1716
#define OLE_E_BLANK
Definition: winerror.h:2621
static HRESULT DataCacheEntry_DiscardData(DataCacheEntry *cache_entry)
Definition: datacache.c:1286
#define ARRAY_SIZE(a)
Definition: main.h:24
struct tagBITMAPFILEHEADER BITMAPFILEHEADER
#define E_NOTIMPL
Definition: ddrawi.h:99
HMETAFILE WINAPI CopyMetaFileW(_In_ HMETAFILE hmfSrc, _In_opt_ LPCWSTR pszFile)
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
HRESULT WINAPI ReadClassStg(IStorage *pstg, CLSID *pclsid)
Definition: storage32.c:9103
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
static HRESULT WINAPI DataCache_UpdateCache(IOleCache2 *iface, IDataObject *data, DWORD mode, void *reserved)
Definition: datacache.c:2619
UINT WINAPI GetWinMetaFileBits(_In_ HENHMETAFILE hemf, _In_ UINT cbData16, _Out_writes_bytes_opt_(cbData16) LPBYTE pData16, _In_ INT iMapMode, _In_ HDC hdcRef)
unsigned int UINT
Definition: ndis.h:50
static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry, IStorage *stg)
Definition: datacache.c:831
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(IPersistStorage *iface, REFIID riid, void **ppvObject)
Definition: datacache.c:1643
static HRESULT WINAPI DataCache_IOleCache2_SetData(IOleCache2 *iface, FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
Definition: datacache.c:2575
static HRESULT WINAPI DataCache_EnumFormatEtc(IDataObject *iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
Definition: datacache.c:1584
static const BYTE dib[]
Definition: ole2.c:201
static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry, const FORMATETC *formatetc, STGMEDIUM *stgmedium, BOOL fRelease)
Definition: datacache.c:1224
#define E_UNEXPECTED
Definition: winerror.h:2456
static void WINAPI DataCache_OnRename(IAdviseSink *iface, IMoniker *mk)
Definition: datacache.c:2860
#define skip(...)
Definition: atltest.h:64
IUnknown IUnknown_inner
Definition: datacache.c:126
static HRESULT WINAPI DataCache_DUnadvise(IDataObject *iface, DWORD dwConnection)
Definition: datacache.c:1614
int WINAPI GetDIBits(_In_ HDC hdc, _In_ HBITMAP hbm, _In_ UINT start, _In_ UINT cLines, _Out_opt_ LPVOID lpvBits, _At_((LPBITMAPINFOHEADER) lpbmi, _Inout_) LPBITMAPINFO lpbmi, _In_ UINT usage)
Definition: name.c:38
static HRESULT WINAPI DataCache_Unfreeze(IViewObject2 *iface, DWORD dwFreeze)
Definition: datacache.c:2167
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
static HRESULT WINAPI DataCache_IDataObject_SetData(IDataObject *iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
Definition: datacache.c:1556
unsigned int ULONG
Definition: retypes.h:1
static ULONG WINAPI DataCache_IOleCacheControl_AddRef(IOleCacheControl *iface)
Definition: datacache.c:2747
GLenum GLuint id
Definition: glext.h:5579
static DataCache * impl_from_IUnknown(IUnknown *iface)
Definition: datacache.c:186
static const WCHAR CONTENTS[]
Definition: datacache.c:533
static BOOL init_cache_entry(DataCacheEntry *entry, const FORMATETC *fmt, DWORD advf, DWORD id)
Definition: datacache.c:361
IDataObject * running_object
Definition: datacache.c:169
HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data, BOOL copy, IEnumSTATDATA **ppenum) DECLSPEC_HIDDEN
Definition: oleobj.c:197
#define STREAM_NUMBER_NOT_SET
Definition: datacache.c:92
#define LOGPIXELSY
Definition: wingdi.h:718
static HRESULT parse_pres_streams(DataCache *cache, IStorage *stg)
Definition: datacache.c:1767
static HRESULT create_automatic_entry(DataCache *cache, const CLSID *clsid)
Definition: datacache.c:1312
static void DataCache_FireOnViewChange(DataCache *this, DWORD aspect, LONG lindex)
Definition: datacache.c:425
static HBITMAP
Definition: button.c:44
static HRESULT open_pres_stream(IStorage *stg, int stream_number, IStream **stm)
Definition: datacache.c:535
IStorage * presentationStorage
Definition: datacache.c:160
BOOL WINAPI SetViewportExtEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPSIZE)
Definition: coord.c:465
#define LIST_ENTRY(type)
Definition: queue.h:175
IOleCacheControl IOleCacheControl_iface
Definition: datacache.c:131
#define DIB_RGB_COLORS
Definition: wingdi.h:366
#define E_POINTER
Definition: winerror.h:2365
STGMEDIUM stgmedium
Definition: datacache.c:101
static HRESULT synthesize_emf(HMETAFILEPICT data, STGMEDIUM *med)
Definition: datacache.c:549
UINT WINAPI GetMetaFileBitsEx(_In_ HMETAFILE hMF, _In_ UINT cbBuffer, _Out_writes_bytes_opt_(cbBuffer) LPVOID lpData)
static const IOleCache2Vtbl DataCache_IOleCache2_VTable
Definition: datacache.c:2929
static void init_stream_header(DataCacheEntry *entry, PresentationDataHeader *header)
Definition: datacache.c:863
static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppvObject)
Definition: datacache.c:1367
#define memset(x, y, z)
Definition: compat.h:39
static HRESULT load_dib(DataCacheEntry *cache_entry, IStream *stm)
Definition: datacache.c:666
static HRESULT WINAPI DataCache_GetDataHere(IDataObject *iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
Definition: datacache.c:1517
#define IsEqualCLSID(rclsid1, rclsid2)
Definition: guiddef.h:96
LONG cy
Definition: windef.h:335
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
static const IAdviseSinkVtbl DataCache_IAdviseSink_VTable
Definition: datacache.c:2952
DWORD reserved
Definition: datacache.c:579
Definition: dsound.c:943
IOleCache2 IOleCache2_iface
Definition: datacache.c:130
#define HeapFree(x, y, z)
Definition: compat.h:594
static ULONG WINAPI DataCache_IPersistStorage_Release(IPersistStorage *iface)
Definition: datacache.c:1667
#define MulDiv(x, y, z)
Definition: gdifloat.h:86
#define GMEM_MOVEABLE
Definition: winbase.h:291
BOOL WINAPI PlayMetaFile(_In_ HDC, _In_ HMETAFILE)
#define SRCCOPY
Definition: wingdi.h:332
struct CFHEADER header
Definition: fdi.c:101
static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storage, BOOL same_as_load)
Definition: datacache.c:1101
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
IAdviseSink * sinkInterface
Definition: datacache.c:154
const GUID IID_IOleCache
static HRESULT save_emf(DataCacheEntry *entry, BOOL contents, IStream *stream)
Definition: datacache.c:1016
int WINAPI GetClipboardFormatNameA(_In_ UINT format, _Out_writes_(cchMaxCount) LPSTR lpszFormatName, _In_ int cchMaxCount)
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
static DataCache * impl_from_IAdviseSink(IAdviseSink *iface)
Definition: datacache.c:211
#define SUCCEEDED(hr)
Definition: intsafe.h:49
static HRESULT WINAPI DataCache_QueryGetData(IDataObject *iface, FORMATETC *fmt)
Definition: datacache.c:1526
Definition: fci.c:126
#define CF_DIB
Definition: constants.h:403
GLuint const GLchar * name
Definition: glext.h:6031
static const BYTE masks[8]
Definition: dib.c:2760