Skip to content

FatalExecutionEngineError on calling HttpQueryServiceConfiguration

The last few days I struggled a lot with WCF endpoints while configuring them running with least privileges. As already mentioned in my post WCF: Namespace Reservierung there are several tools simplifying this procedure. Nevertheless I wanted to write my own little tool with a GUI. The tool works fine so far (go and grep a copy from here) but there's something really annoying.

It's this error I get when calling HttpQueryServiceConfiguration:

FatalExecutionEngineError was detected
Message: The runtime has encountered a fatal error. The address of the error was at "0x79e8a634", on thread "0x1be8". The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or on-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

When executing httpcfg query urlacl I get these two reservations:

URL : http://*:2869/
ACL : D:(A;;GX;;;LS)

URL : http://+:80/Temporary_Listen_Addresses/
ACL : D:(A;;GX;;;WD)

On executing my code (see below) everything is ok. I get exactly the same results as above. However, after adding a third reservation with httpcfg set urlacl ... I get this annoying error.

At this point I should mention that I'm not very familiar with pinvoke and interop, but I want this to work. So, what am I missing or doing wrong? Any answers or suggestions will be appreciated.

Here's my code (shortened, just to show the error):

C#:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Runtime.InteropServices;
  5.  
  6. namespace HTTPApiDebug
  7. {
  8.     class Program
  9.     {
  10.         const uint NO_ERROR = 0;
  11.         const int HTTP_INITIALIZE_CONFIG = 2;
  12.         const uint ERROR_INSUFFICIENT_BUFFER = 122;
  13.         const uint ERROR_NO_MORE_ITEMS = 259;
  14.  
  15.         [DllImport("httpapi.dll")]
  16.         static extern uint HttpInitialize(
  17.              HTTPAPI_VERSION Version,
  18.              uint Flags,
  19.              IntPtr pReserved);
  20.  
  21.         [DllImport("httpapi.dll", ExactSpelling = true,
  22.             EntryPoint = "HttpQueryServiceConfiguration")]
  23.         static extern uint HttpQueryServiceConfiguration(
  24.              IntPtr ServiceIntPtr,
  25.              HTTP_SERVICE_CONFIG_ID ConfigId,
  26.              [In] ref HTTP_SERVICE_CONFIG_URLACL_QUERY pInputConfigInfo,
  27.              uint InputConfigInfoLength,
  28.              [In, Out] ref HTTP_SERVICE_CONFIG_URLACL_SET pOutputConfigInfo,
  29.              uint OutputConfigInfoLength,
  30.              [Optional] out uint pReturnLength,
  31.              IntPtr pOverlapped);
  32.  
  33.         [DllImport("httpapi.dll")]
  34.         static extern uint HttpTerminate(
  35.              uint Flags,
  36.              IntPtr pReserved);
  37.  
  38.         [StructLayout(LayoutKind.Sequential, Pack = 2)]
  39.         struct HTTPAPI_VERSION
  40.         {
  41.             public ushort HttpApiMajorVersion;
  42.             public ushort HttpApiMinorVersion;
  43.  
  44.             public HTTPAPI_VERSION(ushort majorVersion, ushort minorVersion)
  45.             {
  46.                 HttpApiMajorVersion = majorVersion;
  47.                 HttpApiMinorVersion = minorVersion;
  48.             }
  49.         }
  50.  
  51.         [StructLayout(LayoutKind.Sequential)]
  52.         struct HTTP_SERVICE_CONFIG_URLACL_QUERY
  53.         {
  54.             public HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc;
  55.             public HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc;
  56.             public uint dwToken;
  57.         }
  58.  
  59.         [StructLayout(LayoutKind.Sequential)]
  60.         struct HTTP_SERVICE_CONFIG_URLACL_SET
  61.         {
  62.             public HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc;
  63.             public HTTP_SERVICE_CONFIG_URLACL_PARAM ParamDesc;
  64.         }
  65.  
  66.         [StructLayout(LayoutKind.Sequential)]
  67.         struct HTTP_SERVICE_CONFIG_URLACL_KEY
  68.         {
  69.             [MarshalAs(UnmanagedType.LPWStr)]
  70.             public string UrlPrefix;
  71.         }
  72.  
  73.         [StructLayout(LayoutKind.Sequential)]
  74.         struct HTTP_SERVICE_CONFIG_URLACL_PARAM
  75.         {
  76.             [MarshalAs(UnmanagedType.LPWStr)]
  77.             public string Sddl;
  78.         }
  79.  
  80.         enum HTTP_SERVICE_CONFIG_ID
  81.         {
  82.             HttpServiceConfigIPListenList = 0,
  83.             HttpServiceConfigSSLCertInfo,
  84.             HttpServiceConfigUrlAclInfo,
  85.             HttpServiceConfigTimeout,
  86.             HttpServiceConfigMax
  87.         }
  88.  
  89.         enum HTTP_SERVICE_CONFIG_QUERY_TYPE
  90.         {
  91.             HttpServiceConfigQueryExact = 0,
  92.             HttpServiceConfigQueryNext,
  93.             HttpServiceConfigQueryMax
  94.         }
  95.  
  96.        
  97.  
  98.         static void Main(string[] args)
  99.         {
  100.             uint errorCode = NO_ERROR;
  101.  
  102.             HTTPAPI_VERSION httpApiVersion = new HTTPAPI_VERSION(1, 0);
  103.  
  104.             HTTP_SERVICE_CONFIG_URLACL_QUERY pInputConfigInfo =
  105.                 new HTTP_SERVICE_CONFIG_URLACL_QUERY();
  106.             pInputConfigInfo.QueryDesc =
  107.                 HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext;
  108.             pInputConfigInfo.dwToken = 0;
  109.  
  110.             do
  111.             {
  112.                 errorCode = NO_ERROR;
  113.  
  114.                 HTTP_SERVICE_CONFIG_URLACL_SET pOutputConfigInfo =
  115.                     new HTTP_SERVICE_CONFIG_URLACL_SET();
  116.                
  117.                 uint returnLength = 0;
  118.                 HttpInitialize(httpApiVersion,
  119.                     HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
  120.                 try
  121.                 {
  122.                     errorCode = HttpQueryServiceConfiguration(
  123.                                     IntPtr.Zero,
  124.                                     HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
  125.                                     ref pInputConfigInfo,
  126.                                     (uint)Marshal.SizeOf(pInputConfigInfo),
  127.                                     ref pOutputConfigInfo,
  128.                                     returnLength,
  129.                                     out returnLength,
  130.                                     IntPtr.Zero);
  131.                 }
  132.                 finally
  133.                 {
  134.                     HttpTerminate(
  135.                         HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
  136.                 }
  137.                 if (ERROR_INSUFFICIENT_BUFFER == errorCode)
  138.                 {
  139.                     // returnLength can be used to determine the minimum length
  140.                     // the buffer requires for the call to succeed
  141.                     HttpInitialize(httpApiVersion,
  142.                         HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
  143.                     try
  144.                     {
  145.                         errorCode = HttpQueryServiceConfiguration(
  146.                                     IntPtr.Zero,
  147.                                     HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
  148.                                     ref pInputConfigInfo,
  149.                                     (uint)Marshal.SizeOf(pInputConfigInfo),
  150.                                     ref pOutputConfigInfo,
  151.                                     returnLength,
  152.                                     out returnLength,
  153.                                     IntPtr.Zero);
  154.                     }
  155.                     finally
  156.                     {
  157.                         HttpTerminate(
  158.                             HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
  159.                     }
  160.                 }
  161.                 if (ERROR_NO_MORE_ITEMS != errorCode)
  162.                 {
  163.                     Console.WriteLine("URL: " + pOutputConfigInfo.KeyDesc.UrlPrefix +
  164.                         " - SDDL: " + pOutputConfigInfo.ParamDesc.Sddl);
  165.                     ++pInputConfigInfo.dwToken;
  166.                 }
  167.                 if (!(NO_ERROR == errorCode || ERROR_NO_MORE_ITEMS == errorCode))
  168.                 {
  169.                     throw new Exception();
  170.                 }
  171.             }
  172.             while (ERROR_NO_MORE_ITEMS != errorCode && NO_ERROR == errorCode);
  173.  
  174.             Console.ReadLine();
  175.         }
  176.  
  177.     }
  178. }

Update:While googling to find some hints on this issue I came across PaulWh's Tech Blog. He wrote a tool called HttpNamespaceManager which exactly does what I wanted my tool to do - and it looks much smarter than mine. Nevertheless, what's wrong with my code?

Categories: Programming.

Tags: , , , , ,

Comment Feed

No Responses (yet)



Some HTML is OK

or, reply to this post via trackback.