[DllImport("httpapi.dll", SetLastError = true)]
static extern uint HttpQueryServiceConfiguration(
IntPtr ServiceIntPtr,
HTTP_SERVICE_CONFIG_ID ConfigId,
IntPtr pInputConfigInfo,
int InputConfigInfoLength,
IntPtr pOutputConfigInfo,
int OutputConfigInfoLength,
[Optional()]
out int pReturnLength,
IntPtr pOverlapped);
Declare Function HttpQueryServiceConfiguration Lib "httpapi.dll" (TODO) As TODO
HTTP_SERVICE_CONFIG_URLACL_QUERY
HTTP_SERVICE_CONFIG_IP_LISTEN_QUERY
HTTP_SERVICE_CONFIG_URLACL_SET
Depending on the value of ConfigId, both pInputConfigInfo and pOutputConfigInfo should point to a different type of structure. If it wasn't for this, I could redifine the PInvoke signature to explicitly specify the underlying structure type.
ConfigId Value | InputConfigInfor Structure Type |
HttpServiceConfigIPListenList | No input data; set to NULL. |
HttpServiceConfigSSLCertInfo | HTTP_SERVICE_CONFIG_SSL_QUERY structure. |
HttpServiceConfigUrlAclInfo | HTTP_SERVICE_CONFIG_URLACL_QUERY structure. |
ConfigId Value | OutputConfigInfo Structure Type |
HttpServiceConfigIPListenList | HTTP_SERVICE_CONFIG_IP_LISTEN_QUERY structure. |
HttpServiceConfigSSLCertInfo | HTTP_SERVICE_CONFIG_SSL_SET structure. |
HttpServiceConfigUrlAclInfo | HTTP_SERVICE_CONFIG_URLACL_SET structure. |
If your use of this API is focused around a single value of ConfigId, you may want to change the IntPtr (pConfigInformation) to point directly to a managed version of the correct underlying structure and let the default marshaller take care of the interop layer marshaling for you (and your memory management).
HTTP_SERVICE_CONFIG_URLACL_SET QueryServiceConfig(string networkURL)
{
HTTPAPI_VERSION httpApiVersion = new HTTPAPI_VERSION(1, 0);
uint retVal = (uint) ErrorCodes.NOERROR; // NOERROR = 0
retVal = HttpApi.HttpInitialize(httpApiVersion, HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
if ((uint) ErrorCodes.NOERROR == retVal)
{
HTTP_SERVICE_CONFIG_URLACL_KEY urlAclKey = new HTTP_SERVICE_CONFIG_URLACL_KEY(networkURL);
HTTP_SERVICE_CONFIG_URLACL_QUERY inputConfigInfoQuery = new HTTP_SERVICE_CONFIG_URLACL_QUERY();
inputConfigInfoQuery.QueryDesc = HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryExact;
inputConfigInfoQuery.KeyDesc = keyDesc;
inputConfigInfoQuery.dwToken = 0;
int size = Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_URLACL_QUERY));
IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(HTTP_SERVICE_CONFIG_URLACL_QUERY)));
Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, true);
HTTP_SERVICE_CONFIG_URLACL_SET outputConfigInfo = new HTTP_SERVICE_CONFIG_URLACL_SET();
IntPtr pOutputConfigInfo = Marshal.AllocCoTaskMem(0);
int returnLength = 0;
size = Marshal.SizeOf(inputConfigInfoQuery);
retVal = HttpApi.HttpQueryServiceConfiguration(IntPtr.Zero,
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
pInputConfigInfo,
Marshal.SizeOf(inputConfigInfoQuery),
pOutputConfigInfo,
returnLength,
out returnLength,
IntPtr.Zero);
if (ErrorCodes.ERROR_INSUFFICIENT_BUFFER == retVal) // ERROR_INSUFFICIENT_BUFFER = 122
{
Marshal.FreeCoTaskMem(pOutputConfigInfo);
pOutputConfigInfo = Marshal.AllocCoTaskMem(Convert.ToInt32(returnLength));
retVal = HttpApi.HttpQueryServiceConfiguration(IntPtr.Zero,
HTTP_SERVICE_CONFIG_ID.HttpServiceConfigUrlAclInfo,
pInputConfigInfo,
Marshal.SizeOf(inputConfigInfoQuery),
pOutputConfigInfo,
returnLength,
out returnLength,
IntPtr.Zero);
}
if (ErrorCodes.NOERROR == retVal)
{
outputConfigInfo = (HTTP_SERVICE_CONFIG_URLACL_SET)Marshal.PtrToStructure(pOutputConfigInfo, typeof(HTTP_SERVICE_CONFIG_URLACL_SET));
}
HttpApi.HttpTerminate(HttpApi.HTTP_INITIALIZE_CONFIG, IntPtr.Zero);
}
if ((uint) ErrorCodes.NOERROR != retVal)
{
throw new Win32Exception(Convert.ToInt32(retVal));
}
return outputConfigInfo;
}
Here is the code sample to work with SSL certificate configuration records http://dotnetcodebox.blogspot.com/2012/01/how-to-work-with-ssl-certificate.html .
Do you know one? Please contribute it!