ReactOS  0.4.11-dev-745-g76daaf9
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 
261  HeapFree(GetProcessHeap(), 0, cache_entry);
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 
303  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
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  {
327  entry = LIST_ENTRY( head, DataCacheEntry, entry );
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;
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:
414  HeapFree(GetProcessHeap(), 0, entry);
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  {
741  info = (BITMAPINFOHEADER *)dib;
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;
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 
894  init_stream_header(entry, &header);
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 
947  init_stream_header(entry, &header);
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);
971  HeapFree(GetProcessHeap(), 0, data);
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 
1029  init_stream_header(entry, &header);
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 
1075  init_stream_header(entry, &header);
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 
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:
1127  hr = save_view_cache(cache_entry, stream);
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  {
1274  HRESULT hr = DataCacheEntry_LoadData(cache_entry, stg);
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  {
1335  entry = LIST_ENTRY( head, DataCacheEntry, entry );
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) ||
1392  IsEqualIID(&IID_IPersist, riid) )
1393  {
1394  *ppvObject = &this->IPersistStorage_iface;
1395  }
1396  else if ( IsEqualIID(&IID_IViewObject, riid) ||
1397  IsEqualIID(&IID_IViewObject2, riid) )
1398  {
1399  *ppvObject = &this->IViewObject2_iface;
1400  }
1401  else if ( IsEqualIID(&IID_IOleCache, riid) ||
1402  IsEqualIID(&IID_IOleCache2, 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 {
1504  DataCache *This = impl_from_IDataObject(iface);
1506 
1507  TRACE("(%p, %s, %p)\n", iface, debugstr_formatetc(pformatetcIn), pmedium);
1508 
1509  memset(pmedium, 0, sizeof(*pmedium));
1510 
1511  cache_entry = DataCache_GetEntryForFormatEtc(This, pformatetcIn);
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 ) );
1533  cache_entry = DataCache_GetEntryForFormatEtc( This, 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 {
1682  DataCache *This = impl_from_IPersistStorage( iface );
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 {
1696  DataCache *This = impl_from_IPersistStorage(iface);
1698 
1699  TRACE("(%p)\n", iface);
1700 
1701  if (This->dirty)
1702  return S_OK;
1703 
1704  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
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 {
1721  DataCache *This = impl_from_IPersistStorage(iface);
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 
1755  cache_entry = DataCache_GetEntryForFormatEtc( This, fmt );
1756  if (!cache_entry)
1757  hr = DataCache_CreateEntry( This, fmt, advf, FALSE, &cache_entry );
1758  if (SUCCEEDED( hr ))
1759  {
1760  DataCacheEntry_DiscardData( cache_entry );
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 
1813  hr = get_static_entry( cache, &cache_entry );
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 {
1835  DataCache *This = impl_from_IPersistStorage(iface);
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 )
1845  DataCacheEntry_Destroy( This, 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 {
1882  DataCache *This = impl_from_IPersistStorage(iface);
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 */
1890  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
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 */
1901  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
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),
2018  ULONG_PTR dwContinue)
2019 {
2020  DataCache *This = impl_from_IViewObject2(iface);
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 
2039  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
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 
2080  SetWindowExtEx(hdcDraw,
2081  mfpict->xExt,
2082  mfpict->yExt,
2083  &oldWindowExt);
2084 
2085  SetViewportExtEx(hdcDraw,
2086  lprcBounds->right - lprcBounds->left,
2087  lprcBounds->bottom - lprcBounds->top,
2088  &oldViewportExt);
2089 
2090  SetViewportOrgEx(hdcDraw,
2091  lprcBounds->left,
2092  lprcBounds->top,
2093  &oldViewportOrg);
2094 
2095  PlayMetaFile(hdcDraw, mfpict->hMF);
2096 
2097  SetWindowExtEx(hdcDraw,
2098  oldWindowExt.cx,
2099  oldWindowExt.cy,
2100  NULL);
2101 
2102  SetViewportExtEx(hdcDraw,
2103  oldViewportExt.cx,
2104  oldViewportExt.cy,
2105  NULL);
2106 
2107  SetViewportOrgEx(hdcDraw,
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 
2127  bits = (BYTE *) info + bitmap_info_size( info, DIB_RGB_COLORS );
2128  StretchDIBits( hdcDraw, lprcBounds->left, lprcBounds->top,
2129  lprcBounds->right - lprcBounds->left, lprcBounds->bottom - lprcBounds->top,
2130  0, 0, info->bmiHeader.biWidth, info->bmiHeader.biHeight,
2131  bits, info, DIB_RGB_COLORS, SRCCOPY );
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,
2146  DWORD dwDrawAspect,
2147  LONG lindex,
2148  void* pvAspect,
2149  DVTARGETDEVICE* ptd,
2150  HDC hicTargetDevice,
2151  LOGPALETTE** ppColorSet)
2152 {
2153  FIXME("stub\n");
2154  return E_NOTIMPL;
2155 }
2156 
2158  IViewObject2* iface,
2159  DWORD dwDrawAspect,
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,
2271  DWORD dwDrawAspect,
2272  LONG lindex,
2273  DVTARGETDEVICE* ptd,
2274  LPSIZEL lpsizel)
2275 {
2276  DataCache *This = impl_from_IViewObject2(iface);
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 
2299  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
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 {
2446  DataCache *This = impl_from_IOleCache2(iface);
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 
2474  cache_entry = DataCache_GetEntryForFormatEtc(This, &fmt_cpy);
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;
2489  setup_sink(This, cache_entry);
2490  }
2491 
2492  return hr;
2493 }
2494 
2496  IOleCache2* iface,
2497  DWORD dwConnection)
2498 {
2499  DataCache *This = impl_from_IOleCache2(iface);
2501 
2502  TRACE("(%d)\n", dwConnection);
2503 
2504  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
2505  if (cache_entry->id == dwConnection)
2506  {
2507  DataCacheEntry_Destroy(This, cache_entry);
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 
2527  LIST_FOR_EACH_ENTRY( cache_entry, &This->cache_list, DataCacheEntry, entry )
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 
2537  LIST_FOR_EACH_ENTRY( cache_entry, &This->cache_list, DataCacheEntry, entry )
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 {
2582  DataCache *This = impl_from_IOleCache2(iface);
2584  HRESULT hr;
2585 
2586  TRACE("(%p, %p, %s)\n", pformatetc, pmedium, fRelease ? "TRUE" : "FALSE");
2587  TRACE("formatetc = %s\n", debugstr_formatetc(pformatetc));
2588 
2589  cache_entry = DataCache_GetEntryForFormatEtc(This, pformatetc);
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 {
2623  DataCache *This = impl_from_IOleCache2(iface);
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 
2634  LIST_FOR_EACH_ENTRY( cache_entry, &This->cache_list, DataCacheEntry, entry )
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 {
2707  DataCache *This = impl_from_IOleCache2(iface);
2709  HRESULT hr = S_OK;
2710 
2711  TRACE("(%d)\n", dwDiscardOptions);
2712 
2713  if (dwDiscardOptions == DISCARDCACHE_SAVEIFDIRTY)
2715 
2716  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
2717  {
2718  hr = DataCacheEntry_DiscardData(cache_entry);
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 {
2772  DataCache *This = impl_from_IOleCacheControl(iface);
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 
2782  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
2783  {
2784  setup_sink(This, cache_entry);
2785  }
2786 
2787  return S_OK;
2788 }
2789 
2790 /************************************************************************
2791  * DataCache_OnStop (IOleCacheControl)
2792  */
2794 {
2795  DataCache *This = impl_from_IOleCacheControl(iface);
2797 
2798  TRACE("(%p)\n", iface);
2799 
2800  if(!This->running_object) return S_OK;
2801 
2802  LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
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 {
2851  DataCache *This = impl_from_IAdviseSink(iface);
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
HANDLE HGLOBAL
Definition: windef.h:243
#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:2585
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:716
BOOL WINAPI SetViewportOrgEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
Definition: coord.c:648
unsigned short WORD
Definition: ntddk_ex.h:93
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
const GUID IID_IUnknown
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:1453
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
static const char * contents
Definition: parser.c:505
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
static void DataCache_Destroy(DataCache *ptrToDestroy)
Definition: datacache.c:264
#define REFCLSID
Definition: guiddef.h:112
LONG biXPelsPerMeter
Definition: amvideo.idl:37
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
long bottom
Definition: polytest.cpp:53
HENHMETAFILE WINAPI SetEnhMetaFileBits(_In_ UINT nSize, _In_reads_bytes_(nSize) const BYTE *pb)
static HRESULT add_cache_entry(DataCache *This, const FORMATETC *fmt, DWORD advf, int stream_number)
Definition: datacache.c: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
#define DWORD
Definition: msvc.h:34
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
DWORD DWORD
Definition: winlogon.h:84
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
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:363
GLuint const GLchar * name
Definition: glext.h:6031
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
long right
Definition: polytest.cpp:53
#define OLE_E_NOCONNECTION
Definition: winerror.h:2618
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
UINT WINAPI GetEnhMetaFileBits(_In_ HENHMETAFILE hEMF, _In_ UINT nSize, _Out_writes_bytes_opt_(nSize) LPBYTE lpData)
GLenum GLclampf GLint i
Definition: glfuncs.h:14
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
#define FALSE
Definition: types.h:117
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
long top
Definition: polytest.cpp:53
GLenum GLint ref
Definition: glext.h:6028
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define FIXME(fmt,...)
Definition: debug.h:110
DWORD biCompression
Definition: amvideo.idl:35
static PVOID ptr
Definition: dispmode.c:27
r reserved
Definition: btrfs.c:2640
#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
static const GLubyte size_bits[5]
Definition: m_vector.c:58
WORD bounding_box[4]
Definition: datacache.c:578
LONG cx
Definition: windef.h:324
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
long left
Definition: polytest.cpp:53
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static ULONG WINAPI DataCache_IViewObject2_AddRef(IViewObject2 *iface)
Definition: datacache.c: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 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
WINE_DEFAULT_DEBUG_CHANNEL(ole)
static BOOL entry_updatable(DataCacheEntry *entry, DWORD mode)
Definition: datacache.c:2605
DWORD LONG void DVTARGETDEVICE HDC hdcDraw
Definition: msvc.h:93
GLuint GLuint GLsizei count
Definition: gl.h:1545
DWORD biSizeImage
Definition: amvideo.idl:36
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:865
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
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
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
#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
unsigned char BYTE
Definition: ntddk_ex.h:96
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
const XML_Char XML_Encoding * info
Definition: expat.h:530
#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)
unsigned int UINT
Definition: ndis.h:50
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:717
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:365
#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:325
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:331
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
LONGLONG QuadPart
Definition: typedefs.h:112
static HRESULT WINAPI DataCache_QueryGetData(IDataObject *iface, FORMATETC *fmt)
Definition: datacache.c:1527
#define CF_DIB
Definition: constants.h:403
static const BYTE masks[8]
Definition: dib.c:2760