Support loading any presentation aspect.

This commit is contained in:
Andrew Lewycky 2000-03-19 12:42:58 +00:00 committed by Alexandre Julliard
parent db5da8bdd5
commit 7315a4b0aa
1 changed files with 113 additions and 63 deletions

View File

@ -23,18 +23,17 @@
* - I haven't found any good documentation on the real usage of * - I haven't found any good documentation on the real usage of
* the streams created by the data cache. In particular, How to * the streams created by the data cache. In particular, How to
* determine what the XXX stands for in the stream name * determine what the XXX stands for in the stream name
* "\002OlePresXXX". I have an intuition that this is related to * "\002OlePresXXX". It appears to just be a counter.
* the cached aspect of the object but I'm not sure it could
* just be a counter.
* - Also, I don't know the real content of the presentation stream * - Also, I don't know the real content of the presentation stream
* header. I was able to figure-out where the extent of the object * header. I was able to figure-out where the extent of the object
* was stored but that's about it. * was stored and the aspect, but that's about it.
*/ */
#include <assert.h> #include <assert.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "wingdi.h" #include "wingdi.h"
#include "winerror.h" #include "winerror.h"
#include "crtdll.h"
#include "wine/obj_oleview.h" #include "wine/obj_oleview.h"
#include "wine/obj_cache.h" #include "wine/obj_cache.h"
#include "debugtools.h" #include "debugtools.h"
@ -51,14 +50,14 @@ DEFAULT_DEBUG_CHANNEL(ole);
*/ */
typedef struct PresentationDataHeader typedef struct PresentationDataHeader
{ {
DWORD unknown1; DWORD unknown1; /* -1 */
DWORD unknown2; DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
DWORD unknown3; DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
DWORD unknown4; DVASPECT dvAspect;
DWORD unknown5; DWORD unknown5; /* -1 */
DWORD unknown6; DWORD unknown6;
DWORD unknown7; DWORD unknown7; /* 0 */
DWORD objectExtentX; DWORD objectExtentX;
DWORD objectExtentY; DWORD objectExtentY;
DWORD unknown8; DWORD unknown8;
@ -131,9 +130,9 @@ static void DataCache_Destroy(DataCache* ptrToDestroy);
static HRESULT DataCache_ReadPresentationData(DataCache* this, static HRESULT DataCache_ReadPresentationData(DataCache* this,
DWORD drawAspect, DWORD drawAspect,
PresentationDataHeader* header); PresentationDataHeader* header);
static HRESULT DataCache_FindPresStreamName(DataCache* this, static HRESULT DataCache_OpenPresStream(DataCache *this,
DWORD drawAspect, DWORD drawAspect,
OLECHAR* buffer); IStream **pStm);
static HMETAFILE DataCache_ReadPresMetafile(DataCache* this, static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
DWORD drawAspect); DWORD drawAspect);
static void DataCache_FireOnViewChange(DataCache* this, static void DataCache_FireOnViewChange(DataCache* this,
@ -585,35 +584,23 @@ static HRESULT DataCache_ReadPresentationData(
PresentationDataHeader* header) PresentationDataHeader* header)
{ {
IStream* presStream = NULL; IStream* presStream = NULL;
OLECHAR streamName[20];
HRESULT hres; HRESULT hres;
/* /*
* Get the name for the presentation stream. * Open the presentation stream.
*/ */
hres = DataCache_FindPresStreamName( hres = DataCache_OpenPresStream(
this, this,
drawAspect, drawAspect,
streamName);
if (FAILED(hres))
return hres;
/*
* Open the stream and read the header.
*/
hres = IStorage_OpenStream(
this->presentationStorage,
streamName,
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&presStream); &presStream);
if (FAILED(hres)) if (FAILED(hres))
return hres; return hres;
/*
* Read the header.
*/
hres = IStream_Read( hres = IStream_Read(
presStream, presStream,
header, header,
@ -679,34 +666,107 @@ static void DataCache_FireOnViewChange(
} }
} }
/* Helper for DataCache_OpenPresStream */
static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
{
/* The presentation streams have names of the form "\002OlePresXXX",
* where XXX goes from 000 to 999. */
static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
LPCWSTR name = elem->pwcsName;
return (elem->type == STGTY_STREAM)
&& (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
&& (CRTDLL_wcslen(name) == 11)
&& (CRTDLL_wcsncmp(name, OlePres, 8) == 0)
&& CRTDLL_iswdigit(name[8])
&& CRTDLL_iswdigit(name[9])
&& CRTDLL_iswdigit(name[10]);
}
/************************************************************************ /************************************************************************
* DataCache_ReadPresentationData * DataCache_OpenPresStream
* *
* This method will read information for the requested presentation * This method will find the stream for the given presentation. It makes
* into the given structure. * no attempt at fallback.
* *
* Param: * Param:
* this - Pointer to the DataCache object * this - Pointer to the DataCache object
* drawAspect - The aspect of the object that we wish to draw. * drawAspect - The aspect of the object that we wish to draw.
* header - The structure containing information about this * pStm - A returned stream. It points to the beginning of the
* aspect of the object. * - presentation data, including the header.
* *
* NOTE: * Errors:
* This method only supports the DVASPECT_CONTENT aspect. * 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 maches.
*
* If a fallback is desired, just opening the first presentation stream
* is a possibility.
*/ */
static HRESULT DataCache_FindPresStreamName( static HRESULT DataCache_OpenPresStream(
DataCache* this, DataCache *this,
DWORD drawAspect, DWORD drawAspect,
OLECHAR* buffer) IStream **ppStm)
{ {
OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0}; STATSTG elem;
IEnumSTATSTG *pEnum;
HRESULT hr;
if (drawAspect!=DVASPECT_CONTENT) if (!ppStm) return E_POINTER;
return E_FAIL;
memcpy(buffer, name, sizeof(name)); hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
if (FAILED(hr)) return hr;
return S_OK; while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
{
if (DataCache_IsPresentationStream(&elem))
{
IStream *pStm;
hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
&pStm);
if (SUCCEEDED(hr))
{
PresentationDataHeader header;
ULONG actual_read;
hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
/* can't use SUCCEEDED(hr): S_FALSE counts as an error */
if (hr == S_OK && actual_read == sizeof(header)
&& header.dvAspect == drawAspect)
{
/* Rewind the stream before returning it. */
LARGE_INTEGER offset;
offset.s.LowPart = 0;
offset.s.HighPart = 0;
IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
*ppStm = pStm;
CoTaskMemFree(elem.pwcsName);
IEnumSTATSTG_Release(pEnum);
return S_OK;
}
IStream_Release(pStm);
}
}
CoTaskMemFree(elem.pwcsName);
}
IEnumSTATSTG_Release(pEnum);
return (hr == S_FALSE ? OLE_E_BLANK : hr);
} }
/************************************************************************ /************************************************************************
@ -729,32 +789,17 @@ static HMETAFILE DataCache_ReadPresMetafile(
{ {
LARGE_INTEGER offset; LARGE_INTEGER offset;
IStream* presStream = NULL; IStream* presStream = NULL;
OLECHAR streamName[20];
HRESULT hres; HRESULT hres;
void* metafileBits; void* metafileBits;
STATSTG streamInfo; STATSTG streamInfo;
HMETAFILE newMetafile = 0; HMETAFILE newMetafile = 0;
/* /*
* Get the name for the presentation stream. * Open the presentation stream.
*/ */
hres = DataCache_FindPresStreamName( hres = DataCache_OpenPresStream(
this, this,
drawAspect, drawAspect,
streamName);
if (FAILED(hres))
return hres;
/*
* Open the stream and read the header.
*/
hres = IStorage_OpenStream(
this->presentationStorage,
streamName,
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&presStream); &presStream);
if (FAILED(hres)) if (FAILED(hres))
@ -779,6 +824,8 @@ static HMETAFILE DataCache_ReadPresMetafile(
STREAM_SEEK_SET, STREAM_SEEK_SET,
NULL); NULL);
streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
/* /*
* Allocate a buffer for the metafile bits. * Allocate a buffer for the metafile bits.
*/ */
@ -1445,6 +1492,9 @@ static HRESULT WINAPI DataCache_Draw(
/* /*
* Then, we can extract the metafile itself from the cached * Then, we can extract the metafile itself from the cached
* data. * data.
*
* FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
* particularly CF_DIB.
*/ */
presMetafile = DataCache_ReadPresMetafile(this, presMetafile = DataCache_ReadPresMetafile(this,
dwDrawAspect); dwDrawAspect);