//+---------------------------------------------------------------------------- // // File: // convert.cpp // // Contents: // This module contains the code to read/write DIB, metafile, // placeable metafiles, olepres stream, etc... This module also // contains routines for converting from one format to other. // // Classes: // // Functions: // // History: // 15-Feb-94 alexgo fixed a bug in loading placeable metafiles // from a storage (incorrect size calculation). // 25-Jan-94 alexgo first pass at converting to Cairo-style // memory allocations. // 01/11/93 - alexgo - added VDATEHEAP macros to every function // 12/08/93 - ChrisWe - fixed wPrepareBitmapHeader not to use // (LPOLESTR) cast // 12/07/93 - ChrisWe - make default params to StSetSize explicit // 12/02/93 - ChrisWe - more formatting; fixed UtHMFToMFStm, // 32 bit version, which was doing questionable things // with the hBits handle; got rid of the OLESTR // uses in favor of (void *) or (BYTE *) as appropriate // 11/29/93 - ChrisWe - move CONVERT_SOURCEISICON, returned // by UtOlePresStmToContentsStm(), to utils.h // 11/28/93 - ChrisWe - begin file inspection and cleanup // 06/28/93 - SriniK - created // //----------------------------------------------------------------------------- #include #pragma SEG(ole2) NAME_SEG(convert) ASSERTDATA #ifndef _MAC FARINTERNAL_(HMETAFILE) QD2GDI(HANDLE hBits); #endif void UtGetHEMFFromContentsStm(LPSTREAM lpstm, HANDLE * phdata); /************************ FILE FORMATS ********************************** Normal Metafile (memory or disk based): ------------ --------------- | METAHEADER | Metafile bits | ------------ --------------- Placeable Metafile: --------------------- ----------------- | PLACEABLEMETAHEADER | Normal metafile | --------------------- ----------------- Memory Based DIB: ------------------ --------------- ---------- | BITMAPINFOHEADER | RGBQUAD array | DIB bits | ------------------ --------------- ---------- DIB file format: ------------------ ------------------ | BITMAPFILEHEADER | Memory based DIB | ------------------ ------------------ Ole10NativeStream Format: -------- ---------------------- | dwSize | Object's Native data | -------- ---------------------- PBrush Native data format: ----------------- | Dib File format | ----------------- MSDraw Native data format: --------------------- ------------- ------------- ----------------- | mapping mode (WORD) | xExt (WORD) | yExt (WORD) | Normal metafile | --------------------- ------------- ------------- ----------------- *****************************************************************************/ FARINTERNAL UtGetHGLOBALFromStm(LPSTREAM lpstream, DWORD dwSize, HANDLE FAR* lphPres) { VDATEHEAP(); HANDLE hBits = NULL; void FAR *lpBits = NULL; HRESULT error; // initialize this for error return cases *lphPres = NULL; // allocate a new handle if (!(hBits = GlobalAlloc(GMEM_MOVEABLE, dwSize)) || !(lpBits = (BYTE *)GlobalLock(hBits))) { error = ResultFromScode(E_OUTOFMEMORY); goto errRtn; } // read the stream into the allocated memory if (error = StRead(lpstream, lpBits, dwSize)) goto errRtn; // if we got this far, return new handle *lphPres = hBits; errRtn: // unlock the handle, if it was successfully locked if (lpBits) GlobalUnlock(hBits); // free the handle if there was an error if ((error != NOERROR) && hBits) GlobalFree(hBits); return(error); } #ifndef _MAC FARINTERNAL UtGetHDIBFromDIBFileStm(LPSTREAM pstm, HANDLE FAR* lphdata) { VDATEHEAP(); BITMAPFILEHEADER bfh; DWORD dwSize; // the size of the data to read HRESULT error; // read the bitmap file header if (error = pstm->Read(&bfh, sizeof(BITMAPFILEHEADER), NULL)) { *lphdata = NULL; return(error); } // calculate the size of the DIB to read dwSize = bfh.bfSize - sizeof(BITMAPFILEHEADER); // read the DIB return(UtGetHGLOBALFromStm(pstm, dwSize, lphdata)); } FARINTERNAL_(HANDLE) UtGetHMFPICT(HMETAFILE hMF, BOOL fDeleteOnError, DWORD xExt, DWORD yExt) { VDATEHEAP(); HANDLE hmfp; // handle to the new METAFILEPICT LPMETAFILEPICT lpmfp; // pointer to the new METAFILEPICT // if no METAFILE, nothing to do if (hMF == NULL) return(NULL); // allocate a new handle if (!(hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT)))) goto errRtn; // lock the handle if (!(lpmfp = (LPMETAFILEPICT)GlobalLock(hmfp))) goto errRtn; // make the METAFILEPICT lpmfp->hMF = hMF; lpmfp->xExt = (int)xExt; lpmfp->yExt = (int)yExt; lpmfp->mm = MM_ANISOTROPIC; GlobalUnlock(hmfp); return(hmfp); errRtn: if (hmfp) GlobalFree(hmfp); if (fDeleteOnError) DeleteMetaFile(hMF); return(NULL); } #endif // _MAC //+------------------------------------------------------------------------- // // Function: UtGetHMFFromMFStm // // Synopsis: // // Effects: // // Arguments: [lpstream] -- stream containing metafile or PICT // [dwSize] -- data size within stream // [fConvert] -- FALSE for metafile, TRUE for PICT // [lphPres] -- placeholder for output metafile // // Requires: lpstream positioned at start of data // // Returns: HRESULT // // Modifies: // // Algorithm: // // History: 29-Apr-94 AlexT Add comment block, enabled Mac conversion // // Notes: // //-------------------------------------------------------------------------- FARINTERNAL UtGetHMFFromMFStm(LPSTREAM lpstream, DWORD dwSize, BOOL fConvert, HANDLE FAR* lphPres) { #ifdef WIN32 LEDebugOut((DEB_ITRACE, "%p _IN UtGetHMFFromMFStm (%p, %d, %d, %p)\n", NULL, lpstream, dwSize, fConvert, lphPres)); VDATEHEAP(); BYTE *pbMFData = NULL; METAHEADER MetaHdr; HRESULT hrError; // initialize this in case of error return *lphPres = NULL; // allocate a global handle for the data (since QD2GDI needs a // handle) pbMFData = (BYTE *) GlobalAlloc(GMEM_FIXED, dwSize); if (NULL == pbMFData) { hrError = ResultFromScode(E_OUTOFMEMORY); goto errRtn; } // read the stream into the bit storage ULONG cbRead; hrError = lpstream->Read(pbMFData, dwSize, &cbRead); if (FAILED(hrError)) { return(hrError); } // As TOC is being written at the end of presentation, it is essential // to place the seek pointer at the end of presentation data. Hence, // seek past the extra meta header written by UtHMFToMFStm ignoring error lpstream->Read(&MetaHdr, sizeof(MetaHdr), NULL); // hrError = StRead(lpstream, pbMFData, dwSize); if (hrError != NOERROR) { goto errRtn; } if (fConvert) { // It's a Mac PICT *lphPres = QD2GDI((HGLOBAL) pbMFData); } else { // It's a Windows metafile *lphPres = SetMetaFileBitsEx(dwSize, pbMFData); } if (*lphPres == NULL) hrError = ResultFromScode(E_OUTOFMEMORY); errRtn: if (NULL != pbMFData) { GlobalFree(pbMFData); } LEDebugOut((DEB_ITRACE, "%p OUT UtGetHMFFromMFStm ( %lx ) [ %p ]\n", NULL, hrError, *lphPres)); return(hrError); #else HANDLE hBits; // handle to the new METAFILE void FAR* lpBits = NULL; HRESULT error; // initialize this in case of error return *lphPres = NULL; // allocate a new handle, and lock the bits if (!(hBits = GlobalAlloc(GMEM_MOVEABLE, dwSize)) || !(lpBits = GlobalLock(hBits))) { error = ResultFromScode(E_OUTOFMEMORY); goto errRtn; } // read the stream into the bit storage error = StRead(lpstream, lpBits, dwSize); GlobalUnlock(hBits); if (error) goto errRtn; if (!fConvert) *lphPres = SetMetaFileBits(hBits); else { if (*lphPres = QD2GDI(hBits)) { // Need to free this handle upon success GlobalFree(hBits); hBits = NULL; } } if (!*lphPres) error = ResultFromScode(E_OUTOFMEMORY); errRtn: if (error && hBits) GlobalFree(hBits); return(error); #endif // WIN32 } FARINTERNAL UtGetSizeAndExtentsFromPlaceableMFStm(LPSTREAM pstm, DWORD FAR* pdwSize, LONG FAR* plWidth, LONG FAR* plHeight) { VDATEHEAP(); HRESULT error; LARGE_INTEGER large_int; // used to set the seek pointer ULARGE_INTEGER ularge_int; // retrieves the new seek position LONG xExt; // the x extent of the metafile LONG yExt; // the y extent of the metafile METAHEADER mfh; PLACEABLEMETAHEADER plac_mfh; // read the placeable metafile header if (error = pstm->Read(&plac_mfh, sizeof(plac_mfh), NULL)) return(error); // check the magic number in the header if (plac_mfh.key != PMF_KEY) return ResultFromScode(E_FAIL); // remember the seek pointer LISet32(large_int, 0); if (error = pstm->Seek(large_int, STREAM_SEEK_CUR, &ularge_int)) return(error); // read metafile header if (error = pstm->Read(&mfh, sizeof(mfh), NULL)) return(error); // seek back to the begining of metafile header LISet32(large_int, ularge_int.LowPart); if (error = pstm->Seek(large_int, STREAM_SEEK_SET, NULL)) return(error); // calculate the extents of the metafile xExt = (plac_mfh.bbox.right - plac_mfh.bbox.left);// metafile units yExt = (plac_mfh.bbox.bottom - plac_mfh.bbox.top);// metafile units // REVIEW, why aren't there constants for this? xExt = (xExt * 2540) / plac_mfh.inch; // HIMETRIC units yExt = (yExt * 2540) / plac_mfh.inch; // HIMETRIC units if (pdwSize) { #ifdef WIN16 //this code seems to work OK on Win16 *pdwSize = 2 * (mfh.mtSize + mfh.mtHeaderSize); // REVIEW NT: review METAHEADER #else //WIN32 //mt.Size is the size in words of the metafile. //this fixes bug 6739 (static objects can't be copied //or loaded from a file). *pdwSize = sizeof(WORD) * mfh.mtSize; #endif //WIN16 } if (plWidth) *plWidth = xExt; if (plHeight) *plHeight = yExt; return NOERROR; } FARINTERNAL UtGetHMFPICTFromPlaceableMFStm(LPSTREAM pstm, HANDLE FAR* lphdata) { VDATEHEAP(); HRESULT error; // error state so far DWORD dwSize; // size of the METAFILE we have to read from the stream LONG xExt; // x extent of the METAFILE we have to read from the stream LONG yExt; // y extent of the METAFILE we have to read from the stream HMETAFILE hMF; // handle to the METAFILE read from the stream if (lphdata == NULL) return ResultFromScode(E_INVALIDARG); // initialize this in case of error return *lphdata = NULL; // get the size of the METAFILE if (error = UtGetSizeAndExtentsFromPlaceableMFStm(pstm, &dwSize, &xExt, &yExt)) return(error); // fetch the METAFILE if (error = UtGetHMFFromMFStm(pstm, dwSize, FALSE /*fConvert*/, (HANDLE FAR *)&hMF)) return(error); // convert to a METAFILEPICT if (!(*lphdata = UtGetHMFPICT(hMF, TRUE /*fDeleteOnError*/, xExt, yExt))) return ResultFromScode(E_OUTOFMEMORY); return NOERROR; } /****************************************************************************/ /***************** Write routines *********************/ /****************************************************************************/ #ifndef _MAC //+---------------------------------------------------------------------------- // // Function: // iFindDIBits // // Synopsis: // Returns offset from beginning of BITMAPINFOHEADER to the bits // // Arguments: // [lpbih] -- pointer to the BITMAPINFOHEADER // // History: // 09/21/98 - DavidShi // //----------------------------------------------------------------------------- FARINTERNAL_(int) iFindDIBits (LPBITMAPINFOHEADER lpbih) { int iPalSize; // size of palette info int iNumColors=0; // number of colors in DIB // // Find the number of colors // switch (lpbih->biBitCount) { case 1: iNumColors = 2; break; case 4: iNumColors = 16; break; case 8: iNumColors = 256; break; } if (lpbih->biSize >= sizeof(BITMAPINFOHEADER)) { if (lpbih->biClrUsed) { iNumColors = (int)lpbih->biClrUsed; } } // // Calculate the size of the color table. // if (lpbih->biSize < sizeof(BITMAPINFOHEADER)) { iPalSize = iNumColors * sizeof(RGBTRIPLE); } else if (lpbih->biCompression==BI_BITFIELDS) { if (lpbih->biSize < sizeof(BITMAPV4HEADER)) { iPalSize = 3*sizeof(DWORD); } else iPalSize = 0; } else { iPalSize = iNumColors * sizeof(RGBQUAD); } return lpbih->biSize + iPalSize; } //+---------------------------------------------------------------------------- // // Function: // wPrepareBitmapHeader, static // // Synopsis: // Initializes the content of a BITMAPFILEHEADER. Forces bitmap // bits to immediately follow the header. // // Arguments: // [lpbfh] -- pointer to the BITMAPFILEHEADER to initialize // [lpbih] -- pointer to DIB // [dwSize] -- the size of the file; obtained by dividing // the size of the file by 4 (see win32 documentation.) // // History: // 12/08/93 - ChrisWe - made static // //----------------------------------------------------------------------------- static INTERNAL_(void) wPrepareBitmapFileHeader(LPBITMAPFILEHEADER lpbfh, LPBITMAPINFOHEADER lpbih, DWORD dwSize ) { VDATEHEAP(); // NOTE THESE ARE NOT SUPPOSED TO BE UNICODE // see win32s documentation ((char *)(&lpbfh->bfType))[0] = 'B'; ((char *)(&lpbfh->bfType))[1] = 'M'; lpbfh->bfSize = dwSize + sizeof(BITMAPFILEHEADER); lpbfh->bfReserved1 = 0; lpbfh->bfReserved2 = 0; lpbfh->bfOffBits = sizeof(BITMAPFILEHEADER)+iFindDIBits (lpbih); } FARINTERNAL UtHDIBToDIBFileStm(HANDLE hdata, DWORD dwSize, LPSTREAM pstm) { VDATEHEAP(); HRESULT error; BITMAPFILEHEADER bfh; LPBITMAPINFOHEADER pbih; if (!(pbih = (LPBITMAPINFOHEADER)GlobalLock (hdata))) return E_OUTOFMEMORY; wPrepareBitmapFileHeader(&bfh, pbih, dwSize); GlobalUnlock (hdata); if (error = pstm->Write(&bfh, sizeof(bfh), NULL)) return(error); return UtHGLOBALtoStm(hdata, dwSize, pstm); } FARINTERNAL UtDIBStmToDIBFileStm(LPSTREAM pstmDIB, DWORD dwSize, LPSTREAM pstmDIBFile) { VDATEHEAP(); HRESULT error; BITMAPFILEHEADER bfh; BITMAPINFOHEADER bih; ULARGE_INTEGER ularge_int; // indicates how much to copy LARGE_INTEGER large_int; error = pstmDIB->Read (&bih, sizeof(bih), NULL); LISet32(large_int, 0); wPrepareBitmapFileHeader(&bfh, &bih, dwSize); if (error = pstmDIBFile->Write(&bfh, sizeof(bfh), NULL)) return(error); if (error = pstmDIBFile->Write(&bih, sizeof(bih), NULL)) return(error); ULISet32(ularge_int, (dwSize - sizeof(bih))); if ((error = pstmDIB->CopyTo(pstmDIBFile, ularge_int, NULL, NULL)) == NOERROR) StSetSize(pstmDIBFile, 0, TRUE); return(error); } // REVIEW, move these to utils.h so that gen.cpp and mf.cpp can use them for // the same purposes // REVIEW, add some more comments; is HDIBFILEHDR a windows structure? struct tagHDIBFILEHDR { DWORD dwCompression; DWORD dwWidth; DWORD dwHeight; DWORD dwSize; }; typedef struct tagHDIBFILEHDR HDIBFILEHDR; struct tagOLEPRESSTMHDR { DWORD dwAspect; DWORD dwLindex; DWORD dwAdvf; }; typedef struct tagOLEPRESSTMHDR OLEPRESSTMHDR; FARINTERNAL UtHDIBFileToOlePresStm(HANDLE hdata, LPSTREAM pstm) { VDATEHEAP(); HRESULT error; HDIBFILEHDR hdfh; LPBITMAPFILEHEADER lpbfh; LPBITMAPINFOHEADER lpbmi; if (!(lpbfh = (LPBITMAPFILEHEADER)GlobalLock(hdata))) return ResultFromScode(E_OUTOFMEMORY); lpbmi = (LPBITMAPINFOHEADER)(((BYTE *)lpbfh) + sizeof(BITMAPFILEHEADER)); hdfh.dwCompression = 0; // REVIEW, these casts are hosed UtGetDibExtents(lpbmi, (LPLONG)&hdfh.dwWidth, (LPLONG)&hdfh.dwHeight); hdfh.dwSize = lpbfh->bfSize - sizeof(BITMAPFILEHEADER); // write compesssion, Width, Height, size if (error = pstm->Write(&hdfh, sizeof(hdfh), 0)) goto errRtn; // write the BITMAPINFOHEADER // REVIEW, does this size include the data? if ((error = pstm->Write(lpbmi, hdfh.dwSize, NULL)) == NOERROR) StSetSize(pstm, 0, TRUE); errRtn: GlobalUnlock(hdata); return(error); } #endif // _MAC FARINTERNAL UtHMFToMFStm(HANDLE FAR* lphMF, DWORD dwSize, LPSTREAM lpstream) { VDATEHEAP(); HRESULT error; // if there's no handle, there's nothing to do if (*lphMF == 0) return ResultFromScode(OLE_E_BLANK); #ifdef _MAC AssertSz(GetHandleSize((Handle)*lphMF) == dwSize, "pic hdl size not correct"); HLock( (HANDLE)*lphMF ); error = StWrite(lpstream, * (*lphMF), dwSize); // Eric: We should be unlocking, right? HUnlock((HANDLE)(*lphMF)); if (error != NOERROR) AssertSz(0, "StWrite failure" ); #else HANDLE hBits = NULL; void *lpBits; #ifdef WIN32 // allocate memory to hold the METAFILE bits // Bug 18346 - OLE16 use to get the Handle size of the Metafile which was a METAHEADER bigger than the // actual Metafile. Need to write out this much more worth of data so 16 bit dlls can read the Picture. dwSize += sizeof(METAHEADER); hBits = GlobalAlloc(GPTR, dwSize); if (hBits == NULL) return ResultFromScode(E_OUTOFMEMORY); if (!(lpBits = GlobalLock(hBits))) goto errRtn; // REVIEW, shouldn't we check the returned size? // REVIEW, what should we do about enhanced metafiles? If we // convert and write those out (which have more features that 32 bit // apps might use,) then you can't read the same document on a win16 // machine.... GetMetaFileBitsEx((HMETAFILE)*lphMF, dwSize, lpBits); // write the metafile bits out to the stream error = StWrite(lpstream, lpBits, dwSize); GlobalUnlock(hBits); errRtn: // free the metafile bits GlobalFree(hBits); #else if (!(hBits = GetMetaFileBits(*lphMF))) { error = ResultFromScode(E_OUTOFMEMORY); goto errRtn; } if (lpBits = GlobalLock(hBits)) { error = StWrite(lpstream, lpBits, dwSize); GlobalUnlock(hBits); } else error = ResultFromScode(E_OUTOFMEMORY); if (hBits) *lphMF = SetMetaFileBits(hBits); errRtn: #endif // WIN32 #endif // _MAC // set the stream size if (error == NOERROR) StSetSize(lpstream, 0, TRUE); return(error); } //+---------------------------------------------------------------------------- // // Function: // wPreparePlaceableMFHeader, static // // Synopsis: // Initializes a PLACEABLEMETAHEADER. // // Arguments: // [lpplac_mfh] -- pointer to the PLACEABLEMETAHEADER to initialize // [lWidth] -- Width of the metafile // REVIEW, in what units? // REVIEW, why is this not unsigned? // [lHeight] -- Height of the metafile // REVIEW, in what units? // REVIEW, why is this not unsigned? // // Notes: // // History: // 12/08/93 - ChrisWe - made static // //----------------------------------------------------------------------------- static INTERNAL_(void) wPreparePlaceableMFHeader( PLACEABLEMETAHEADER FAR* lpplac_mfh, LONG lWidth, LONG lHeight) { VDATEHEAP(); WORD FAR* lpw; // roves over the words included in the checksum lpplac_mfh->key = PMF_KEY; lpplac_mfh->hmf = 0; lpplac_mfh->inch = 576; // REVIEW, where's this magic number from? lpplac_mfh->bbox.left = 0; lpplac_mfh->bbox.top = 0; lpplac_mfh->bbox.right = (int) ((lWidth * lpplac_mfh->inch) / 2540); // REVIEW, more magic lpplac_mfh->bbox.bottom = (int) ((lHeight * lpplac_mfh->inch) / 2540); // REVIEW, more magic lpplac_mfh->reserved = NULL; // Compute the checksum of the 10 words that precede the checksum field. // It is calculated by XORing zero with those 10 words. for(lpplac_mfh->checksum = 0, lpw = (WORD FAR*)lpplac_mfh; lpw < (WORD FAR*)&lpplac_mfh->checksum; ++lpw) lpplac_mfh->checksum ^= *lpw; } FARINTERNAL UtHMFToPlaceableMFStm(HANDLE FAR* lphMF, DWORD dwSize, LONG lWidth, LONG lHeight, LPSTREAM pstm) { VDATEHEAP(); PLACEABLEMETAHEADER plac_mfh; HRESULT error; wPreparePlaceableMFHeader(&plac_mfh, lWidth, lHeight); // write the placeable header to the stream if (error = pstm->Write(&plac_mfh, sizeof(plac_mfh), NULL)) return(error); // write the rest of the METAFILE to the stream return UtHMFToMFStm(lphMF, dwSize, pstm); } FARINTERNAL UtMFStmToPlaceableMFStm(LPSTREAM pstmMF, DWORD dwSize, LONG lWidth, LONG lHeight, LPSTREAM pstmPMF) { VDATEHEAP(); PLACEABLEMETAHEADER plac_mfh; HRESULT error; ULARGE_INTEGER ularge_int; // indicates how much data to copy wPreparePlaceableMFHeader(&plac_mfh, lWidth, lHeight); // write the placeable header to the stream if (error = pstmPMF->Write(&plac_mfh, sizeof(plac_mfh), NULL)) return(error); // copy the METAFILE data from one stream to the other ULISet32(ularge_int, dwSize); if ((error = pstmMF->CopyTo(pstmPMF, ularge_int, NULL, NULL)) == NOERROR) StSetSize(pstmPMF, 0, TRUE); return(error); } //+------------------------------------------------------------------------- // // Function: UtWriteOlePresStmHeader, private // // Synopsis: Write the presentation stream header // // Effects: // // Arguments: [lpstream] -- destination stream // [pforetc] -- FORMATETC for this presentation // [dwAdvf] -- advise flags for the presentation // // Requires: // // Returns: HRESULT // // Modifies: // // Algorithm: // // History: 11-May-94 AlexT Added function header, translate to // ANSI before saving ptd // // Notes: This function can fail in low memory for presentations with // non-NULL ptds (since we allocate memory to do the conversion // to the persistent format). NtIssue #2789 // //-------------------------------------------------------------------------- FARINTERNAL UtWriteOlePresStmHeader(LPSTREAM lpstream, LPFORMATETC pforetc, DWORD dwAdvf) { VDATEHEAP(); HRESULT error; OLEPRESSTMHDR opsh; // write clip format // REVIEW, change name of this function? if (error = WriteClipformatStm(lpstream, pforetc->cfFormat)) return(error); // write target device info if (pforetc->ptd) { DVTDINFO dvtdInfo; DVTARGETDEVICE *ptdA; error = UtGetDvtd32Info(pforetc->ptd, &dvtdInfo); if (FAILED(error)) { return(error); } ptdA = (DVTARGETDEVICE *) PrivMemAlloc(dvtdInfo.cbConvertSize); if (NULL == ptdA) { return(E_OUTOFMEMORY); } error = UtConvertDvtd32toDvtd16(pforetc->ptd, &dvtdInfo, ptdA); if (SUCCEEDED(error)) { error = StWrite(lpstream, ptdA, ptdA->tdSize); } PrivMemFree(ptdA); if (FAILED(error)) { return(error); } } else { // if ptd is null then write 4 as size. // REVIEW, what is that the sizeof()? DWORD dwNullPtdLength = 4; if (error = StWrite(lpstream, &dwNullPtdLength, sizeof(DWORD))) return(error); } opsh.dwAspect = pforetc->dwAspect; opsh.dwLindex = pforetc->lindex; opsh.dwAdvf = dwAdvf; // write DVASPECT, lindex, advise flags return StWrite(lpstream, &opsh, sizeof(opsh)); } //+------------------------------------------------------------------------- // // Function: UtReadOlePresStmHeader // // Synopsis: Reads in a presentation stream header // // Arguments: [pstm] -- source stream // [pforetc] -- FORMATETC to be filled in // [pdwAdvf] -- advise flags to be filled in // [pfConvert] -- Mac conversion required, to be filled in // // Requires: // // Returns: HRESULT // // Modifies: // // Algorithm: // // History: 11-May-94 AlexT Added function header, translate ptd // from ANSI when loading // // Notes: // //-------------------------------------------------------------------------- FARINTERNAL UtReadOlePresStmHeader(LPSTREAM pstm, LPFORMATETC pforetc, DWORD FAR* pdwAdvf, BOOL FAR* pfConvert) { VDATEHEAP(); HRESULT error; DWORD dwRead; OLEPRESSTMHDR opsh; // initialize this for error return cases // Check for NULL ptr, as caller may not need this information if (pfConvert) { *pfConvert = FALSE; } // there's no target device information yet pforetc->ptd = NULL; // REVIEW, rename this function to indicate its origin? error = ReadClipformatStm(pstm, &dwRead); if (error == NOERROR) pforetc->cfFormat = (CLIPFORMAT)dwRead; else { #ifndef _MAC if (GetScode(error) == OLE_S_MAC_CLIPFORMAT) { // check whether the clipformat is "pict" // REVIEW, what's this cuteness? if (dwRead != *((DWORD *)"TCIP")) return(error); if (pfConvert) *pfConvert = TRUE; else return ResultFromScode(DV_E_CLIPFORMAT); pforetc->cfFormat = CF_METAFILEPICT; } else #endif return(error); } // set the proper tymed if (pforetc->cfFormat == CF_METAFILEPICT) { pforetc->tymed = TYMED_MFPICT; } else if (pforetc->cfFormat == CF_ENHMETAFILE) { pforetc->tymed = TYMED_ENHMF; } else if (pforetc->cfFormat == CF_BITMAP) { AssertSz(0, "We don't read/save CF_BITMAP anymore"); return ResultFromScode(DV_E_CLIPFORMAT); } else if (pforetc->cfFormat == NULL) { pforetc->tymed = TYMED_NULL; } else { pforetc->tymed = TYMED_HGLOBAL; } // Read targetdevice info. if (error = StRead(pstm, &dwRead, sizeof(dwRead))) return(error); // if the tdSize of ptd is non-null and is > 4, then go ahead read the // remaining data of the target device info if (dwRead > 4) { DVTARGETDEVICE *ptdA; DVTDINFO dvtdInfo; ptdA = (DVTARGETDEVICE *) PrivMemAlloc(dwRead); if (NULL == ptdA) { return ResultFromScode(E_OUTOFMEMORY); } ptdA->tdSize = dwRead; error = StRead(pstm, ((BYTE*)ptdA) + sizeof(dwRead), dwRead - sizeof(dwRead)); if (SUCCEEDED(error)) { error = UtGetDvtd16Info(ptdA, &dvtdInfo); if (SUCCEEDED(error)) { pforetc->ptd = (DVTARGETDEVICE *) PubMemAlloc(dvtdInfo.cbConvertSize); if (NULL == pforetc->ptd) { error = E_OUTOFMEMORY; } else { error = UtConvertDvtd16toDvtd32(ptdA, &dvtdInfo, pforetc->ptd); } } } PrivMemFree(ptdA); if (FAILED(error)) { goto errRtn; } } else pforetc->ptd = NULL; // Read DVASPECT, lindex, advise flags if ((error = StRead(pstm, &opsh, sizeof(opsh))) != NOERROR) goto errRtn; pforetc->dwAspect = opsh.dwAspect; pforetc->lindex = opsh.dwLindex; if (pdwAdvf) *pdwAdvf = opsh.dwAdvf; return NOERROR; errRtn: if (pforetc->ptd) { PubMemFree(pforetc->ptd); pforetc->ptd = NULL; } return(error); } FARINTERNAL UtOlePresStmToContentsStm(LPSTORAGE pstg, LPOLESTR lpszPresStm, BOOL fDeletePresStm, UINT FAR* puiStatus) { VDATEHEAP(); LPSTREAM pstmOlePres; LPSTREAM pstmContents = NULL; HRESULT error; FORMATETC foretc; HDIBFILEHDR hdfh; // there's no status yet *puiStatus = 0; // POSTPPC: // // This function needs to be rewritten to correctly handle the case described in // the comments below (rather than just skipping out of the function if the contents // stream already exists). The best course of action will probably be to convert // DIBs->Metafiles and Metafiles->DIBs in the needed cases. // The code inside the #ifdef below is used to determine if the contents // stream has already been created (which is the case for an object that has // been converted to a bitmap) because in the case of an object that has been // converted to a static DIB and the object has a METAFILE presentation stream // we already have a cachenode created as a DIB and we will read the contents // stream after this call to get the DIB data. However, this function sees // the metafile presentation, and converts it into the contents stream (which // when then try to load as a DIB) and bad things happen (it doesn't work). If // the stream already exists, then we bail out of this function. if (pstg->CreateStream(OLE_CONTENTS_STREAM,(STGM_READWRITE | STGM_SHARE_EXCLUSIVE), NULL, 0, &pstmContents) != NOERROR) { return NOERROR; } // created stream, it must not have existed pstmContents->Release(); pstg->DestroyElement(OLE_CONTENTS_STREAM); if ((error = pstg->OpenStream(lpszPresStm, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstmOlePres)) != NOERROR) { // we can't open the source stream *puiStatus |= CONVERT_NOSOURCE; // check whether "CONTENTS" stream exits if (pstg->OpenStream(OLE_CONTENTS_STREAM, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstmContents) != NOERROR) { // we can't open the destination stream either // REVIEW, since we can't open the source, who cares? // REVIEW, is there a cheaper way to test existence // other than opening? *puiStatus |= CONVERT_NODESTINATION; } else pstmContents->Release(); return(error); } foretc.ptd = NULL; if (error = UtReadOlePresStmHeader(pstmOlePres, &foretc, NULL, NULL)) goto errRtn; if (error = pstmOlePres->Read(&hdfh, sizeof(hdfh), 0)) goto errRtn; AssertSz(hdfh.dwCompression == 0, "Non-zero compression not supported"); if (error = OpenOrCreateStream(pstg, OLE_CONTENTS_STREAM, &pstmContents)) { *puiStatus |= CONVERT_NODESTINATION; goto errRtn; } if (foretc.dwAspect == DVASPECT_ICON) { *puiStatus |= CONVERT_SOURCEISICON; fDeletePresStm = FALSE; error = NOERROR; goto errRtn; } if (foretc.cfFormat == CF_DIB) error = UtDIBStmToDIBFileStm(pstmOlePres, hdfh.dwSize, pstmContents); else if (foretc.cfFormat == CF_METAFILEPICT) error = UtMFStmToPlaceableMFStm(pstmOlePres, hdfh.dwSize, hdfh.dwWidth, hdfh.dwHeight, pstmContents); else error = ResultFromScode(DV_E_CLIPFORMAT); errRtn: if (pstmOlePres) pstmOlePres->Release(); if (pstmContents) pstmContents->Release(); if (foretc.ptd) PubMemFree(foretc.ptd); if (error == NOERROR) { if (fDeletePresStm && lpszPresStm) pstg->DestroyElement(lpszPresStm); } else { pstg->DestroyElement(OLE_CONTENTS_STREAM); } return(error); } FARINTERNAL UtOlePresStmToContentsStm(LPSTORAGE pstg, LPOLESTR lpszPresStm, LPSTREAM pstmContents, UINT FAR* puiStatus) { HRESULT error = S_OK; LPSTREAM pstmOlePres = NULL; FORMATETC foretc; HDIBFILEHDR hdfh; // there's no status yet *puiStatus = 0; if ((error = pstg->OpenStream(lpszPresStm, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstmOlePres)) != NOERROR) { // we can't open the source stream *puiStatus |= CONVERT_NOSOURCE; return(error); } foretc.ptd = NULL; if (error = UtReadOlePresStmHeader(pstmOlePres, &foretc, NULL, NULL)) goto errRtn; if (error = pstmOlePres->Read(&hdfh, sizeof(hdfh), 0)) goto errRtn; AssertSz(hdfh.dwCompression == 0, "Non-zero compression not supported"); if (foretc.dwAspect == DVASPECT_ICON) { *puiStatus |= CONVERT_SOURCEISICON; error = NOERROR; goto errRtn; } if (foretc.cfFormat == CF_DIB) error = UtDIBStmToDIBFileStm(pstmOlePres, hdfh.dwSize, pstmContents); else if (foretc.cfFormat == CF_METAFILEPICT) error = UtMFStmToPlaceableMFStm(pstmOlePres, hdfh.dwSize, hdfh.dwWidth, hdfh.dwHeight, pstmContents); else error = ResultFromScode(DV_E_CLIPFORMAT); errRtn: if (pstmOlePres) pstmOlePres->Release(); return error; } FARINTERNAL_(HANDLE) UtGetHPRESFromNative(LPSTORAGE pstg, LPSTREAM pstm, CLIPFORMAT cfFormat, BOOL fOle10Native) { VDATEHEAP(); BOOL fReleaseStm = !pstm; HGLOBAL hdata = NULL; if ((cfFormat != CF_METAFILEPICT) && (cfFormat != CF_DIB) && (cfFormat != CF_ENHMETAFILE)) { return(NULL); } if (fOle10Native) { DWORD dwSize; if(!pstm) { if (pstg->OpenStream(OLE10_NATIVE_STREAM, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstm) != NOERROR) return(NULL); } if (pstm->Read(&dwSize, sizeof(DWORD), NULL) == NOERROR) { // is it PBrush native data? if (cfFormat == CF_DIB) UtGetHDIBFromDIBFileStm(pstm, &hdata); else { // MSDraw native data or PaintBrush // UtGetHMFPICTFromMSDrawNativeStm(pstm, dwSize, &hdata); } } } else { if(!pstm) { if (pstg->OpenStream(OLE_CONTENTS_STREAM, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstm) != NOERROR) return(NULL); } if (cfFormat == CF_DIB) { UtGetHDIBFromDIBFileStm(pstm, &hdata); } else if (cfFormat == CF_METAFILEPICT) { UtGetHMFPICTFromPlaceableMFStm(pstm, &hdata); } else { UtGetHEMFFromContentsStm(pstm, &hdata); } } if(fReleaseStm) pstm->Release(); return(hdata); }