|
|
// Microsoft Corporation 1997
//
// This file contains methods for copying and releasing STGMEDIUMs and BINDINFOs
// (which contains a STGMEDIUM).
//
// Created: 8-15-97 t-gpease
//
#include <urlmon.hxx>
#undef URLMONOFFSETOF
#define URLMONOFFSETOF(t,f) ((DWORD_PTR)(&((t*)0)->f))
//
// This function clears the BINDINFO structure.
//
//- The "cbSize" will not be clear and will be the same as it
// was pasted in. This is by design so that you can reuse the
// BINDINFO (eg copy another BINDINFO into it).
//
//- It does NOT release the memory that the BINDINFO oocupies
// (this could be on the stack).
//
//- It does properly release items that the BINDINFO might be
// pointing to.
//
STDAPI_(void) ReleaseBindInfo(BINDINFO * pbindinfo) { if ( !pbindinfo) return;
DWORD cb = pbindinfo->cbSize;
UrlMkAssert( cb && "CopyBindInfo(): cbSize of the BINDINFO is ZERO. We need the cbSize to be set before calling us."); if(!cb ) return; // we don't know which structure it is, so don't touch it.
if (cb >= URLMONOFFSETOF(BINDINFO, dwReserved) && pbindinfo->pUnk) { pbindinfo->pUnk->Release(); }
// Orginal BINDINFO no need to check size
if (pbindinfo->szExtraInfo) { delete [] pbindinfo->szExtraInfo; }
// Orginal BINDINFO no need to check size
if (pbindinfo->szCustomVerb) { delete [] pbindinfo->szCustomVerb; }
// Orginal BINDINFO no need to check size
ReleaseStgMedium(&pbindinfo->stgmedData);
// set this to zero so other function will not try to use the BINDINFO
ZeroMemory(pbindinfo, cb); pbindinfo->cbSize = cb; // but keep this intact
return; }
//
// This function copies STGMEDIUM stuctures.
//
//- Users need to allocate the memory that the STGMEDIUM Dest will be copied
// into.
//
//- If anything goes wrong, we return the proper HRESULT and STGMEDIUM.will
// have been zero-ed.
//
STDAPI CopyStgMedium(const STGMEDIUM * pcstgmedSrc, STGMEDIUM * pstgmedDest) { HRESULT hr = S_OK;
if ( !pcstgmedSrc || !pstgmedDest ) return E_POINTER;
ZeroMemory(pstgmedDest, sizeof(*pstgmedDest));
switch (pcstgmedSrc->tymed) {
case TYMED_HGLOBAL: { void * pvDest; const void * pcvSrc; DWORD_PTR dwcbLen; HGLOBAL hGlobalDest;
if (!pcstgmedSrc->hGlobal) break; // nothing to do
hr = E_OUTOFMEMORY; pcvSrc = GlobalLock(pcstgmedSrc->hGlobal); if (!pcvSrc) goto Cleanup;
dwcbLen = GlobalSize(pcstgmedSrc->hGlobal); // We can't do the following line:
// hGlobalDest = GlobalAlloc((GMEM_MOVEABLE | GMEM_SHARE), dwcbLen);
// because we hand out the bindinfo.stgmedData.hglobal to callers
// that do NOT lock it and use the handle instead of the pointer.
hGlobalDest = GlobalAlloc(GMEM_FIXED | GMEM_SHARE, dwcbLen); if (!hGlobalDest) { GlobalUnlock(pcstgmedSrc->hGlobal); goto Cleanup; }
pvDest = GlobalLock(hGlobalDest); if (!pvDest) { GlobalFree(hGlobalDest); GlobalUnlock(pcstgmedSrc->hGlobal); goto Cleanup; }
UrlMkAssert(dwcbLen>>32 == 0); memcpy(pvDest, pcvSrc, (unsigned long)dwcbLen);
pstgmedDest->hGlobal = hGlobalDest;
GlobalUnlock(hGlobalDest); GlobalUnlock(pcstgmedSrc->hGlobal); hr = S_OK; } break;
case TYMED_FILE: { if (!pcstgmedSrc->lpszFileName) break; // nothing to do
hr = E_OUTOFMEMORY;
LPWSTR lpwstr = OLESTRDuplicate(pcstgmedSrc->lpszFileName); if (!lpwstr) goto Cleanup;
pstgmedDest->lpszFileName = lpwstr;
hr = S_OK; } break;
case TYMED_ISTREAM: { pstgmedDest->pstm = pcstgmedSrc->pstm; if ( pstgmedDest->pstm ) pstgmedDest->pstm->AddRef(); } break;
case TYMED_ISTORAGE: { pstgmedDest->pstg = pcstgmedSrc->pstg; if ( pstgmedDest->pstg ) pstgmedDest->pstg->AddRef(); } break;
default: UrlMkAssert( !"CloneStgMedium has encountered a TYMED it doesn't know how to copy." ); // fall thru and copy it.
case TYMED_NULL: // blindly copy
case TYMED_GDI: // Just copy...
memcpy(pstgmedDest, pcstgmedSrc, sizeof(*pstgmedDest)); break; }
// Common things that can be copied if we get to this point.
pstgmedDest->tymed = pcstgmedSrc->tymed; pstgmedDest->pUnkForRelease = pcstgmedSrc->pUnkForRelease; if (pstgmedDest->pUnkForRelease) (pstgmedDest->pUnkForRelease)->AddRef();
Cleanup: return hr; }
//
// This function copies BINDINFO structures.
//
// NOTE: IE4 added properties to the BINDINFO structure. This function
// works with both versions. If the structure is extended in the
// future, it will blindly copy the additional properties in the
// structure.
//
//- Users need to allocate the memory that the BINDINFO Dest will be copied
// into.
//
//- Users also need to set the "cbSize" of the BINDINFO Dest to
// the sizeof(BINDINFO) before calling (see NOTE above).
//
//- If there is a "cbSize" conflict between the Src and the Dest, we will:
// 1) Src->cbSize = Dest->cbSize, normal copy.
// 2) Src->cbSize > Dest->cbSize, copy as much info about the Src into
// the Dest as will fit.
// 3) Src->cbSize < Dest->cbSize, copy the Src into the Dest, Zero the
// remaining unfilled portion of the Dest.
//
//- We don't not copy the securityattribute. We clear this value of the
// BINDINFO Dest.
//
//- If anything goes wrong, we return the proper HRESULT and clear the
// the BINDINFO structure using ReleaseBindInfo() (below).
// NOTE: If "cbSize" of the Dest is ZERO, we don't do anything.
//
STDAPI CopyBindInfo( const BINDINFO * pcbiSrc, BINDINFO *pbiDest ) { /****** 8-15-97 t-gpease
Current structure at the time of writing... from URLMON.H typedef struct tagBINDINFO { ULONG cbSize; LPWSTR szExtraInfo; STGMEDIUM stgmedData; DWORD grfBindInfoF; DWORD dwBindVerb; LPWSTR szCustomVerb; DWORD cbstgmedData; // new part below this line //
DWORD dwOptions; DWORD dwOptionsFlags; DWORD dwCodePage; SECURITY_ATTRIBUTES securityAttributes; IID iid; IUnknown __RPC_FAR *pUnk; DWORD dwReserved; } BINDINFO;
Anything bigger than this we will blindly copy.the size of cbSize *******/
// NOTE: hr will an error until just before the Cleanup label.
HRESULT hr = E_INVALIDARG; DWORD cbSrc; DWORD cbDst;
if (!pcbiSrc || !pbiDest) return E_POINTER;
cbSrc = pcbiSrc->cbSize; cbDst = pbiDest->cbSize; UrlMkAssert( cbSrc && "CopyBindInfo(): cbSize of the source is ZERO. You must set the cbSize."); UrlMkAssert( cbDst && "CopyBindInfo(): cbSize of the destination is ZERO. It needs to be set to the size of the BINDINFO before calling us."); if (!cbSrc || !cbDst) goto Abort; // nothing to do or can do.
// Copy those bytes in common, zero the rest if any
memcpy(pbiDest, pcbiSrc, min(cbSrc, cbDst)); pbiDest->cbSize = cbDst; // always keep this intact
if (cbDst > cbSrc) { ZeroMemory((BYTE *)pbiDest + cbSrc, cbDst - cbSrc); }
if (cbDst >= URLMONOFFSETOF(BINDINFO, dwReserved)) { ZeroMemory(&pbiDest->securityAttributes, sizeof(SECURITY_ATTRIBUTES)); }
if (pcbiSrc->pUnk && cbDst >= URLMONOFFSETOF(BINDINFO, dwReserved)) { pbiDest->pUnk->AddRef(); }
// NULL these anything fails we don't want to free the Sources resources.
pbiDest->szExtraInfo = NULL; pbiDest->szCustomVerb = NULL; // Original BINDINFO no need to check size
hr = CopyStgMedium( &pcbiSrc->stgmedData, &pbiDest->stgmedData ); if (hr) goto Cleanup;
// Original BINDINFO no need to check size
if (pcbiSrc->szExtraInfo) { LPWSTR lpwstr = OLESTRDuplicate(pcbiSrc->szExtraInfo); if (!lpwstr) { hr = E_OUTOFMEMORY; goto Cleanup; }
pbiDest->szExtraInfo= lpwstr; }
// Original BINDINFO no need to check size
if (pcbiSrc->szCustomVerb) { LPWSTR lpwstr = OLESTRDuplicate(pcbiSrc->szCustomVerb); if (!lpwstr) { hr = E_OUTOFMEMORY; goto Cleanup; }
pbiDest->szCustomVerb= lpwstr; }
Cleanup: if (hr) { // This will set pbiDest members to zero so other function will not
// try to use the new BINDINFO.
ReleaseBindInfo( pbiDest ); }
Abort: return(hr); }
|