oleaut: Split OLEPictureImpl_Load.
Split OLEPictureImpl_Load into separate functions for the different file types.
This commit is contained in:
parent
e06b046f59
commit
08764dde8a
|
@ -1052,137 +1052,9 @@ static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
|
||||||
|
|
||||||
#endif /* HAVE_GIF_LIB_H */
|
#endif /* HAVE_GIF_LIB_H */
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
* OLEPictureImpl_IPersistStream_Load (IUnknown)
|
|
||||||
*
|
|
||||||
* Loads the binary data from the IStream. Starts at current position.
|
|
||||||
* There appears to be an 2 DWORD header:
|
|
||||||
* DWORD magic;
|
|
||||||
* DWORD len;
|
|
||||||
*
|
|
||||||
* Currently implemented: BITMAP, ICON, JPEG, GIF
|
|
||||||
*/
|
|
||||||
static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
|
|
||||||
HRESULT hr = E_FAIL;
|
|
||||||
BOOL headerisdata = FALSE;
|
|
||||||
BOOL statfailed = FALSE;
|
|
||||||
ULONG xread, toread;
|
|
||||||
BYTE *xbuf;
|
|
||||||
DWORD header[2];
|
|
||||||
WORD magic;
|
|
||||||
STATSTG statstg;
|
|
||||||
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
|
||||||
|
|
||||||
TRACE("(%p,%p)\n",This,pStm);
|
|
||||||
|
|
||||||
/****************************************************************************************
|
static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
|
||||||
* Part 1: Load the data
|
{
|
||||||
*/
|
|
||||||
/* Sometimes we have a header, sometimes we don't. Apply some guesses to find
|
|
||||||
* out whether we do.
|
|
||||||
*
|
|
||||||
* UPDATE: the IStream can be mapped to a plain file instead of a stream in a
|
|
||||||
* compound file. This may explain most, if not all, of the cases of "no
|
|
||||||
* header", and the header validation should take this into account.
|
|
||||||
* At least in Visual Basic 6, resource streams, valid headers are
|
|
||||||
* header[0] == "lt\0\0",
|
|
||||||
* header[1] == length_of_stream.
|
|
||||||
*
|
|
||||||
* Also handle streams where we do not have a working "Stat" method by
|
|
||||||
* reading all data until the end of the stream.
|
|
||||||
*/
|
|
||||||
hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
|
|
||||||
if (hr) {
|
|
||||||
TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr);
|
|
||||||
statfailed = TRUE;
|
|
||||||
/* we will read at least 8 byte ... just right below */
|
|
||||||
statstg.cbSize.QuadPart = 8;
|
|
||||||
}
|
|
||||||
hr=IStream_Read(pStm,header,8,&xread);
|
|
||||||
if (hr || xread!=8) {
|
|
||||||
FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
headerisdata = FALSE;
|
|
||||||
xread = 0;
|
|
||||||
if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
|
|
||||||
toread = header[1];
|
|
||||||
} else {
|
|
||||||
if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
|
|
||||||
!memcmp(&(header[0]), "BM", 2) || /* BMP header */
|
|
||||||
!memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
|
|
||||||
(header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
|
|
||||||
(header[1]==0)
|
|
||||||
) {/* Incorrect header, assume none. */
|
|
||||||
headerisdata = TRUE;
|
|
||||||
toread = statstg.cbSize.QuadPart-8;
|
|
||||||
xread = 8;
|
|
||||||
} else {
|
|
||||||
FIXME("Unknown stream header magic: %08lx\n", header[0]);
|
|
||||||
toread = header[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (statfailed) { /* we don't know the size ... read all we get */
|
|
||||||
int sizeinc = 4096;
|
|
||||||
int origsize = sizeinc;
|
|
||||||
ULONG nread = 42;
|
|
||||||
|
|
||||||
TRACE("Reading all data from stream.\n");
|
|
||||||
xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
|
|
||||||
if (headerisdata)
|
|
||||||
memcpy (xbuf, &header, 8);
|
|
||||||
while (1) {
|
|
||||||
while (xread < origsize) {
|
|
||||||
hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
|
|
||||||
xread+=nread;
|
|
||||||
if (hr || !nread)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!nread || hr) /* done, or error */
|
|
||||||
break;
|
|
||||||
if (xread == origsize) {
|
|
||||||
origsize += sizeinc;
|
|
||||||
sizeinc = 2*sizeinc; /* exponential increase */
|
|
||||||
xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hr)
|
|
||||||
TRACE("hr in no-stat loader case is %08lx\n", hr);
|
|
||||||
TRACE("loaded %ld bytes.\n", xread);
|
|
||||||
This->datalen = xread;
|
|
||||||
This->data = xbuf;
|
|
||||||
} else {
|
|
||||||
This->datalen = toread+(headerisdata?8:0);
|
|
||||||
xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
|
|
||||||
|
|
||||||
if (headerisdata)
|
|
||||||
memcpy (xbuf, &header, 8);
|
|
||||||
|
|
||||||
while (xread < This->datalen) {
|
|
||||||
ULONG nread;
|
|
||||||
hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
|
|
||||||
xread+=nread;
|
|
||||||
if (hr || !nread)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (xread != This->datalen)
|
|
||||||
FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
|
|
||||||
}
|
|
||||||
if (This->datalen == 0) { /* Marks the "NONE" picture */
|
|
||||||
This->desc.picType = PICTYPE_NONE;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************************
|
|
||||||
* Part 2: Process the loaded data
|
|
||||||
*/
|
|
||||||
|
|
||||||
magic = xbuf[0] + (xbuf[1]<<8);
|
|
||||||
switch (magic) {
|
|
||||||
case 0x4947: { /* GIF */
|
|
||||||
#ifdef HAVE_GIF_LIB_H
|
#ifdef HAVE_GIF_LIB_H
|
||||||
struct gifdata gd;
|
struct gifdata gd;
|
||||||
GifFileType *gif;
|
GifFileType *gif;
|
||||||
|
@ -1387,8 +1259,10 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
|
||||||
FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
|
FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
case 0xd8ff: { /* JPEG */
|
|
||||||
|
static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
|
||||||
|
{
|
||||||
#ifdef HAVE_JPEGLIB_H
|
#ifdef HAVE_JPEGLIB_H
|
||||||
struct jpeg_decompress_struct jd;
|
struct jpeg_decompress_struct jd;
|
||||||
struct jpeg_error_mgr jerr;
|
struct jpeg_error_mgr jerr;
|
||||||
|
@ -1484,15 +1358,16 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
|
||||||
DeleteDC(hdcref);
|
DeleteDC(hdcref);
|
||||||
This->desc.picType = PICTYPE_BITMAP;
|
This->desc.picType = PICTYPE_BITMAP;
|
||||||
OLEPictureImpl_SetBitmap(This);
|
OLEPictureImpl_SetBitmap(This);
|
||||||
hr = S_OK;
|
|
||||||
HeapFree(GetProcessHeap(),0,bits);
|
HeapFree(GetProcessHeap(),0,bits);
|
||||||
|
return S_OK;
|
||||||
#else
|
#else
|
||||||
ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
|
ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
|
||||||
hr = E_FAIL;
|
return E_FAIL;
|
||||||
#endif
|
#endif
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
case 0x4d42: { /* Bitmap */
|
static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
|
||||||
|
{
|
||||||
BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
|
BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
|
||||||
BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
|
BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
|
||||||
HDC hdcref;
|
HDC hdcref;
|
||||||
|
@ -1512,10 +1387,11 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
|
||||||
DeleteDC(hdcref);
|
DeleteDC(hdcref);
|
||||||
This->desc.picType = PICTYPE_BITMAP;
|
This->desc.picType = PICTYPE_BITMAP;
|
||||||
OLEPictureImpl_SetBitmap(This);
|
OLEPictureImpl_SetBitmap(This);
|
||||||
hr = S_OK;
|
return S_OK;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
case 0x0000: { /* ICON , first word is dwReserved */
|
static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
|
||||||
|
{
|
||||||
HICON hicon;
|
HICON hicon;
|
||||||
CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
|
CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
|
||||||
HDC hdcRef;
|
HDC hdcRef;
|
||||||
|
@ -1560,7 +1436,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
|
||||||
);
|
);
|
||||||
if (!hicon) {
|
if (!hicon) {
|
||||||
FIXME("CreateIcon failed.\n");
|
FIXME("CreateIcon failed.\n");
|
||||||
hr = E_FAIL;
|
return E_FAIL;
|
||||||
} else {
|
} else {
|
||||||
This->desc.picType = PICTYPE_ICON;
|
This->desc.picType = PICTYPE_ICON;
|
||||||
This->desc.u.icon.hicon = hicon;
|
This->desc.u.icon.hicon = hicon;
|
||||||
|
@ -1570,8 +1446,151 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
|
||||||
This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
|
This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
|
||||||
This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
|
This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
|
||||||
DeleteDC(hdcRef);
|
DeleteDC(hdcRef);
|
||||||
hr = S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* OLEPictureImpl_IPersistStream_Load (IUnknown)
|
||||||
|
*
|
||||||
|
* Loads the binary data from the IStream. Starts at current position.
|
||||||
|
* There appears to be an 2 DWORD header:
|
||||||
|
* DWORD magic;
|
||||||
|
* DWORD len;
|
||||||
|
*
|
||||||
|
* Currently implemented: BITMAP, ICON, JPEG, GIF
|
||||||
|
*/
|
||||||
|
static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
|
||||||
|
HRESULT hr = E_FAIL;
|
||||||
|
BOOL headerisdata = FALSE;
|
||||||
|
BOOL statfailed = FALSE;
|
||||||
|
ULONG xread, toread;
|
||||||
|
BYTE *xbuf;
|
||||||
|
DWORD header[2];
|
||||||
|
WORD magic;
|
||||||
|
STATSTG statstg;
|
||||||
|
OLEPictureImpl *This = impl_from_IPersistStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p,%p)\n",This,pStm);
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* Part 1: Load the data
|
||||||
|
*/
|
||||||
|
/* Sometimes we have a header, sometimes we don't. Apply some guesses to find
|
||||||
|
* out whether we do.
|
||||||
|
*
|
||||||
|
* UPDATE: the IStream can be mapped to a plain file instead of a stream in a
|
||||||
|
* compound file. This may explain most, if not all, of the cases of "no
|
||||||
|
* header", and the header validation should take this into account.
|
||||||
|
* At least in Visual Basic 6, resource streams, valid headers are
|
||||||
|
* header[0] == "lt\0\0",
|
||||||
|
* header[1] == length_of_stream.
|
||||||
|
*
|
||||||
|
* Also handle streams where we do not have a working "Stat" method by
|
||||||
|
* reading all data until the end of the stream.
|
||||||
|
*/
|
||||||
|
hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
|
||||||
|
if (hr) {
|
||||||
|
TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr);
|
||||||
|
statfailed = TRUE;
|
||||||
|
/* we will read at least 8 byte ... just right below */
|
||||||
|
statstg.cbSize.QuadPart = 8;
|
||||||
|
}
|
||||||
|
hr=IStream_Read(pStm,header,8,&xread);
|
||||||
|
if (hr || xread!=8) {
|
||||||
|
FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
headerisdata = FALSE;
|
||||||
|
xread = 0;
|
||||||
|
if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
|
||||||
|
toread = header[1];
|
||||||
|
} else {
|
||||||
|
if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
|
||||||
|
!memcmp(&(header[0]), "BM", 2) || /* BMP header */
|
||||||
|
!memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
|
||||||
|
(header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
|
||||||
|
(header[1]==0)
|
||||||
|
) {/* Incorrect header, assume none. */
|
||||||
|
headerisdata = TRUE;
|
||||||
|
toread = statstg.cbSize.QuadPart-8;
|
||||||
|
xread = 8;
|
||||||
|
} else {
|
||||||
|
FIXME("Unknown stream header magic: %08lx\n", header[0]);
|
||||||
|
toread = header[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statfailed) { /* we don't know the size ... read all we get */
|
||||||
|
int sizeinc = 4096;
|
||||||
|
int origsize = sizeinc;
|
||||||
|
ULONG nread = 42;
|
||||||
|
|
||||||
|
TRACE("Reading all data from stream.\n");
|
||||||
|
xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
|
||||||
|
if (headerisdata)
|
||||||
|
memcpy (xbuf, &header, 8);
|
||||||
|
while (1) {
|
||||||
|
while (xread < origsize) {
|
||||||
|
hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
|
||||||
|
xread+=nread;
|
||||||
|
if (hr || !nread)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!nread || hr) /* done, or error */
|
||||||
|
break;
|
||||||
|
if (xread == origsize) {
|
||||||
|
origsize += sizeinc;
|
||||||
|
sizeinc = 2*sizeinc; /* exponential increase */
|
||||||
|
xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hr)
|
||||||
|
TRACE("hr in no-stat loader case is %08lx\n", hr);
|
||||||
|
TRACE("loaded %ld bytes.\n", xread);
|
||||||
|
This->datalen = xread;
|
||||||
|
This->data = xbuf;
|
||||||
|
} else {
|
||||||
|
This->datalen = toread+(headerisdata?8:0);
|
||||||
|
xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
|
||||||
|
|
||||||
|
if (headerisdata)
|
||||||
|
memcpy (xbuf, &header, 8);
|
||||||
|
|
||||||
|
while (xread < This->datalen) {
|
||||||
|
ULONG nread;
|
||||||
|
hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
|
||||||
|
xread+=nread;
|
||||||
|
if (hr || !nread)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (xread != This->datalen)
|
||||||
|
FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
|
||||||
|
}
|
||||||
|
if (This->datalen == 0) { /* Marks the "NONE" picture */
|
||||||
|
This->desc.picType = PICTYPE_NONE;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* Part 2: Process the loaded data
|
||||||
|
*/
|
||||||
|
|
||||||
|
magic = xbuf[0] + (xbuf[1]<<8);
|
||||||
|
switch (magic) {
|
||||||
|
case 0x4947: /* GIF */
|
||||||
|
hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
|
||||||
|
break;
|
||||||
|
case 0xd8ff: /* JPEG */
|
||||||
|
hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
|
||||||
|
break;
|
||||||
|
case 0x4d42: /* Bitmap */
|
||||||
|
hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
|
||||||
|
break;
|
||||||
|
case 0x0000: { /* ICON , first word is dwReserved */
|
||||||
|
hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue