ole32: Don't keep the streams open.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d877dce7a2
commit
57a5ab21f9
|
@ -90,12 +90,8 @@ typedef struct PresentationDataHeader
|
||||||
DWORD dwSize;
|
DWORD dwSize;
|
||||||
} PresentationDataHeader;
|
} PresentationDataHeader;
|
||||||
|
|
||||||
enum stream_type
|
#define STREAM_NUMBER_NOT_SET -2
|
||||||
{
|
#define STREAM_NUMBER_CONTENTS -1 /* CONTENTS stream */
|
||||||
no_stream,
|
|
||||||
pres_stream,
|
|
||||||
contents_stream
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct DataCacheEntry
|
typedef struct DataCacheEntry
|
||||||
{
|
{
|
||||||
|
@ -104,19 +100,16 @@ typedef struct DataCacheEntry
|
||||||
FORMATETC fmtetc;
|
FORMATETC fmtetc;
|
||||||
/* cached data */
|
/* cached data */
|
||||||
STGMEDIUM stgmedium;
|
STGMEDIUM stgmedium;
|
||||||
/*
|
|
||||||
* This stream pointer is set through a call to
|
|
||||||
* IPersistStorage_Load. This is where the visual
|
|
||||||
* representation of the object is stored.
|
|
||||||
*/
|
|
||||||
IStream *stream;
|
|
||||||
enum stream_type stream_type;
|
|
||||||
/* connection ID */
|
/* connection ID */
|
||||||
DWORD id;
|
DWORD id;
|
||||||
/* dirty flag */
|
/* dirty flag */
|
||||||
BOOL dirty;
|
BOOL dirty;
|
||||||
/* stream number (-1 if not set ) */
|
/* stream number that the entry was loaded from.
|
||||||
unsigned short stream_number;
|
This is used to defer loading until the data is actually needed. */
|
||||||
|
int load_stream_num;
|
||||||
|
/* stream number that the entry will be saved to.
|
||||||
|
This may differ from above if cache entries have been Uncache()d for example. */
|
||||||
|
int save_stream_num;
|
||||||
/* sink id set when object is running */
|
/* sink id set when object is running */
|
||||||
DWORD sink_id;
|
DWORD sink_id;
|
||||||
/* Advise sink flags */
|
/* Advise sink flags */
|
||||||
|
@ -260,8 +253,6 @@ static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
|
||||||
static void DataCacheEntry_Destroy(DataCache *cache, DataCacheEntry *cache_entry)
|
static void DataCacheEntry_Destroy(DataCache *cache, DataCacheEntry *cache_entry)
|
||||||
{
|
{
|
||||||
list_remove(&cache_entry->entry);
|
list_remove(&cache_entry->entry);
|
||||||
if (cache_entry->stream)
|
|
||||||
IStream_Release(cache_entry->stream);
|
|
||||||
CoTaskMemFree(cache_entry->fmtetc.ptd);
|
CoTaskMemFree(cache_entry->fmtetc.ptd);
|
||||||
ReleaseStgMedium(&cache_entry->stgmedium);
|
ReleaseStgMedium(&cache_entry->stgmedium);
|
||||||
if(cache_entry->sink_id)
|
if(cache_entry->sink_id)
|
||||||
|
@ -355,11 +346,10 @@ static BOOL init_cache_entry(DataCacheEntry *entry, const FORMATETC *fmt, DWORD
|
||||||
|
|
||||||
entry->stgmedium.tymed = TYMED_NULL;
|
entry->stgmedium.tymed = TYMED_NULL;
|
||||||
entry->stgmedium.pUnkForRelease = NULL;
|
entry->stgmedium.pUnkForRelease = NULL;
|
||||||
entry->stream = NULL;
|
|
||||||
entry->stream_type = no_stream;
|
|
||||||
entry->id = id;
|
entry->id = id;
|
||||||
entry->dirty = TRUE;
|
entry->dirty = TRUE;
|
||||||
entry->stream_number = -1;
|
entry->load_stream_num = STREAM_NUMBER_NOT_SET;
|
||||||
|
entry->save_stream_num = STREAM_NUMBER_NOT_SET;
|
||||||
entry->sink_id = 0;
|
entry->sink_id = 0;
|
||||||
entry->advise_flags = advf;
|
entry->advise_flags = advf;
|
||||||
|
|
||||||
|
@ -518,60 +508,18 @@ static HRESULT write_clipformat(IStream *stream, CLIPFORMAT clipformat)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
|
||||||
* DataCacheEntry_OpenPresStream
|
|
||||||
*
|
|
||||||
* This method will find the stream for the given presentation. It makes
|
|
||||||
* no attempt at fallback.
|
|
||||||
*
|
|
||||||
* Param:
|
|
||||||
* this - Pointer to the DataCache object
|
|
||||||
* drawAspect - The aspect of the object that we wish to draw.
|
|
||||||
* pStm - A returned stream. It points to the beginning of the
|
|
||||||
* - presentation data, including the header.
|
|
||||||
*
|
|
||||||
* Errors:
|
|
||||||
* S_OK The requested stream has been opened.
|
|
||||||
* OLE_E_BLANK The requested stream could not be found.
|
|
||||||
* Quite a few others I'm too lazy to map correctly.
|
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* Algorithm: Scan the elements of the presentation storage, looking
|
|
||||||
* for presentation streams. For each presentation stream,
|
|
||||||
* load the header and check to see if the aspect matches.
|
|
||||||
*
|
|
||||||
* If a fallback is desired, just opening the first presentation stream
|
|
||||||
* is a possibility.
|
|
||||||
*/
|
|
||||||
static HRESULT DataCacheEntry_OpenPresStream(DataCacheEntry *cache_entry, IStream **ppStm)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
LARGE_INTEGER offset;
|
|
||||||
|
|
||||||
if (cache_entry->stream)
|
|
||||||
{
|
|
||||||
/* Rewind the stream before returning it. */
|
|
||||||
offset.QuadPart = 0;
|
|
||||||
|
|
||||||
hr = IStream_Seek( cache_entry->stream, offset, STREAM_SEEK_SET, NULL );
|
|
||||||
if (SUCCEEDED( hr ))
|
|
||||||
{
|
|
||||||
*ppStm = cache_entry->stream;
|
|
||||||
IStream_AddRef( cache_entry->stream );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
hr = OLE_E_BLANK;
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT open_pres_stream( IStorage *stg, int stream_number, IStream **stm )
|
static HRESULT open_pres_stream( IStorage *stg, int stream_number, IStream **stm )
|
||||||
{
|
{
|
||||||
WCHAR name[] = {2,'O','l','e','P','r','e','s',
|
WCHAR pres[] = {2,'O','l','e','P','r','e','s',
|
||||||
'0' + (stream_number / 100) % 10,
|
'0' + (stream_number / 100) % 10,
|
||||||
'0' + (stream_number / 10) % 10,
|
'0' + (stream_number / 10) % 10,
|
||||||
'0' + stream_number % 10, 0};
|
'0' + stream_number % 10, 0};
|
||||||
|
const WCHAR *name = pres;
|
||||||
|
|
||||||
|
if (stream_number == STREAM_NUMBER_NOT_SET) return E_FAIL;
|
||||||
|
if (stream_number == STREAM_NUMBER_CONTENTS) name = CONTENTS;
|
||||||
|
|
||||||
return IStorage_OpenStream( stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
|
return IStorage_OpenStream( stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm );
|
||||||
}
|
}
|
||||||
|
@ -589,9 +537,9 @@ static HRESULT load_mf_pict( DataCacheEntry *cache_entry, IStream *stm )
|
||||||
static const LARGE_INTEGER offset_zero;
|
static const LARGE_INTEGER offset_zero;
|
||||||
ULONG read;
|
ULONG read;
|
||||||
|
|
||||||
if (cache_entry->stream_type != pres_stream)
|
if (cache_entry->load_stream_num == STREAM_NUMBER_CONTENTS)
|
||||||
{
|
{
|
||||||
FIXME( "Unimplemented for stream type %d\n", cache_entry->stream_type );
|
FIXME( "Unimplemented for CONTENTS stream\n" );
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,9 +606,9 @@ static HRESULT load_dib( DataCacheEntry *cache_entry, IStream *stm )
|
||||||
BITMAPFILEHEADER file;
|
BITMAPFILEHEADER file;
|
||||||
BITMAPINFOHEADER *info;
|
BITMAPINFOHEADER *info;
|
||||||
|
|
||||||
if (cache_entry->stream_type != contents_stream)
|
if (cache_entry->load_stream_num != STREAM_NUMBER_CONTENTS)
|
||||||
{
|
{
|
||||||
FIXME( "Unimplemented for stream type %d\n", cache_entry->stream_type );
|
FIXME( "Unimplemented for presentation stream\n" );
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,12 +694,13 @@ fail:
|
||||||
* This method returns a metafile handle if it is successful.
|
* This method returns a metafile handle if it is successful.
|
||||||
* it will return 0 if not.
|
* it will return 0 if not.
|
||||||
*/
|
*/
|
||||||
static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry)
|
static HRESULT DataCacheEntry_LoadData(DataCacheEntry *cache_entry, IStorage *stg)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
IStream *stm;
|
IStream *stm;
|
||||||
|
|
||||||
hr = DataCacheEntry_OpenPresStream( cache_entry, &stm );
|
if (!stg) return OLE_E_BLANK;
|
||||||
|
hr = open_pres_stream( stg, cache_entry->load_stream_num, &stm );
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
switch (cache_entry->fmtetc.cfFormat)
|
switch (cache_entry->fmtetc.cfFormat)
|
||||||
|
@ -1004,14 +953,13 @@ static HRESULT save_view_cache(DataCacheEntry *entry, IStream *stream)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0};
|
|
||||||
static HRESULT create_stream(DataCacheEntry *cache_entry, IStorage *storage,
|
static HRESULT create_stream(DataCacheEntry *cache_entry, IStorage *storage,
|
||||||
BOOL contents, IStream **stream)
|
BOOL contents, IStream **stream)
|
||||||
{
|
{
|
||||||
WCHAR pres[] = {2,'O','l','e','P','r','e','s',
|
WCHAR pres[] = {2,'O','l','e','P','r','e','s',
|
||||||
'0' + (cache_entry->stream_number / 100) % 10,
|
'0' + (cache_entry->save_stream_num / 100) % 10,
|
||||||
'0' + (cache_entry->stream_number / 10) % 10,
|
'0' + (cache_entry->save_stream_num / 10) % 10,
|
||||||
'0' + cache_entry->stream_number % 10, 0};
|
'0' + cache_entry->save_stream_num % 10, 0};
|
||||||
const WCHAR *name;
|
const WCHAR *name;
|
||||||
|
|
||||||
if (contents)
|
if (contents)
|
||||||
|
@ -1031,7 +979,7 @@ static HRESULT DataCacheEntry_Save(DataCacheEntry *cache_entry, IStorage *storag
|
||||||
IStream *stream;
|
IStream *stream;
|
||||||
BOOL contents = (cache_entry->id == 1);
|
BOOL contents = (cache_entry->id == 1);
|
||||||
|
|
||||||
TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->stream_number, debugstr_formatetc(&cache_entry->fmtetc));
|
TRACE("stream_number = %d, fmtetc = %s\n", cache_entry->save_stream_num, debugstr_formatetc(&cache_entry->fmtetc));
|
||||||
|
|
||||||
hr = create_stream(cache_entry, storage, contents, &stream);
|
hr = create_stream(cache_entry, storage, contents, &stream);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
|
@ -1216,11 +1164,11 @@ static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
|
||||||
return copy_stg_medium(cache_entry->fmtetc.cfFormat, &cache_entry->stgmedium, stgmedium);
|
return copy_stg_medium(cache_entry->fmtetc.cfFormat, &cache_entry->stgmedium, stgmedium);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, FORMATETC *fmt, STGMEDIUM *stgmedium)
|
static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, IStorage *stg, FORMATETC *fmt, STGMEDIUM *stgmedium)
|
||||||
{
|
{
|
||||||
if (cache_entry->stgmedium.tymed == TYMED_NULL && cache_entry->stream)
|
if (cache_entry->stgmedium.tymed == TYMED_NULL && cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET)
|
||||||
{
|
{
|
||||||
HRESULT hr = DataCacheEntry_LoadData(cache_entry);
|
HRESULT hr = DataCacheEntry_LoadData(cache_entry, stg);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -1239,15 +1187,6 @@ static inline HRESULT DataCacheEntry_DiscardData(DataCacheEntry *cache_entry)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void DataCacheEntry_HandsOffStorage(DataCacheEntry *cache_entry)
|
|
||||||
{
|
|
||||||
if (cache_entry->stream)
|
|
||||||
{
|
|
||||||
IStream_Release(cache_entry->stream);
|
|
||||||
cache_entry->stream = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline DWORD tymed_from_cf( DWORD cf )
|
static inline DWORD tymed_from_cf( DWORD cf )
|
||||||
{
|
{
|
||||||
switch( cf )
|
switch( cf )
|
||||||
|
@ -1470,7 +1409,7 @@ static HRESULT WINAPI DataCache_GetData(
|
||||||
if (!cache_entry)
|
if (!cache_entry)
|
||||||
return OLE_E_BLANK;
|
return OLE_E_BLANK;
|
||||||
|
|
||||||
return DataCacheEntry_GetData(cache_entry, pformatetcIn, pmedium);
|
return DataCacheEntry_GetData(cache_entry, This->presentationStorage, pformatetcIn, pmedium);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI DataCache_GetDataHere(
|
static HRESULT WINAPI DataCache_GetDataHere(
|
||||||
|
@ -1703,8 +1642,7 @@ static HRESULT WINAPI DataCache_InitNew(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, DWORD advf, IStream *stm,
|
static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, DWORD advf, int stream_number )
|
||||||
enum stream_type type )
|
|
||||||
{
|
{
|
||||||
DataCacheEntry *cache_entry;
|
DataCacheEntry *cache_entry;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
@ -1717,10 +1655,8 @@ static HRESULT add_cache_entry( DataCache *This, const FORMATETC *fmt, DWORD adv
|
||||||
if (SUCCEEDED( hr ))
|
if (SUCCEEDED( hr ))
|
||||||
{
|
{
|
||||||
DataCacheEntry_DiscardData( cache_entry );
|
DataCacheEntry_DiscardData( cache_entry );
|
||||||
if (cache_entry->stream) IStream_Release( cache_entry->stream );
|
cache_entry->load_stream_num = stream_number;
|
||||||
cache_entry->stream = stm;
|
cache_entry->save_stream_num = stream_number;
|
||||||
IStream_AddRef( stm );
|
|
||||||
cache_entry->stream_type = type;
|
|
||||||
cache_entry->dirty = FALSE;
|
cache_entry->dirty = FALSE;
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -1753,7 +1689,7 @@ static HRESULT parse_pres_streams( DataCache *cache, IStorage *stg )
|
||||||
fmtetc.lindex = header.lindex;
|
fmtetc.lindex = header.lindex;
|
||||||
fmtetc.tymed = tymed_from_cf( clipformat );
|
fmtetc.tymed = tymed_from_cf( clipformat );
|
||||||
|
|
||||||
add_cache_entry( cache, &fmtetc, header.advf, stm, pres_stream );
|
add_cache_entry( cache, &fmtetc, header.advf, stream_number );
|
||||||
}
|
}
|
||||||
IStream_Release( stm );
|
IStream_Release( stm );
|
||||||
stream_number++;
|
stream_number++;
|
||||||
|
@ -1771,7 +1707,7 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage *stg )
|
||||||
const FORMATETC *fmt;
|
const FORMATETC *fmt;
|
||||||
IStream *stm;
|
IStream *stm;
|
||||||
|
|
||||||
hr = IStorage_OpenStream( stg, CONTENTS, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
|
hr = open_pres_stream( stg, STREAM_NUMBER_CONTENTS, &stm );
|
||||||
if (FAILED( hr )) return hr;
|
if (FAILED( hr )) return hr;
|
||||||
|
|
||||||
hr = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
|
hr = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
|
||||||
|
@ -1786,7 +1722,7 @@ static HRESULT parse_contents_stream( DataCache *This, IStorage *stg )
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = add_cache_entry( This, fmt, 0, stm, contents_stream );
|
hr = add_cache_entry( This, fmt, 0, STREAM_NUMBER_CONTENTS );
|
||||||
|
|
||||||
done:
|
done:
|
||||||
IStream_Release( stm );
|
IStream_Release( stm );
|
||||||
|
@ -1852,17 +1788,17 @@ static HRESULT WINAPI DataCache_Save(IPersistStorage* iface, IStorage *stg, BOOL
|
||||||
DataCache *This = impl_from_IPersistStorage(iface);
|
DataCache *This = impl_from_IPersistStorage(iface);
|
||||||
DataCacheEntry *cache_entry;
|
DataCacheEntry *cache_entry;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
unsigned short stream_number = 0;
|
int stream_number = 0;
|
||||||
|
|
||||||
TRACE("(%p, %p, %d)\n", iface, stg, same_as_load);
|
TRACE("(%p, %p, %d)\n", iface, stg, same_as_load);
|
||||||
|
|
||||||
/* assign stream numbers to the cache entries */
|
/* assign stream numbers to the cache entries */
|
||||||
LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
|
LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
|
||||||
{
|
{
|
||||||
if (cache_entry->stream_number != stream_number)
|
if (cache_entry->save_stream_num != stream_number)
|
||||||
{
|
{
|
||||||
cache_entry->dirty = TRUE; /* needs to be written out again */
|
cache_entry->dirty = TRUE; /* needs to be written out again */
|
||||||
cache_entry->stream_number = stream_number;
|
cache_entry->save_stream_num = stream_number;
|
||||||
}
|
}
|
||||||
stream_number++;
|
stream_number++;
|
||||||
}
|
}
|
||||||
|
@ -1916,7 +1852,6 @@ static HRESULT WINAPI DataCache_HandsOffStorage(
|
||||||
IPersistStorage* iface)
|
IPersistStorage* iface)
|
||||||
{
|
{
|
||||||
DataCache *this = impl_from_IPersistStorage(iface);
|
DataCache *this = impl_from_IPersistStorage(iface);
|
||||||
DataCacheEntry *cache_entry;
|
|
||||||
|
|
||||||
TRACE("(%p)\n", iface);
|
TRACE("(%p)\n", iface);
|
||||||
|
|
||||||
|
@ -1926,9 +1861,6 @@ static HRESULT WINAPI DataCache_HandsOffStorage(
|
||||||
this->presentationStorage = NULL;
|
this->presentationStorage = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY(cache_entry, &this->cache_list, DataCacheEntry, entry)
|
|
||||||
DataCacheEntry_HandsOffStorage(cache_entry);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2018,9 +1950,9 @@ static HRESULT WINAPI DataCache_Draw(
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* if the data hasn't been loaded yet, do it now */
|
/* if the data hasn't been loaded yet, do it now */
|
||||||
if ((cache_entry->stgmedium.tymed == TYMED_NULL) && cache_entry->stream)
|
if ((cache_entry->stgmedium.tymed == TYMED_NULL) && (cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET))
|
||||||
{
|
{
|
||||||
hres = DataCacheEntry_LoadData(cache_entry);
|
hres = DataCacheEntry_LoadData(cache_entry, This->presentationStorage);
|
||||||
if (FAILED(hres))
|
if (FAILED(hres))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2278,9 +2210,9 @@ static HRESULT WINAPI DataCache_GetExtent(
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* if the data hasn't been loaded yet, do it now */
|
/* if the data hasn't been loaded yet, do it now */
|
||||||
if ((cache_entry->stgmedium.tymed == TYMED_NULL) && cache_entry->stream)
|
if ((cache_entry->stgmedium.tymed == TYMED_NULL) && (cache_entry->load_stream_num != STREAM_NUMBER_NOT_SET))
|
||||||
{
|
{
|
||||||
hres = DataCacheEntry_LoadData(cache_entry);
|
hres = DataCacheEntry_LoadData(cache_entry, This->presentationStorage);
|
||||||
if (FAILED(hres))
|
if (FAILED(hres))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue