ole32: Refactor OLE's data cache Save implementation.
Signed-off-by: Sergio Gómez Del Real <sdelreal@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
756f781786
commit
07af05fa80
|
@ -775,75 +775,36 @@ static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT DataCacheEntry_CreateStream(DataCacheEntry *cache_entry,
|
static void init_stream_header(DataCacheEntry *entry, PresentationDataHeader *header)
|
||||||
IStorage *storage, IStream **stream)
|
|
||||||
{
|
{
|
||||||
WCHAR wszName[] = {2,'O','l','e','P','r','e','s',
|
if (entry->fmtetc.ptd)
|
||||||
'0' + (cache_entry->stream_number / 100) % 10,
|
FIXME("ptd not serialized\n");
|
||||||
'0' + (cache_entry->stream_number / 10) % 10,
|
header->tdSize = sizeof(header->tdSize);
|
||||||
'0' + cache_entry->stream_number % 10, 0};
|
header->dvAspect = entry->fmtetc.dwAspect;
|
||||||
|
header->lindex = entry->fmtetc.lindex;
|
||||||
/* FIXME: cache the created stream in This? */
|
header->advf = entry->advise_flags;
|
||||||
return IStorage_CreateStream(storage, wszName,
|
header->unknown7 = 0;
|
||||||
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
|
header->dwObjectExtentX = 0;
|
||||||
0, 0, stream);
|
header->dwObjectExtentY = 0;
|
||||||
|
header->dwSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storage,
|
static HRESULT save_dib(DataCacheEntry *entry, BOOL contents, IStream *stream)
|
||||||
BOOL same_as_load)
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
int data_size = GlobalSize(entry->stgmedium.u.hGlobal);
|
||||||
|
BITMAPINFO *bmi = GlobalLock(entry->stgmedium.u.hGlobal);
|
||||||
|
|
||||||
|
if (!contents)
|
||||||
{
|
{
|
||||||
PresentationDataHeader header;
|
PresentationDataHeader header;
|
||||||
HRESULT hr;
|
|
||||||
IStream *pres_stream;
|
|
||||||
void *data = NULL;
|
|
||||||
|
|
||||||
TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->stream_number, debugstr_formatetc(&cache_entry->fmtetc));
|
init_stream_header(entry, &header);
|
||||||
|
hr = write_clipformat(stream, entry->fmtetc.cfFormat);
|
||||||
hr = DataCacheEntry_CreateStream(cache_entry, storage, &pres_stream);
|
if (FAILED(hr)) goto end;
|
||||||
if (FAILED(hr))
|
if (data_size)
|
||||||
return hr;
|
|
||||||
|
|
||||||
hr = write_clipformat(pres_stream, cache_entry->fmtetc.cfFormat);
|
|
||||||
if (FAILED(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
if (cache_entry->fmtetc.ptd)
|
|
||||||
FIXME("ptd not serialized\n");
|
|
||||||
header.tdSize = sizeof(header.tdSize);
|
|
||||||
header.dvAspect = cache_entry->fmtetc.dwAspect;
|
|
||||||
header.lindex = cache_entry->fmtetc.lindex;
|
|
||||||
header.advf = cache_entry->advise_flags;
|
|
||||||
header.unknown7 = 0;
|
|
||||||
header.dwObjectExtentX = 0;
|
|
||||||
header.dwObjectExtentY = 0;
|
|
||||||
header.dwSize = 0;
|
|
||||||
|
|
||||||
/* size the data */
|
|
||||||
switch (cache_entry->fmtetc.cfFormat)
|
|
||||||
{
|
{
|
||||||
case CF_METAFILEPICT:
|
header.dwSize = data_size;
|
||||||
{
|
|
||||||
if (cache_entry->stgmedium.tymed != TYMED_NULL)
|
|
||||||
{
|
|
||||||
const METAFILEPICT *mfpict = GlobalLock(cache_entry->stgmedium.u.hMetaFilePict);
|
|
||||||
if (!mfpict)
|
|
||||||
{
|
|
||||||
IStream_Release(pres_stream);
|
|
||||||
return DV_E_STGMEDIUM;
|
|
||||||
}
|
|
||||||
header.dwObjectExtentX = mfpict->xExt;
|
|
||||||
header.dwObjectExtentY = mfpict->yExt;
|
|
||||||
header.dwSize = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
|
|
||||||
GlobalUnlock(cache_entry->stgmedium.u.hMetaFilePict);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CF_DIB:
|
|
||||||
{
|
|
||||||
header.dwSize = GlobalSize(cache_entry->stgmedium.u.hGlobal);
|
|
||||||
if (header.dwSize)
|
|
||||||
{
|
|
||||||
const BITMAPINFO *bmi = GlobalLock(cache_entry->stgmedium.u.hGlobal);
|
|
||||||
/* Size in units of 0.01mm (ie. MM_HIMETRIC) */
|
/* Size in units of 0.01mm (ie. MM_HIMETRIC) */
|
||||||
if (bmi->bmiHeader.biXPelsPerMeter != 0 && bmi->bmiHeader.biYPelsPerMeter != 0)
|
if (bmi->bmiHeader.biXPelsPerMeter != 0 && bmi->bmiHeader.biYPelsPerMeter != 0)
|
||||||
{
|
{
|
||||||
|
@ -857,65 +818,105 @@ static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storag
|
||||||
header.dwObjectExtentY = MulDiv(bmi->bmiHeader.biHeight, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
|
header.dwObjectExtentY = MulDiv(bmi->bmiHeader.biHeight, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
|
||||||
ReleaseDC(0, hdc);
|
ReleaseDC(0, hdc);
|
||||||
}
|
}
|
||||||
GlobalUnlock(cache_entry->stgmedium.u.hGlobal);
|
|
||||||
}
|
}
|
||||||
break;
|
hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
|
||||||
}
|
if (hr == S_OK && data_size)
|
||||||
default:
|
hr = IStream_Write(stream, bmi, data_size, NULL);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
end:
|
||||||
* Write the header.
|
if (bmi) GlobalUnlock(entry->stgmedium.u.hGlobal);
|
||||||
*/
|
|
||||||
hr = IStream_Write(pres_stream, &header, sizeof(PresentationDataHeader),
|
|
||||||
NULL);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
IStream_Release(pres_stream);
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the data */
|
static HRESULT save_mfpict(DataCacheEntry *entry, BOOL contents, IStream *stream)
|
||||||
switch (cache_entry->fmtetc.cfFormat)
|
|
||||||
{
|
{
|
||||||
case CF_METAFILEPICT:
|
HRESULT hr = S_OK;
|
||||||
|
int data_size = 0;
|
||||||
|
void *data = NULL;
|
||||||
|
METAFILEPICT *mfpict = NULL;
|
||||||
|
|
||||||
|
if (!contents)
|
||||||
{
|
{
|
||||||
if (cache_entry->stgmedium.tymed != TYMED_NULL)
|
PresentationDataHeader header;
|
||||||
|
|
||||||
|
init_stream_header(entry, &header);
|
||||||
|
hr = write_clipformat(stream, entry->fmtetc.cfFormat);
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
if (entry->stgmedium.tymed != TYMED_NULL)
|
||||||
{
|
{
|
||||||
const METAFILEPICT *mfpict = GlobalLock(cache_entry->stgmedium.u.hMetaFilePict);
|
mfpict = GlobalLock(entry->stgmedium.u.hMetaFilePict);
|
||||||
if (!mfpict)
|
if (!mfpict)
|
||||||
{
|
|
||||||
IStream_Release(pres_stream);
|
|
||||||
return DV_E_STGMEDIUM;
|
return DV_E_STGMEDIUM;
|
||||||
}
|
data_size = GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
|
||||||
if (header.dwSize)
|
header.dwObjectExtentX = mfpict->xExt;
|
||||||
{
|
header.dwObjectExtentY = mfpict->yExt;
|
||||||
|
header.dwSize = data_size;
|
||||||
data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
|
data = HeapAlloc(GetProcessHeap(), 0, header.dwSize);
|
||||||
GetMetaFileBitsEx(mfpict->hMF, header.dwSize, data);
|
if (!data)
|
||||||
GlobalUnlock(cache_entry->stgmedium.u.hMetaFilePict);
|
|
||||||
if (data)
|
|
||||||
{
|
{
|
||||||
hr = IStream_Write(pres_stream, data, header.dwSize, NULL);
|
GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
GetMetaFileBitsEx(mfpict->hMF, header.dwSize, data);
|
||||||
|
GlobalUnlock(entry->stgmedium.u.hMetaFilePict);
|
||||||
|
}
|
||||||
|
hr = IStream_Write(stream, &header, sizeof(PresentationDataHeader), NULL);
|
||||||
|
if (hr == S_OK && data_size)
|
||||||
|
hr = IStream_Write(stream, data, data_size, NULL);
|
||||||
HeapFree(GetProcessHeap(), 0, data);
|
HeapFree(GetProcessHeap(), 0, data);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
return hr;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CF_DIB:
|
|
||||||
{
|
|
||||||
data = GlobalLock(cache_entry->stgmedium.u.hGlobal);
|
|
||||||
if (header.dwSize)
|
|
||||||
hr = IStream_Write(pres_stream, data, header.dwSize, NULL);
|
|
||||||
GlobalUnlock(cache_entry->stgmedium.u.hGlobal);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IStream_Release(pres_stream);
|
static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
|
||||||
|
|
||||||
|
static HRESULT create_stream(DataCacheEntry *cache_entry, IStorage *storage,
|
||||||
|
BOOL contents, IStream **stream)
|
||||||
|
{
|
||||||
|
WCHAR pres[] = {2,'O','l','e','P','r','e','s',
|
||||||
|
'0' + (cache_entry->stream_number / 100) % 10,
|
||||||
|
'0' + (cache_entry->stream_number / 10) % 10,
|
||||||
|
'0' + cache_entry->stream_number % 10, 0};
|
||||||
|
const WCHAR *name;
|
||||||
|
|
||||||
|
if (contents)
|
||||||
|
name = CONTENTS;
|
||||||
|
else
|
||||||
|
name = pres;
|
||||||
|
|
||||||
|
return IStorage_CreateStream(storage, name,
|
||||||
|
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
|
||||||
|
0, 0, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storage,
|
||||||
|
BOOL same_as_load)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
IStream *stream;
|
||||||
|
BOOL contents = (cache_entry->id == 1);
|
||||||
|
|
||||||
|
TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->stream_number, debugstr_formatetc(&cache_entry->fmtetc));
|
||||||
|
|
||||||
|
hr = create_stream(cache_entry, storage, contents, &stream);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
switch (cache_entry->fmtetc.cfFormat)
|
||||||
|
{
|
||||||
|
case CF_DIB:
|
||||||
|
hr = save_dib(cache_entry, contents, stream);
|
||||||
|
break;
|
||||||
|
case CF_METAFILEPICT:
|
||||||
|
hr = save_mfpict(cache_entry, contents, stream);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("got unsupported clipboard format %x\n", cache_entry->fmtetc.cfFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
IStream_Release(stream);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1651,8 +1652,6 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage *stg, IStream *s
|
||||||
return add_cache_entry( This, fmt, 0, stm, contents_stream );
|
return add_cache_entry( This, fmt, 0, stm, contents_stream );
|
||||||
}
|
}
|
||||||
|
|
||||||
static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* DataCache_Load (IPersistStorage)
|
* DataCache_Load (IPersistStorage)
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue