Debugging Reporting Services with WinDbg

I recently needed to use classes and methods from MSXML6.dll in Reporting Services reports (to make web service calls).

Tried to instantiate XMLHTTP and DOMDocument from MSXML6.dll with late binding like this:

Request = CreateObject("MSXML2.XMLHTTP.6.0")
Doc = CreateObject("MSXML2.DOMDocument.6.0")

However it failed with a SecurityException, but the exact cause was unknown.

 

I decided to identify the cause by attaching WinDbg (x86) to RsReportHost.exe

 

On each report refresh I noticed a number of exceptions like:

(2a54.34d4): CLR exception - code e0434352 (first chance)
(2a54.34d4): CLR exception - code e0434352 (first chance)
(2a54.34d4): C++ EH exception - code e06d7363 (first chance)
(2a54.34d4): C++ EH exception - code e06d7363 (first chance)

 

I configured WinDbg to break on first chance exceptions under: Debug -> Event Filters…

Debug_Event_Filters

 

And loaded the SOS extension with:

.loadby sos clr

 

Typical (top part) of the call stack was:

0:007> !clrstack
OS Thread Id: 0x55f4 (7)
Child SP       IP Call Site
00bbb28c 7652dae8 [HelperMethodFrame: 00bbb28c]
00bbb33c 72f25d5a System.Security.CodeAccessSecurityEngine.ThrowSecurityException(...)
00bbb36c 72f25cad System.Security.CodeAccessSecurityEngine.ThrowSecurityException(...)
00bbb394 72f2136c System.Security.CodeAccessSecurityEngine.CheckSetHelper(...)
00bbb3e4 73581acf System.Security.CodeAccessSecurityEngine.CheckSetHelper(...)
00bbb50c 73e41376 [GCFrame: 00bbb50c]
00bbbd08 73e41376 [GCFrame: 00bbbd08]
00bbbdc0 73e41376 [GCFrame: 00bbbdc0]
00bbbf58 73e41376 [DebuggerSecurityCodeMarkFrame: 00bbbf58]
00bbbee4 73e41376 [HelperMethodFrame: 00bbbee4]
00bbbf7c 09a16859 Microsoft.VisualBasic.Interaction.CreateObject(System.String, System.String)
00bbbfa4 09a180ba ReportExprHostImpl+CustomCodeProxy.CallServiceTest2()
00bbbfcc 09a1807b ReportExprHostImpl+Description_TextBoxExprHost+Paragraph00_ParagraphExprHost+TextRun00_TextRunExprHost.get_ValueExpr()

(parameters trimmed for readability)

 

I checked the mscorlib.dll code for System.Security.CodeAccessSecurityEngine.CheckSetHelper(…) in ILSpy.

Noticed something interesting: The local variable permThatFailed could show which permission was missing.

This was also used when calling System.Security.SecurityException.MakeSecurityException, so that was an ideal place to set a breakpoint.

 

Set a breakpoint with !bpmd:

0:015> !bpmd mscorlib.dll System.Security.SecurityException.MakeSecurityException
Found 1 methods in module 72bf1000...
MethodDesc = 72c88e84
Setting breakpoint: bp 72F33813 [System.Security.SecurityException.MakeSecurityException(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.RuntimeMethodHandleInternal, System.Security.Permissions.SecurityAction, System.Object, System.Security.IPermission)]
Adding pending breakpoints...

 

Continued execution, refreshed the report and then checked the call stack with parameters:

0:014> !clrstack -p
OS Thread Id: 0x54c0 (14)
Child SP       IP Call Site
0103bd88 72f33813 System.Security.SecurityException.MakeSecurityException(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.RuntimeMethodHandleInternal, System.Security.Permissions.SecurityAction, System.Object, System.Security.IPermission)
PARAMETERS:
asmName (<CLR reg>) = 0x036c4bd0
asmEvidence (<CLR reg>) = 0x036c5b64
granted (0x0103bda0) = 0x00000000
refused (0x0103bd9c) = 0x036c4bd0
rmh (0x0103bd98) = 0x036c5b64
action (0x0103bd94) = 0x00000000
demand (0x0103bd90) = 0x00000000
permThatFailed (0x0103bd8c) = 0x00000002

 

The permThatFailed parameter consistently had the value 2.

I looked up the values for the SecurityPermissionFlag enumeration in ILSpy:

And found this:

/// <summary>Ability to call unmanaged code.</summary>
UnmanagedCode = 2,

 

Conclusion

The SecurityException occured because permission to execute unmanaged code was missing.