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