//+---------------------------------------------------------------------------- // // File: // ole2util.cpp // // Contents: // Ole internal utility routines // // Classes: // // Functions: // // History: // 06/01/94 - AlexGo - UtQueryPictFormat now supports // enhanced metafiles // 03/18/94 - AlexGo - fixed UtGetPresStreamName (incorrect // string processing) // 01/11/94 - ChrisWe - don't reference unlocked handle in // UtConvertBitmapToDib // 01/11/94 - alexgo - added VDATEHEAP macro to every function // 12/07/93 - ChrisWe - removed incorrect uses of (LPOLESTR); // removed duplicate GetClassFromDataObj function, which // is the same as UtGetClassID // 11/30/93 - ChrisWe - continue file cleanup; don't open // streams in UtRemoveExtraOlePresStreams() // 11/28/93 - ChrisWe - file cleanup and inspection; // reformatted many functions // 11/22/93 - ChrisWe - replace overloaded ==, != with // IsEqualIID and IsEqualCLSID // 06/28/93 - SriniK - added UtGetDibExtents // 11/16/92 - JasonFul - created; moved contents here from util.cpp // //----------------------------------------------------------------------------- #include #pragma SEG(ole2util) NAME_SEG(Ole2Utils) ASSERTDATA #define WIDTHBYTES(i) ((i+31)/32*4) #define PALETTESIZE 256 /* Number of entries in the system palette */ // REVIEW, according to the spec, IDataObject::EnumFormatEtc() is only // required to service one dwDirection DATADIR_ value at a time. This // function has been asking it to do more than one at a time, and expecting // return of FORMATETCs that match all the requested directions. Code // seen in OleRegEnumFormatEtc() checks on creation, and fails if any // value other than plain DATADIR_GET or plain DATADIR_SET is specified // so this has clearly never worked for OLE1, or registration database lookups // since the only caller of UtIsFormatSupported has always asked for both // at the same time. #pragma SEG(UtIsFormatSupported) FARINTERNAL_(BOOL) UtIsFormatSupported(IDataObject FAR* lpDataObj, DWORD dwDirection, CLIPFORMAT cfFormat) { VDATEHEAP(); FORMATETC formatetc; // a place to fetch formats from the enumerator IEnumFORMATETC FAR* penm; // enumerates the formats of [lpDataObj] ULONG ulNumFetched; // a count of the number of formats fetched HRESULT error; // the error state so far // try to get the enumerator from the data object error = lpDataObj->EnumFormatEtc(dwDirection, &penm); if (error != NOERROR) { if (FAILED(error)) return FALSE; else { CLSID clsid; // Use reg db; this case is primarily for the OLE1 // compatibility code since it may talk to a data // object from a server in the same process as // the server. if (UtGetClassID(lpDataObj, &clsid) != TRUE) return(FALSE); // synthesize an enumerator // REVIEW, if the data object is synthesized for // the OLE1 object, why doesn't that implementation // go ahead and synthesize this? Why does it have // to be done like this? What if it's on the clipboard // and someone wants to use it? if (OleRegEnumFormatEtc(clsid, dwDirection, &penm) != NOERROR) return FALSE; Assert(penm); } } // check for the format we're looking for while(NOERROR == (error = penm->Next(1, &formatetc, &ulNumFetched))) { if ((ulNumFetched == 1) && (formatetc.cfFormat == cfFormat)) break; } // release the enumerator penm->Release(); // if error isn't S_FALSE, we fetched an item, and broke out of the // while loop above --> the format was found. Return TRUE indicating // that the format is supported return(error == NOERROR ? TRUE : FALSE); } #pragma SEG(UtDupPalette) FARINTERNAL_(HPALETTE) UtDupPalette(HPALETTE hpalette) { VDATEHEAP(); WORD cEntries; // holds the number of entries in the palette HANDLE hLogPal; // ia a handle to a new logical palette LPLOGPALETTE pLogPal; // is a pointer to the new logical palette HPALETTE hpaletteNew = NULL; // the new palette we will return if (0 == GetObject(hpalette, sizeof(cEntries), &cEntries)) return(NULL); if (NULL == (hLogPal = GlobalAlloc(GMEM_MOVEABLE, sizeof (LOGPALETTE) + cEntries * sizeof (PALETTEENTRY)))) return(NULL); if (NULL == (pLogPal = (LPLOGPALETTE)GlobalLock(hLogPal))) goto errRtn; if (0 == GetPaletteEntries(hpalette, 0, cEntries, pLogPal->palPalEntry)) goto errRtn; pLogPal->palVersion = 0x300; pLogPal->palNumEntries = cEntries; if (NULL == (hpaletteNew = CreatePalette(pLogPal))) goto errRtn; errRtn: if (pLogPal) GlobalUnlock(hLogPal); if (hLogPal) GlobalFree(hLogPal); AssertSz(hpaletteNew, "Warning: UtDupPalette Failed"); return(hpaletteNew); } //+------------------------------------------------------------------------- // // Function: UtFormatToTymed // // Synopsis: gets the right TYMED for the given rendering format // // Effects: // // Arguments: [cf] -- the clipboard format // // Requires: // // Returns: one of the TYMED enumeration // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 07-Jul-94 alexgo added EMF's // // Notes: This should only be called for formats that we can // render // //-------------------------------------------------------------------------- #pragma SEG(UtFormatToTymed) FARINTERNAL_(DWORD) UtFormatToTymed(CLIPFORMAT cf) { VDATEHEAP(); if( cf == CF_METAFILEPICT ) { return TYMED_MFPICT; } else if( cf == CF_BITMAP ) { return TYMED_GDI; } else if( cf == CF_DIB ) { return TYMED_HGLOBAL; } else if( cf == CF_ENHMETAFILE ) { return TYMED_ENHMF; } else if( cf == CF_PALETTE ) { LEWARN(1,"Trying to render CF_PALETTE"); return TYMED_GDI; } LEDebugOut((DEB_WARN, "WARNING: trying to render clipformat (%lx)\n", cf)); return TYMED_HGLOBAL; } //+------------------------------------------------------------------------- // // Function: UtQueryPictFormat // // Synopsis: finds our "preferred" drawing formatetc from the given // data object // // Effects: // // Arguments: [lpSrcDataObj] -- the source data object // [lpforetc] -- where to stuff the preferred format // // Requires: // // Returns: // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 01-Jun-94 alexgo rewrite/now supports Enhanced Metafiles // // Notes: // //-------------------------------------------------------------------------- #pragma SEG(UtQueryPictFormat) FARINTERNAL_(BOOL) UtQueryPictFormat(LPDATAOBJECT lpSrcDataObj, LPFORMATETC lpforetc) { FORMATETC foretctemp; // local copy of current values of format desc VDATEHEAP(); LEDebugOut((DEB_ITRACE, "%p _IN UtQueryPictFormat ( %p , %p )\n", NULL, lpSrcDataObj, lpforetc)); // copy format descriptor foretctemp = *lpforetc; // set values and query for our preferred formats in order of // preference foretctemp.cfFormat = CF_METAFILEPICT; foretctemp.tymed = TYMED_MFPICT; if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR) { goto QuerySuccess; } foretctemp.cfFormat = CF_ENHMETAFILE; foretctemp.tymed = TYMED_ENHMF; if( lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR ) { goto QuerySuccess; } foretctemp.cfFormat = CF_DIB; foretctemp.tymed = TYMED_HGLOBAL; if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR) { goto QuerySuccess; } foretctemp.cfFormat = CF_BITMAP; foretctemp.tymed = TYMED_GDI; if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR) { goto QuerySuccess; } LEDebugOut((DEB_ITRACE, "%p OUT UtQueryPictFormat ( %lu )\n", NULL, FALSE)); return FALSE; QuerySuccess: // data object supports this format; change passed in // format to match lpforetc->cfFormat = foretctemp.cfFormat; lpforetc->tymed = foretctemp.tymed; // return success LEDebugOut((DEB_ITRACE, "%p OUT UtQueryPictFormat ( %lu )\n", NULL, TRUE)); return(TRUE); } #pragma SEG(UtConvertDibToBitmap) FARINTERNAL_(HBITMAP) UtConvertDibToBitmap(HANDLE hDib) { VDATEHEAP(); LPBITMAPINFOHEADER lpbmih; HDC hdc; // the device context to create the bitmap for size_t uBitsOffset; // the offset to where the image begins in the DIB HBITMAP hBitmap; // the bitmap we'll return if (!(lpbmih = (LPBITMAPINFOHEADER)GlobalLock(hDib))) return(NULL); if (!(hdc = GetDC(NULL))) // Get screen DC. { // REVIEW: we may have to use the target device of this // cache node. return(NULL); } uBitsOffset = sizeof(BITMAPINFOHEADER) + (lpbmih->biClrUsed ? lpbmih->biClrUsed : UtPaletteSize(lpbmih)); hBitmap = CreateDIBitmap(hdc, lpbmih, CBM_INIT, ((BYTE *)lpbmih)+uBitsOffset, (LPBITMAPINFO) lpbmih, DIB_RGB_COLORS); // release the DC ReleaseDC(NULL, hdc); return hBitmap; } //+---------------------------------------------------------------------------- // // Function: // UtConvertBitmapToDib, internal // // Synopsis: // Creates a Device Independent Bitmap capturing the content of // the argument bitmap. // // Arguments: // [hBitmap] -- Handle to the bitmap to convert // [hpal] -- color palette for the bitmap; may be null for // default stock palette // // Returns: // Handle to the DIB. May be null if any part of the conversion // failed. // // Notes: // // History: // 11/29/93 - ChrisWe - file inspection and cleanup // 07/18/94 - DavePl - fixed for 16, 32, bpp bitmaps // //----------------------------------------------------------------------------- FARINTERNAL_(HANDLE) UtConvertBitmapToDib(HBITMAP hBitmap, HPALETTE hpal) { VDATEHEAP(); HDC hScreenDC; BITMAP bm; // bitmap for hBitmap UINT uBits; // number of color bits for bitmap size_t uBmiSize; // size of bitmap info for the DIB size_t biSizeImage; // temp to hold value in the handle memory HANDLE hBmi; // handle for the new DIB bitmap we'll create LPBITMAPINFOHEADER lpBmi; // pointer to the actual data area for DIB HANDLE hDib = NULL; // the DIB we'll return BOOL fSuccess = FALSE; DWORD dwCompression; BOOL fDeletePalette = FALSE; if (NULL == hBitmap) { return(NULL); } // if no palette provided, use the default if (NULL == hpal) { // This block fixes NTBUG #13029. The problem is that on a palette // device (ie a 256 color video driver), we don't get passed the palette // that is used by the DDB. So, we build the palette based on what // is currently selected into the system palette. // POSTPPC: // // We should change the clipboard code that calls this to ask for // CF_PALETTE from the IDataObject that the DDB was obtained from, that // way we know we get the colors that the calling app really intended HDC hDCGlobal = GetDC(NULL); int iRasterCaps = GetDeviceCaps(hDCGlobal, RASTERCAPS); ReleaseDC(NULL, hDCGlobal); if ((iRasterCaps & RC_PALETTE)) { // Based the following code from the win sdk MYPAL example program. // this creates a palette out of the currently active palette. HANDLE hLogPal = GlobalAlloc (GHND, (sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * (PALETTESIZE)))); // if we are OOM, return failure now, because we aren't going // to make it through the allocations later on. if (!hLogPal) return NULL; LPLOGPALETTE pLogPal = (LPLOGPALETTE)GlobalLock (hLogPal); // 0x300 is a magic number required by GDI pLogPal->palVersion = 0x300; pLogPal->palNumEntries = PALETTESIZE; // fill in intensities for all palette entry colors for (int iLoop = 0; iLoop < PALETTESIZE; iLoop++) { *((WORD *) (&pLogPal->palPalEntry[iLoop].peRed)) = (WORD)iLoop; pLogPal->palPalEntry[iLoop].peBlue = 0; pLogPal->palPalEntry[iLoop].peFlags = PC_EXPLICIT; } // create a logical color palette according the information // in the LOGPALETTE structure. hpal = CreatePalette ((LPLOGPALETTE) pLogPal) ; GlobalUnlock(hLogPal); GlobalFree(hLogPal); if (!hpal) return NULL; fDeletePalette = TRUE; } else { hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); } } if (NULL == GetObject(hBitmap, sizeof(bm), (LPVOID)&bm)) { return(NULL); } uBits = bm.bmPlanes * bm.bmBitsPixel; // Based on the number of bits per pixel, set up the size // of the color table, and the compression type as per the // the following table: // // // BPP Palette Size Compression // ~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~ // 1,2,4,8 2^BPP * sizeof(RGBQUAD) None // 16, 32 3 * sizeof(DWORD) masks BI_BITFIELDS // 24 0 None if (16 == bm.bmBitsPixel || 32 == bm.bmBitsPixel) { uBmiSize = sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD); dwCompression = BI_BITFIELDS; } else if (24 == bm.bmBitsPixel) { uBmiSize = sizeof(BITMAPINFOHEADER); dwCompression = BI_RGB; } else { Assert( bm.bmBitsPixel == 1 || bm.bmBitsPixel == 2 || bm.bmBitsPixel == 4 || bm.bmBitsPixel == 8 ); // VGA and EGA are planar devices on Chicago, so uBits needs // to be used when determining the size of the bitmap info + // the size of the color table. uBmiSize = sizeof(BITMAPINFOHEADER) + (1 << uBits) * sizeof(RGBQUAD); dwCompression = BI_RGB; } // Allocate enough memory to hold the BITMAPINFOHEADER hBmi = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)uBmiSize); if (NULL == hBmi) { return NULL; } lpBmi = (LPBITMAPINFOHEADER) GlobalLock(hBmi); if (NULL == lpBmi) { GlobalFree(hBmi); return NULL; } // Set up any interesting non-zero fields lpBmi->biSize = (LONG)sizeof(BITMAPINFOHEADER); lpBmi->biWidth = (LONG) bm.bmWidth; lpBmi->biHeight = (LONG) bm.bmHeight; lpBmi->biPlanes = 1; lpBmi->biBitCount = uBits; lpBmi->biCompression = dwCompression; // Grab the screen DC and set out palette into it hScreenDC = GetDC(NULL); if (NULL == hScreenDC) { GlobalUnlock(hBmi); goto errRtn; } // Call GetDIBits with a NULL lpBits parm, so that it will calculate // the biSizeImage field for us GetDIBits(hScreenDC, // DC hBitmap, // Bitmap handle 0, // First scan line bm.bmHeight, // Number of scan lines NULL, // Buffer (LPBITMAPINFO)lpBmi, // BITMAPINFO DIB_RGB_COLORS); // If the driver did not fill in the biSizeImage field, make one up if (0 == lpBmi->biSizeImage) { LEDebugOut((DEB_WARN, "WARNING: biSizeImage was not computed for us\n")); lpBmi->biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * uBits) * bm.bmHeight; } // Realloc the buffer to provide space for the bits. Use a new handle so // that in the failure case we do not lose the exiting handle, which we // would need to clean up properly. biSizeImage = lpBmi->biSizeImage; GlobalUnlock(hBmi); hDib = GlobalReAlloc(hBmi, (uBmiSize + biSizeImage), GMEM_MOVEABLE); if (NULL == hDib) { goto errRtn; } // If the realloc succeeded, we can get rid of the old handle hBmi = NULL; // re-acquire the pointer to the handle lpBmi = (LPBITMAPINFOHEADER)GlobalLock(hDib); if (NULL == lpBmi) { goto errRtn; } hpal = SelectPalette(hScreenDC, hpal, FALSE); RealizePalette(hScreenDC); // Call GetDIBits with a NON-NULL lpBits parm, and get the actual bits if (GetDIBits(hScreenDC, // DC hBitmap, // HBITMAP 0, // First scan line (WORD)lpBmi->biHeight, // Count of scan lines ((BYTE FAR *)lpBmi)+uBmiSize, // Bitmap bits (LPBITMAPINFO)lpBmi, // BITMAPINFOHEADER DIB_RGB_COLORS) // Palette style ) { fSuccess = TRUE; } GlobalUnlock(hDib); errRtn: if (hScreenDC) { // Select back the old palette into the screen DC SelectPalette(hScreenDC, hpal, FALSE); ReleaseDC(NULL, hScreenDC); } if (fDeletePalette) { DeleteObject(hpal); } // If we failed, we need to free up the header and the DIB // memory if (FALSE == fSuccess) { if (hBmi) { GlobalFree(hBmi); } if (hDib) { GlobalFree(hDib); hDib = NULL; } } return(hDib); } //+---------------------------------------------------------------------------- // // Function: // UtPaletteSize, internal // // Synopsis: // Returns the size of a color table for a palette given the // number of bits of color desired. // // Basically, the number of color table entries is: // // 1BPP // 1<<1 = 2 // // 4BPP // if pbmi->biClrUsed is not zero and is less than 16, then use pbmi->biClrUsed, // otherwise use 1 << 4 = 16 // // 8BPP // if pbmi->biClrUsed is not zero and is less than 256, then use pbmi->biClrUsed, // otherwise use 1 << 8 = 256 // // 16BPP // if pbmi->biCompression is BITFIELDS then there are three color entries, // otherwise no color entries. // // 24BPP // pbmi->biCompression must be BI_RGB, there is no color table. // // 32BPP // if pbmi->biCompression is BITFIELDS then there are three color entries, // otherwise no color entries. // // // There is never a case with a color table larger than 256 colors. // // Arguments: // [lpHeader] -- ptr to BITMAPINFOHEADER structure // // Returns: // Size in bytes of color information // // Notes: // // History: // 11/29/93 - ChrisWe - change bit count argument to unsigned, // and return value to size_t // // 07/18/94 - DavePl - Fixed for 16, 24, 32bpp DIBs // //----------------------------------------------------------------------------- FARINTERNAL_(size_t) UtPaletteSize(BITMAPINFOHEADER * pbmi) { DWORD dwSize; WORD biBitCount = pbmi->biBitCount; VDATEHEAP(); // Compute size of color table information in a DIB. if (8 >= biBitCount) { if (pbmi->biClrUsed && (pbmi->biClrUsed < (DWORD) (1 << biBitCount)) ) { dwSize = pbmi->biClrUsed * sizeof(RGBQUAD); } else { Assert(0 == pbmi->biClrUsed); dwSize = (1 << biBitCount) * sizeof(RGBQUAD); } } else if (BI_BITFIELDS == pbmi->biCompression) { Assert(24 != biBitCount); // BI_BITFIELDS should never be set for 24 bit. dwSize = 3 * sizeof(RGBQUAD); } else { dwSize = 0; } Assert( (dwSize < 65536) && "Palette size overflows WORD"); return dwSize; } //+------------------------------------------------------------------------- // // Function: UtGetDibExtents // // Synopsis: Returns the size of the DIB in HIMETRIC units // // Effects: // // Arguments: [lpbmi] -- the BITMAPINFOHEADER for the DIB // [plWidth] -- OUT param for width // [plHeight] -- OUT param for height // // Requires: // // Returns: // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 04-Aug-94 Davepl Corrected logic // // Notes: // //-------------------------------------------------------------------------- FARINTERNAL_(void) UtGetDibExtents(LPBITMAPINFOHEADER lpbmi, LONG FAR* plWidth, LONG FAR* plHeight) { VDATEHEAP(); #define HIMET_PER_METER 100000L // number of HIMETRIC units / meter if (!(lpbmi->biXPelsPerMeter && lpbmi->biYPelsPerMeter)) { HDC hdc; hdc = GetDC(NULL); lpbmi->biXPelsPerMeter = MulDiv(GetDeviceCaps(hdc, LOGPIXELSX), 10000, 254); lpbmi->biYPelsPerMeter = MulDiv(GetDeviceCaps(hdc, LOGPIXELSY), 10000, 254); ReleaseDC(NULL, hdc); } *plWidth = (lpbmi->biWidth * HIMET_PER_METER / lpbmi->biXPelsPerMeter); *plHeight= (lpbmi->biHeight * HIMET_PER_METER / lpbmi->biYPelsPerMeter); // no longer need this #undef HIMET_PER_METER } #pragma SEG(UtGetClassID) FARINTERNAL_(BOOL) UtGetClassID(LPUNKNOWN lpUnk, CLSID FAR* lpClsid) { VDATEHEAP(); LPOLEOBJECT lpOleObj; // IOleObject pointer LPPERSIST lpPersist; // IPersist pointer // try to ask it as an object if (lpUnk->QueryInterface(IID_IOleObject, (LPLPVOID)&lpOleObj) == NOERROR) { lpOleObj->GetUserClassID(lpClsid); lpOleObj->Release(); return(TRUE); } // try to ask it as a persistent object if (lpUnk->QueryInterface(IID_IPersist, (LPLPVOID)&lpPersist) == NOERROR) { lpPersist->GetClassID(lpClsid); lpPersist->Release(); return(TRUE); } *lpClsid = CLSID_NULL; return(FALSE); } #pragma SEG(UtGetIconData) FARINTERNAL UtGetIconData(LPDATAOBJECT lpSrcDataObj, REFCLSID rclsid, LPFORMATETC lpforetc, LPSTGMEDIUM lpstgmed) { VDATEHEAP(); CLSID clsid = rclsid; lpstgmed->tymed = TYMED_NULL; lpstgmed->pUnkForRelease = NULL; lpstgmed->hGlobal = NULL; if (lpSrcDataObj) { if (lpSrcDataObj->GetData(lpforetc, lpstgmed) == NOERROR) return NOERROR; if (IsEqualCLSID(clsid, CLSID_NULL)) UtGetClassID(lpSrcDataObj, &clsid); } // get data from registration database lpstgmed->hGlobal = OleGetIconOfClass(clsid, NULL, TRUE); if (lpstgmed->hGlobal == NULL) return ResultFromScode(E_OUTOFMEMORY); else lpstgmed->tymed = TYMED_MFPICT; return NOERROR; } // Performs operation like COPY, MOVE, REMOVE etc.. on src, dst storages. The // caller can specifiy which streams to be operated upon through // grfAllowedStreams parameter. STDAPI UtDoStreamOperation(LPSTORAGE pstgSrc, LPSTORAGE pstgDst, int iOpCode, DWORD grfAllowedStmTypes) { VDATEHEAP(); HRESULT error; // error status so far IEnumSTATSTG FAR* penumStg; // used to enumerate the storage elements ULONG celtFetched; // how many storage elements were fetched STATSTG statstg; // get an enumerator over the source storage if (error = pstgSrc->EnumElements(NULL, NULL, NULL, &penumStg)) return error; // repeat for every storage while(penumStg->Next(1, &statstg, &celtFetched) == NOERROR) { // operate on streams that we're interested in if (statstg.type == STGTY_STREAM) { DWORD stmType; // find the type of the stream // REVIEW, we must have constants for these name // prefixes!!! switch (statstg.pwcsName[0]) { case '\1': stmType = STREAMTYPE_CONTROL; break; case '\2': stmType = STREAMTYPE_CACHE; break; case '\3': stmType = STREAMTYPE_CONTAINER; break; default: stmType = (DWORD)STREAMTYPE_OTHER; } // check whether it should be operated upon if (stmType & grfAllowedStmTypes) { switch(iOpCode) { #ifdef LATER case OPCODE_COPY: pstgDst->DestroyElement( statstg.pwcsName); error = pstgSrc->MoveElementTo( statstg.pwcsName, pstgDst, statstg.pwcsName, STGMOVE_COPY); break; case OPCODE_MOVE: pstgDst->DestroyElement( statstg.pwcsName); error = pstgSrc->MoveElementTo( statstg.pwcsName, pstgDst, statstg.pwcsName, STGMOVE_MOVE); break; case OPCODE_EXCLUDEFROMCOPY: AssertSz(FALSE, "Not yet implemented"); break; #endif // LATER case OPCODE_REMOVE: error = pstgSrc->DestroyElement( statstg.pwcsName); break; default: AssertSz(FALSE, "Invalid opcode"); break; } } } // if the enumerator allocated a new name string, get rid of it if (statstg.pwcsName) PubMemFree(statstg.pwcsName); // quit the enumeration loop if we've hit an error if (error != NOERROR) break; } // release the enumerator penumStg->Release(); // return the error state return error; } FARINTERNAL_(void) UtGetPresStreamName(LPOLESTR lpszName, int iStreamNum) { VDATEHEAP(); int i; // counts down the digits of iStreamNum // count down the last three '0' characters of OLE_PRESENTATION_STREAM // the -2 backs us up to the last character (remember the NULL // terminator!) for(lpszName += sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR) - 2, i = 3; i; --lpszName, --i) { *lpszName = OLESTR("0123456789")[iStreamNum % 10]; if( iStreamNum > 0 ) { iStreamNum /= 10; } } } FARINTERNAL_(void) UtRemoveExtraOlePresStreams(LPSTORAGE pstg, int iStart) { VDATEHEAP(); HRESULT hr; // error code from stream deletion OLECHAR szName[sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)]; // space for the stream names // if the stream number is invalid, do nothing if ((iStart < 0) || (iStart >= OLE_MAX_PRES_STREAMS)) return; // create presentation stream name _xstrcpy(szName, OLE_PRESENTATION_STREAM); UtGetPresStreamName(szName, iStart); // for each of these streams that exists, get rid of it while((hr = pstg->DestroyElement(szName)) == NOERROR) { // if we've gotten to the end of the possible streams, quit if (++iStart >= OLE_MAX_PRES_STREAMS) break; // Get the next presentation stream name UtGetPresStreamName(szName, iStart); } // since the only reason these streams should be open, the first // failure had better be that the file was not found, and not // anything else (such as STG_E_ACCESSDENIED) AssertSz(hr == STG_E_FILENOTFOUND, "UtRemoveExtraOlePresStreams failure"); } //+------------------------------------------------------------------------- // // Function: ConvertPixelsToHIMETRIC // // Synopsis: Converts a pixel dimension to HIMETRIC units // // Effects: // // Arguments: [hdcRef] -- the reference DC // [ulPels] -- dimension in pixel measurement // [pulHIMETRIC] -- OUT param of converted HIMETRIC result // [tDimension] -- indicates XDIMENSION or YDIMENSION of input // // Returns: S_OK, E_FAIL // // Algorithm: screen_mm * input_pels HIMETRICS/ // ---------------------- * / == HIMETRICS // screen_pels /mm // // History: dd-mmm-yy Author Comment // 04-Aug-94 Davepl Created // // Notes: We need to know whether the input size is in the X or // Y dimension, since the aspect ratio could vary // //-------------------------------------------------------------------------- FARINTERNAL ConvertPixelsToHIMETRIC (HDC hdcRef, ULONG lPels, ULONG * pulHIMETRIC, DIMENSION tDimension) { VDATEHEAP(); VDATEPTROUT(pulHIMETRIC, ULONG *); // Clear OUT parameter in case of error *pulHIMETRIC = 0; ULONG scrmm = 0; ULONG scrpel = 0; const ULONG HIMETRIC_PER_MM = 100; // If we weren't given a reference DC, use the screen as a default BOOL fLocalDC = FALSE; if (NULL == hdcRef) { hdcRef = GetDC(NULL); if (hdcRef) { fLocalDC = TRUE; } } if (hdcRef) { Assert(tDimension == XDIMENSION || tDimension == YDIMENSION); // Get the count of pixels and millimeters for the screen if (tDimension == XDIMENSION) { scrmm = GetDeviceCaps(hdcRef, HORZSIZE); scrpel = GetDeviceCaps(hdcRef, HORZRES); } else { scrmm = GetDeviceCaps(hdcRef, VERTSIZE); scrpel = GetDeviceCaps(hdcRef, VERTRES); } // If we had to create a temporary DC, it can be released now if (TRUE == fLocalDC) { ReleaseDC(NULL, hdcRef); } } // If we successfully obtained the DC's size and resolution, // we can compute the HIMETRIC value. if (scrmm && scrpel) { *pulHIMETRIC = (scrmm * lPels * HIMETRIC_PER_MM) / scrpel; return S_OK; } return E_FAIL; }