Jeff Sanders Technical Blog

I am a Microsoft employee that has worked on all aspects of the Web Stack for a long time. I hope these blogs are useful to you! Use this information at your own risk.


<< Go Back

How To Modify Injected Attributed Code In An Atl Control That Is Crashing

- 17 Dec 2008

(ATL Control Visual Studio 2003 Crashes long value) I found a problem in the injected code from Visual Studio 2003 for an ATL control that had a property that was a long (VT_I4) value.  You could reliably crash the control if you put it into an html page and had jscript in a loop, setting the value over and over (100 X) in this case would crash it.  To make the crash reliable, I turned off BSTR caching and set full gflags.  You could see the issue was the freeing of a BSTR twice. 

Since Visual Studio 2003 is in extended support, getting a fix for this injected code was not possible so I had to fix it myself.  The easiest fix is to simply build the control using Visual Studio 2008!

I STRONGLY recommend that rather than doing this for the control, instead simply build with the latest Visual Studio to avoid the problem.

You can generate the injected code in the project as follows:

You will notice some files that have a .mrg string in the filename.  This is the injected code from the compiler.  You can edit these, remove the .mrg and rebuild to get your code changes.

Generating the merged code, I found that the ::Invoke call was calling ::VariantChangeType( ) on a variable that was passed in.  This is evil because this code does not own the Variant passed in!  What was happening is that the type was being changed to a long and calling ::SysFreeString on the BSTR in the passed in Variant.  To fix this I just changed the code to make a copy of the Variant and pass that in instead.  Actually I kind of cheated here and simply generated the injected code from building the project under Visual Studio 2005 and compared this to the 2003 code since I knew that code ran without causing the access violation.

Here are the steps I took:

 rgVars[0] = *rgpVars[0];
 v = &rgVars[0];

Now your code block in that section should look something like this:

if (wFlags & 4) {
                    if (pDispParams->cArgs != 1) {
                        return DISP_E_BADPARAMCOUNT;
                    }
                  
      rgVars[0] = *rgpVars[0];
      v = &rgVars[0];

                    if (v->vt != VT_I4 && FAILED(__VariantChangeType(v, &v0, VT_I4))) {

Again…

I STRONGLY recommend that rather than doing this for the control, instead simply build with the latest Visual Studio to avoid the problem.

 

<< Go Back