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):
-
using System;
-
using System.Collections.Generic;
-
using System.Text;
-
using System.Runtime.InteropServices;
-
-
namespace HTTPApiDebug
-
{
-
class Program
-
{
-
const uint NO_ERROR = 0;
-
const int HTTP_INITIALIZE_CONFIG = 2;
-
const uint ERROR_INSUFFICIENT_BUFFER = 122;
-
const uint ERROR_NO_MORE_ITEMS = 259;
-
-
[DllImport("httpapi.dll")]
-
static extern uint HttpInitialize(
-
HTTPAPI_VERSION Version,
-
uint Flags,
-
IntPtr pReserved);
-
-
[DllImport("httpapi.dll", ExactSpelling = true,
-
EntryPoint = "HttpQueryServiceConfiguration")]
-
static extern uint HttpQueryServiceConfiguration(
-
IntPtr ServiceIntPtr,
-
HTTP_SERVICE_CONFIG_ID ConfigId,
-
[In] ref HTTP_SERVICE_CONFIG_URLACL_QUERY pInputConfigInfo,
-
uint InputConfigInfoLength,
-
[In, Out] ref HTTP_SERVICE_CONFIG_URLACL_SET pOutputConfigInfo,
-
uint OutputConfigInfoLength,
-
[Optional] out uint pReturnLength,
-
IntPtr pOverlapped);
-
-
[DllImport("httpapi.dll")]
-
static extern uint HttpTerminate(
-
uint Flags,
-
IntPtr pReserved);
-
-
[StructLayout(LayoutKind.Sequential, Pack = 2)]
-
struct HTTPAPI_VERSION
-
{
-
public ushort HttpApiMajorVersion;
-
public ushort HttpApiMinorVersion;
-
-
public HTTPAPI_VERSION(ushort majorVersion, ushort minorVersion)
-
{
-
HttpApiMajorVersion = majorVersion;
-
HttpApiMinorVersion = minorVersion;
-
}
-
}
-
-
[StructLayout(LayoutKind.Sequential)]
-
struct HTTP_SERVICE_CONFIG_URLACL_QUERY
-
{
-
public HTTP_SERVICE_CONFIG_QUERY_TYPE QueryDesc;
-
public HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc;
-
public uint dwToken;
-
}
-
-
[StructLayout(LayoutKind.Sequential)]
-
struct HTTP_SERVICE_CONFIG_URLACL_SET
-
{
-
public HTTP_SERVICE_CONFIG_URLACL_KEY KeyDesc;
-
public HTTP_SERVICE_CONFIG_URLACL_PARAM ParamDesc;
-
}
-
-
[StructLayout(LayoutKind.Sequential)]
-
struct HTTP_SERVICE_CONFIG_URLACL_KEY
-
{
-
[MarshalAs(UnmanagedType.LPWStr)]
-
public string UrlPrefix;
-
}
-
-
[StructLayout(LayoutKind.Sequential)]
-
struct HTTP_SERVICE_CONFIG_URLACL_PARAM
-
{
-
[MarshalAs(UnmanagedType.LPWStr)]
-
public string Sddl;
-
}
-
-
enum HTTP_SERVICE_CONFIG_ID
-
{
-
HttpServiceConfigIPListenList = 0,
-
HttpServiceConfigSSLCertInfo,
-
HttpServiceConfigUrlAclInfo,
-
HttpServiceConfigTimeout,
-
HttpServiceConfigMax
-
}
-
-
enum HTTP_SERVICE_CONFIG_QUERY_TYPE
-
{
-
HttpServiceConfigQueryExact = 0,
-
HttpServiceConfigQueryNext,
-
HttpServiceConfigQueryMax
-
}
-
-
-
-
static void Main(string[] args)
-
{
-
uint errorCode = NO_ERROR;
-
-
-
HTTP_SERVICE_CONFIG_URLACL_QUERY pInputConfigInfo =
-
pInputConfigInfo.QueryDesc =
-
HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext;
-
pInputConfigInfo.dwToken = 0;
-
-
do
-
{
-
errorCode = NO_ERROR;
-
-
HTTP_SERVICE_CONFIG_URLACL_SET pOutputConfigInfo =
-
-
uint returnLength = 0;
-
HttpInitialize(httpApiVersion,
-
HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
-
try
-
{
-
errorCode = HttpQueryServiceConfiguration(
-
IntPtr.Zero,
-
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
-
ref pInputConfigInfo,
-
ref pOutputConfigInfo,
-
returnLength,
-
out returnLength,
-
IntPtr.Zero);
-
}
-
finally
-
{
-
HttpTerminate(
-
HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
-
}
-
if (ERROR_INSUFFICIENT_BUFFER == errorCode)
-
{
-
// returnLength can be used to determine the minimum length
-
// the buffer requires for the call to succeed
-
HttpInitialize(httpApiVersion,
-
HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
-
try
-
{
-
errorCode = HttpQueryServiceConfiguration(
-
IntPtr.Zero,
-
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
-
ref pInputConfigInfo,
-
ref pOutputConfigInfo,
-
returnLength,
-
out returnLength,
-
IntPtr.Zero);
-
}
-
finally
-
{
-
HttpTerminate(
-
HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
-
}
-
}
-
if (ERROR_NO_MORE_ITEMS != errorCode)
-
{
-
Console.WriteLine("URL: " + pOutputConfigInfo.KeyDesc.UrlPrefix +
-
" - SDDL: " + pOutputConfigInfo.ParamDesc.Sddl);
-
++pInputConfigInfo.dwToken;
-
}
-
if (!(NO_ERROR == errorCode || ERROR_NO_MORE_ITEMS == errorCode))
-
{
-
}
-
}
-
while (ERROR_NO_MORE_ITEMS != errorCode && NO_ERROR == errorCode);
-
-
Console.ReadLine();
-
}
-
-
}
-
}
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?