Tuesday, January 20, 2009

IRibbonControl->get_Id Gives Access violation

While developing Custom Ribbon interface for excel we were Getting Access violation while calling function get_Id() in one of my control callback. Following is code snip for that


STDMETHOD(ButtonClicked)( IDispatch * RibbonControl)
{

CComQIPtr pRibbonControl;
pRibbonControl = RibbonControl;
BSTR bstr;
pRibbonControl->get_Id(&bstr);

....

above line was giving access violation in debug build. But it works in release build ...

So do not get blocked due to this...
}

I spent almost one day for this ...
Note: This was happening only on vs6

3 comments:

R said...

Rajendra,

Im trying to disable some of the items on my Excel 2007 Ribbon like the Zoom / Formula Bar and Gridlines. In protected mode I do not want the user to be able to toggle with these properties. I have successfuly disabled the commandbars in Excel 2003, but Im not sure how to go about it with the ribbon style menu. Can you help ?

Hichem Sarrai said...

Hi Rajendra,
Me too I went in the same problem and found that you also did...
Actually the problem with giving a bstr to get_id() method is that bstr is a pointer to the first character in the bstr data string. However bstr consist of a length prefix, data string and a terminator (2 NULL characters!) see http://msdn.microsoft.com/en-us/library/ms221069.aspx.
I don't know what's going on in get_id method but it's probably checking the length prefix trying to find the length of the bstr. Checking this length is not working in release : the four bytes prefixing the data string are referring to an invalid integer! => access violation.
This is probably miraculously working for Release and not for Debug!
You should build a valid bstr before giving it to get_id()
1 )using CComBSTR
CComQIPtr ribbon_control(RibbonControl);
CComBSTR bstr_id;
hr = ribbon_control->get_Id(&bstr_id);
2) or just initializing bstr to NULL before passing it to get_id. Setting bstr to NULL probably mean for get_id method that there is no length prefix to look for.
3) or maybe SysAllocString if you want to fill the bstr before use:
BSTR MyBstr = SysAllocString(L"I am a happy BSTR");

Hope this help!

Hichem

Rajendersaini said...

@sorry guys i was not checking my blog for very long time. Let me know if you still need help. Although it is very late i guess :(