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