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