From 08764dde8abf964ce99780a56b72622774086fe1 Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Sun, 5 Mar 2006 13:34:31 +0000 Subject: [PATCH] oleaut: Split OLEPictureImpl_Load. Split OLEPictureImpl_Load into separate functions for the different file types. --- dlls/oleaut32/olepicture.c | 305 ++++++++++++++++++++----------------- 1 file changed, 162 insertions(+), 143 deletions(-) diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index b11bc40b9e1..d4ae1b56bef 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -1052,137 +1052,9 @@ static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) { #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); - /**************************************************************************************** - * 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 */ +static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ #ifdef HAVE_GIF_LIB_H struct gifdata gd; 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"); return E_FAIL; #endif - } - case 0xd8ff: { /* JPEG */ +} + +static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ #ifdef HAVE_JPEGLIB_H struct jpeg_decompress_struct jd; struct jpeg_error_mgr jerr; @@ -1484,15 +1358,16 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { DeleteDC(hdcref); This->desc.picType = PICTYPE_BITMAP; OLEPictureImpl_SetBitmap(This); - hr = S_OK; HeapFree(GetProcessHeap(),0,bits); + return S_OK; #else ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n"); - hr = E_FAIL; + return E_FAIL; #endif - break; - } - case 0x4d42: { /* Bitmap */ +} + +static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf; BITMAPINFO *bi = (BITMAPINFO*)(bfh+1); HDC hdcref; @@ -1512,10 +1387,11 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { DeleteDC(hdcref); This->desc.picType = PICTYPE_BITMAP; OLEPictureImpl_SetBitmap(This); - hr = S_OK; - break; - } - case 0x0000: { /* ICON , first word is dwReserved */ + return S_OK; +} + +static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) +{ HICON hicon; CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf; HDC hdcRef; @@ -1560,7 +1436,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { ); if (!hicon) { FIXME("CreateIcon failed.\n"); - hr = E_FAIL; + return E_FAIL; } else { This->desc.picType = PICTYPE_ICON; 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->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY); 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; } default: