Support loading any presentation aspect.
This commit is contained in:
parent
db5da8bdd5
commit
7315a4b0aa
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue