Sign in to follow this  
RonHiler

Error from CreateStaticFromData call

Recommended Posts

RonHiler    214
Hey guys, This function is throwing an error on me. The OleCreateStaticFromData() is returning -2147221008. I Googled that value but I'm not coming up with any english translation for that number. And GetLastError() isn't getting me anything useful. Can anyone point me in the right direction for either translating that number into something human readable or tell me what I might be doing wrong in this bit of code?
//---------------------------------------------------------------------------
IOleObject* RichEditBitmapClass::GetOleObject(IOleClientSite *OleClientSite, IStorage *Storage)
	{
	SCODE sc;
	IOleObject *OleObject;

	if (stgmed.hBitmap == NULL)
		return NULL;

	sc = OleCreateStaticFromData(this, IID_IOleObject, OLERENDER_FORMAT, &fromat, OleClientSite, Storage, (void**)&OleObject);
	if (sc != S_OK)
		return NULL;
	return OleObject;
	}

Share this post


Link to post
Share on other sites
mattd    1078
-2147221008 == 0x800401F0, i.e., interpret the HRESULT (why are you using a SCODE?) as hex.

Click:
Quote:

//
// MessageId: CO_E_NOTINITIALIZED
//
// MessageText:
//
// CoInitialize has not been called.
//
#define CO_E_NOTINITIALIZED _HRESULT_TYPEDEF_(0x800401F0L)


You can also find this out in MSVC's debugger by using the ",hr" formatter in the watch window:

0x800401F0,hr     0x800401f0     CoInitialize has not been called.     unsigned int


Need to call this first.

[Edited by - mattd on February 18, 2010 11:02:20 AM]

Share this post


Link to post
Share on other sites
RonHiler    214
Quote:
Original post by mattd
You can also find this out in MSVC's debugger by using the ",hr" formatter in the watch window:

0x800401F0,hr     0x800401f0     CoInitialize has not been called.     unsigned int


Cool! Learn something new every day :)

Thanks Matt, that's exactly what I needed.

Share this post


Link to post
Share on other sites
RonHiler    214
Well, I'm going to need more help. My function (which is designed to display a bitmap in a rich edit box) is not working, and I have absolutely no clue as to why. I apologize for the size of the code, I'll remove the error checking to reduce it a bit.

The problem I am having is that no image is appearing in my rich edit box. If I let the routine fire once, I get no error message (but also no image), if I let it fire a second time I get this info:

HEAP[DDOCharGen.exe]: Invalid allocation size - B057CD00 (exceeded 7ffdefff)
HEAP[DDOCharGen.exe]: Invalid allocation size - B057CD00 (exceeded 7ffdefff)
Error creating ole object

I know it's asking a lot, but I'm hoping somebody will see something I am missing.

Here is the code for this function:


#pragma once

#include "stdafx.h"

class RichEditBitmapClass : IDataObject
{
public:
RichEditBitmapClass();
virtual ~RichEditBitmapClass();

static void InsertBitmap(HWND EditBox, HBITMAP Bitmap);

//the IUnknown interface
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();

//the IDataObject Interface
HRESULT STDMETHODCALLTYPE GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
HRESULT STDMETHODCALLTYPE GetDataHere(FORMATETC*, STGMEDIUM*);
HRESULT STDMETHODCALLTYPE QueryGetData(FORMATETC*);
HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc(FORMATETC*, FORMATETC*);
HRESULT STDMETHODCALLTYPE SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL rlse);
HRESULT STDMETHODCALLTYPE EnumFormatEtc(DWORD, IEnumFORMATETC**);
HRESULT STDMETHODCALLTYPE DAdvise(FORMATETC*, DWORD, IAdviseSink*, DWORD*);
HRESULT STDMETHODCALLTYPE DUnadvise(DWORD);
HRESULT STDMETHODCALLTYPE EnumDAdvise(IEnumSTATDATA**);

private:
ULONG RefCnt;
STGMEDIUM stgmed;
FORMATETC fromat;
BOOL release;

void SetBitmap(HBITMAP Bitmap);
IOleObject* GetOleObject(IOleClientSite *OleClientSite, IStorage *Storage);
};





#include "RichEditBitmapClass.h"
#include "InterfaceManagerClass.h"

//---------------------------------------------------------------------------
RichEditBitmapClass::RichEditBitmapClass()
{
RefCnt = 0;
release = false;
CoInitialize(NULL);
}

//---------------------------------------------------------------------------
RichEditBitmapClass::~RichEditBitmapClass()
{
if (release == TRUE)
ReleaseStgMedium(&stgmed);
CoUninitialize();
}

//---------------------------------------------------------------------------
void RichEditBitmapClass::InsertBitmap(HWND EditBox, HBITMAP Bitmap)
{
IRichEditOle *RichEditOle;
RichEditBitmapClass *ImageDataObject;
LPDATAOBJECT DataObject;
IOleClientSite *OleClientSite;
IStorage *Storage;
LPLOCKBYTES LockBytes;
HRESULT hr;
IOleObject *OleObject;
REOBJECT reobject;
CLSID clsid;

//grab the IRichEditOle interface
SendMessage(EditBox, EM_GETOLEINTERFACE, 0, (LPARAM)&RichEditOle);

//Get the image data object
ImageDataObject = new RichEditBitmapClass;
ImageDataObject->QueryInterface(IID_IDataObject, (void**)&DataObject);
ImageDataObject->SetBitmap(Bitmap);

//Get the RichEdit client site
hr = RichEditOle->GetClientSite(&OleClientSite);
if (hr != S_OK)
...

//Initialize a Storage Object
LockBytes = NULL;
hr = CreateILockBytesOnHGlobal(NULL, TRUE, &LockBytes);
if (hr != S_OK || LockBytes == NULL)
...
hr = StgCreateDocfileOnILockBytes(LockBytes, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &Storage);
if (hr != S_OK || Storage == NULL)
...

// The final ole object which will be inserted in the richedit control
OleObject = ImageDataObject->GetOleObject(OleClientSite, Storage);
if (OleObject == NULL)
...

OleSetContainedObject(OleObject, TRUE);

//Now Add the object to the RichEdit
ZeroMemory(&reobject, sizeof(REOBJECT));
reobject.cbStruct = sizeof(REOBJECT);

hr = OleObject->GetUserClassID(&clsid);
if (hr != S_OK)
...

reobject.clsid = clsid;
reobject.cp = REO_CP_SELECTION;
reobject.dvaspect = DVASPECT_CONTENT;
reobject.poleobj = OleObject;
reobject.polesite = OleClientSite;
reobject.pstg = Storage;

// Insert the bitmap at the current location in the richedit control
RichEditOle->InsertObject(&reobject);

//cleanup
OleObject->Release();
Storage->Release();
OleClientSite->Release();
DataObject->Release();
RichEditOle->Release();
}

//---------------------------------------------------------------------------
void RichEditBitmapClass::SetBitmap(HBITMAP Bitmap)
{
STGMEDIUM stgm;
FORMATETC fm;

stgm.tymed = TYMED_GDI; // Storage medium = HBITMAP handle
stgm.hBitmap = Bitmap;
stgm.pUnkForRelease = NULL; // Use ReleaseStgMedium

fm.cfFormat = CF_BITMAP; // Clipboard format = CF_BITMAP
fm.ptd = NULL; // Target Device = Screen
fm.dwAspect = DVASPECT_CONTENT; // Level of detail = Full content
fm.lindex = -1; // Index = Not applicaple
fm.tymed = TYMED_GDI; // Storage medium = HBITMAP handle

SetData(&fm, &stgm, TRUE);
}

//---------------------------------------------------------------------------
IOleObject* RichEditBitmapClass::GetOleObject(IOleClientSite *OleClientSite, IStorage *Storage)
{
HRESULT hr;
IOleObject *OleObject;

if (stgmed.hBitmap == NULL)
return NULL;

hr = OleCreateStaticFromData(this, IID_IOleObject, OLERENDER_FORMAT, &fromat, OleClientSite, Storage, (void**)&OleObject);
if (hr != S_OK)
return NULL;

return OleObject;
}


//---------------------------------------------------------------------------
//----------------------IUnkown pure virtual functions-----------------------
//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::QueryInterface(REFIID iid, void **ppvObject)
{
if (iid == IID_IUnknown || iid == IID_IDataObject)
{
*ppvObject = this;
AddRef();
return S_OK;
}
else
return E_NOINTERFACE;
}

//---------------------------------------------------------------------------
ULONG RichEditBitmapClass::AddRef()
{
RefCnt++;
return RefCnt;
}

//---------------------------------------------------------------------------
ULONG RichEditBitmapClass::Release()
{
RefCnt--;
if (RefCnt == 0)
delete this;

return RefCnt;
}

//---------------------------------------------------------------------------
//------------------IDataObject pure virtual functions-----------------------
//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{
HANDLE Dest;

Dest = OleDuplicateData(stgmed.hBitmap, CF_BITMAP, NULL);
if (Dest == NULL)
return E_HANDLE;

pmedium->tymed = TYMED_GDI;
pmedium->hBitmap = (HBITMAP)Dest;
pmedium->pUnkForRelease = NULL;

return S_OK;
}

//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::GetDataHere(FORMATETC*, STGMEDIUM*)
{
return E_NOTIMPL;
}

//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::QueryGetData(FORMATETC*)
{
return E_NOTIMPL;
}

//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::GetCanonicalFormatEtc(FORMATETC*, FORMATETC*)
{
return E_NOTIMPL;
}

//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL rlse)
{
fromat = *pformatetc;
stgmed = *pmedium;
release = rlse;

return S_OK;
}

//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::EnumFormatEtc(DWORD, IEnumFORMATETC**)
{
return E_NOTIMPL;
}

//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::DAdvise(FORMATETC*, DWORD, IAdviseSink*, DWORD *)
{
return E_NOTIMPL;
}

//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::DUnadvise(DWORD)
{
return E_NOTIMPL;
}

//---------------------------------------------------------------------------
HRESULT RichEditBitmapClass::EnumDAdvise(IEnumSTATDATA**)
{
return E_NOTIMPL;
}




Note that this code is loosely based on the code found on this page:
http://www.codeguru.com/cpp/controls/richedit/article.php/c5383

Share this post


Link to post
Share on other sites
mattd    1078
All I can suggest is to use your debugger and find exactly what call is producing the message, and work backwards from there, inspecting handles and values (and most importantly, error codes) as you go.

That, or move to the .NET platform ASAP :P

Share this post


Link to post
Share on other sites
RonHiler    214
Quote:
Original post by mattd
All I can suggest is to use your debugger and find exactly what call is producing the message, and work backwards from there, inspecting handles and values (and most importantly, error codes) as you go.

Oh, I know the call that is failing. It's this one

OleObject = ImageDataObject->GetOleObject(OleClientSite, Storage);

I think there is something amiss with Storage in that call, but I can't figure out what.

Quote:
That, or move to the .NET platform ASAP :P

It'll be a cold day in hell... :)

Share this post


Link to post
Share on other sites
mattd    1078
One thing that sticks out.. you really only want to CoInitialize / CoUninitialize once per thread, ever.

Try moving them out of the (de)constructor and to a more global scope.

Share this post


Link to post
Share on other sites
RonHiler    214
Good point. Thanks Matt. That at least got rid of the heap error. Still no image though, and the fail is in the same place. I'll keep working on it. If/when I figure it out, I'll post the solution.

Share this post


Link to post
Share on other sites
RonHiler    214
I got it!

Given the code I gave you guys, you couldn't have helped me. The problem was a level higher. I always feel like such an idiot when I figure these things out :) It turns out the graphic was being drawn the whole time, but immediately afterword, was getting cleared out again to draw the subsequent text. Duh. Anyway, the code works as shown (once you move the Co(un)initialize calls as per Matt's suggestion), if anyone wants to use it as a base for their own code.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this