G
Guest
this is the function that the problem lies in. it is in MFC file ctlpset.cpp
BOOL COleControl::GetPropsetData(LPFORMATETC lpFormatEtc,
LPSTGMEDIUM lpStgMedium, REFCLSID fmtid)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
BOOL bGetDataHere = (lpStgMedium->tymed != TYMED_NULL);
// Allow IStream or IStorage as the storage medium.
if (!(lpFormatEtc->tymed & (TYMED_ISTREAM|TYMED_ISTORAGE)))
{
TRACE(traceAppMsg, 0, "Propset only supported for stream or storage.\n");
return FALSE;
}
LPSTORAGE lpStorage = NULL; // here they initialize the lpStorage,
lpStream to NULL
LPSTREAM lpStream = NULL;
//then they test whether the output file is a stream or storage.
if (lpFormatEtc->tymed & TYMED_ISTORAGE)
{
//if it is storage,then the lpStorage is assigned a new value
//but lpStream keep the NULL value.
// Caller wants propset data in a storage object.
if (bGetDataHere)
{
// Use the caller-supplied storage object.
lpStorage = lpStgMedium->pstg;
}
else
{
// Create a storage object on a memory ILockBytes implementation.
LPLOCKBYTES lpLockBytes = NULL;
if (FAILED(CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes)))
{
TRACE(traceAppMsg, 0, "CreateILockBytesOnHGlobal failed.\n");
return FALSE;
}
ASSERT_POINTER(lpLockBytes, ILockBytes);
if (FAILED(StgCreateDocfileOnILockBytes(lpLockBytes,
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0,
&lpStorage)))
{
TRACE(traceAppMsg, 0, "StgCreateDocfileOnILockBytes failed.\n");
lpLockBytes->Release();
return FALSE;
}
// Docfile now has reference to ILockBytes, so release ours.
lpLockBytes->Release();
}
ASSERT_POINTER(lpStorage, IStorage);
// Create a stream within the storage.
if (FAILED(lpStorage->CreateStream(OLESTR("Contents"),
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, 0,
&lpStream)))
{
TRACE(traceAppMsg, 0, "IStorage::CreateStream failed.\n");
if (!bGetDataHere)
lpStorage->Release();
return FALSE;
}
}
else
{
//if it is stream ,then the lpStream is assigned a new value
//but lpStorage keep the NULL value.
// Caller wants propset data in a stream object.
if (bGetDataHere)
{
// Use the caller-supplied stream object
lpStream = lpStgMedium->pstm;
}
else
{
lpStream = _AfxCreateMemoryStream();
if (lpStream == NULL)
return FALSE;
}
}
//but in later program, we can find that, if there is a fail in the
process, they always release lpStream,lpStorage togetgher. so we can tell,
if our ocx control adhere to MS's rule, it runs fluently, if not, it may have
problem.
ASSERT_POINTER(lpStream, IStream);
// Create the property set.
CLSID clsid;
GetClassID(&clsid);
CPropertySet pset(clsid);
pset.SetOSVersion(MAKELONG(LOWORD(GetVersion()), OSTYPE));
CPropertySection* ppsec = pset.AddSection(fmtid);
if (ppsec == NULL)
{
TRACE(traceAppMsg, 0, "CPropertySet::AddSection failed.\n");
lpStream->Release();
lpStorage->Release();
return FALSE;
}
// Set the name, based on the ambient display name (from the container).
ppsec->SetSectionName(AmbientDisplayName());
CPropsetPropExchange propx(*ppsec, lpStorage, FALSE);
BOOL bPropExchange = FALSE;
TRY
{
DoPropExchange(&propx);
bPropExchange = TRUE;
}
END_TRY
if (!bPropExchange)
{
TRACE(traceAppMsg, 0, "DoPropExchange failed.\n");
lpStream->Release();
lpStorage->Release();
return FALSE;
}
// Store the property set in the stream.
if (!pset.WriteToStream(lpStream))
{
TRACE(traceAppMsg, 0, "CPropertySet::WriteToStream failed.\n");
lpStream->Release();
lpStorage->Release();
return FALSE;
}
// Return the property set in the requested medium.
if (lpFormatEtc->tymed & TYMED_ISTORAGE)
{
// Return as a storage object.
ASSERT_POINTER(lpStorage, IStorage);
lpStream->Release();
lpStgMedium->pstg = lpStorage;
lpStgMedium->tymed = TYMED_ISTORAGE;
lpStgMedium->pUnkForRelease = NULL;
}
else
{
// Return as a stream.
ASSERT_POINTER(lpStream, IStream);
lpStgMedium->pstm = lpStream;
lpStgMedium->tymed = TYMED_ISTREAM;
lpStgMedium->pUnkForRelease = NULL;
}
return TRUE;
}
BOOL COleControl::GetPropsetData(LPFORMATETC lpFormatEtc,
LPSTGMEDIUM lpStgMedium, REFCLSID fmtid)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
BOOL bGetDataHere = (lpStgMedium->tymed != TYMED_NULL);
// Allow IStream or IStorage as the storage medium.
if (!(lpFormatEtc->tymed & (TYMED_ISTREAM|TYMED_ISTORAGE)))
{
TRACE(traceAppMsg, 0, "Propset only supported for stream or storage.\n");
return FALSE;
}
LPSTORAGE lpStorage = NULL; // here they initialize the lpStorage,
lpStream to NULL
LPSTREAM lpStream = NULL;
//then they test whether the output file is a stream or storage.
if (lpFormatEtc->tymed & TYMED_ISTORAGE)
{
//if it is storage,then the lpStorage is assigned a new value
//but lpStream keep the NULL value.
// Caller wants propset data in a storage object.
if (bGetDataHere)
{
// Use the caller-supplied storage object.
lpStorage = lpStgMedium->pstg;
}
else
{
// Create a storage object on a memory ILockBytes implementation.
LPLOCKBYTES lpLockBytes = NULL;
if (FAILED(CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes)))
{
TRACE(traceAppMsg, 0, "CreateILockBytesOnHGlobal failed.\n");
return FALSE;
}
ASSERT_POINTER(lpLockBytes, ILockBytes);
if (FAILED(StgCreateDocfileOnILockBytes(lpLockBytes,
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0,
&lpStorage)))
{
TRACE(traceAppMsg, 0, "StgCreateDocfileOnILockBytes failed.\n");
lpLockBytes->Release();
return FALSE;
}
// Docfile now has reference to ILockBytes, so release ours.
lpLockBytes->Release();
}
ASSERT_POINTER(lpStorage, IStorage);
// Create a stream within the storage.
if (FAILED(lpStorage->CreateStream(OLESTR("Contents"),
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, 0,
&lpStream)))
{
TRACE(traceAppMsg, 0, "IStorage::CreateStream failed.\n");
if (!bGetDataHere)
lpStorage->Release();
return FALSE;
}
}
else
{
//if it is stream ,then the lpStream is assigned a new value
//but lpStorage keep the NULL value.
// Caller wants propset data in a stream object.
if (bGetDataHere)
{
// Use the caller-supplied stream object
lpStream = lpStgMedium->pstm;
}
else
{
lpStream = _AfxCreateMemoryStream();
if (lpStream == NULL)
return FALSE;
}
}
//but in later program, we can find that, if there is a fail in the
process, they always release lpStream,lpStorage togetgher. so we can tell,
if our ocx control adhere to MS's rule, it runs fluently, if not, it may have
problem.
ASSERT_POINTER(lpStream, IStream);
// Create the property set.
CLSID clsid;
GetClassID(&clsid);
CPropertySet pset(clsid);
pset.SetOSVersion(MAKELONG(LOWORD(GetVersion()), OSTYPE));
CPropertySection* ppsec = pset.AddSection(fmtid);
if (ppsec == NULL)
{
TRACE(traceAppMsg, 0, "CPropertySet::AddSection failed.\n");
lpStream->Release();
lpStorage->Release();
return FALSE;
}
// Set the name, based on the ambient display name (from the container).
ppsec->SetSectionName(AmbientDisplayName());
CPropsetPropExchange propx(*ppsec, lpStorage, FALSE);
BOOL bPropExchange = FALSE;
TRY
{
DoPropExchange(&propx);
bPropExchange = TRUE;
}
END_TRY
if (!bPropExchange)
{
TRACE(traceAppMsg, 0, "DoPropExchange failed.\n");
lpStream->Release();
lpStorage->Release();
return FALSE;
}
// Store the property set in the stream.
if (!pset.WriteToStream(lpStream))
{
TRACE(traceAppMsg, 0, "CPropertySet::WriteToStream failed.\n");
lpStream->Release();
lpStorage->Release();
return FALSE;
}
// Return the property set in the requested medium.
if (lpFormatEtc->tymed & TYMED_ISTORAGE)
{
// Return as a storage object.
ASSERT_POINTER(lpStorage, IStorage);
lpStream->Release();
lpStgMedium->pstg = lpStorage;
lpStgMedium->tymed = TYMED_ISTORAGE;
lpStgMedium->pUnkForRelease = NULL;
}
else
{
// Return as a stream.
ASSERT_POINTER(lpStream, IStream);
lpStgMedium->pstm = lpStream;
lpStgMedium->tymed = TYMED_ISTREAM;
lpStgMedium->pUnkForRelease = NULL;
}
return TRUE;
}