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:
Sergio Gómez Del Real 2017-12-06 10:52:23 -05:00 committed by Alexandre Julliard
parent 756f781786
commit 07af05fa80
1 changed files with 119 additions and 120 deletions

View File

@ -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)
* *