304 lines
13 KiB
C#
304 lines
13 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
|
using Microsoft.AspNetCore.Server.IIS.Core;
|
|
|
|
namespace Microsoft.AspNetCore.Server.IIS
|
|
{
|
|
internal static class NativeMethods
|
|
{
|
|
internal const int HR_OK = 0;
|
|
internal const int ERROR_NOT_FOUND = unchecked((int)0x80070490);
|
|
internal const int ERROR_OPERATION_ABORTED = unchecked((int)0x800703E3);
|
|
internal const int COR_E_IO = unchecked((int)0x80131620);
|
|
|
|
private const string KERNEL32 = "kernel32.dll";
|
|
|
|
internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";
|
|
|
|
[DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)]
|
|
|
|
public static extern bool CloseHandle(IntPtr handle);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
private static extern IntPtr GetModuleHandle(string lpModuleName);
|
|
|
|
public static bool IsAspNetCoreModuleLoaded()
|
|
{
|
|
return GetModuleHandle(AspNetCoreModuleDll) != IntPtr.Zero;
|
|
}
|
|
|
|
public enum REQUEST_NOTIFICATION_STATUS
|
|
{
|
|
RQ_NOTIFICATION_CONTINUE,
|
|
RQ_NOTIFICATION_PENDING,
|
|
RQ_NOTIFICATION_FINISH_REQUEST
|
|
}
|
|
|
|
public delegate REQUEST_NOTIFICATION_STATUS PFN_REQUEST_HANDLER(IntPtr pInProcessHandler, IntPtr pvRequestContext);
|
|
public delegate void PFN_DISCONNECT_HANDLER(IntPtr pvManagedHttpContext);
|
|
public delegate bool PFN_SHUTDOWN_HANDLER(IntPtr pvRequestContext);
|
|
public delegate REQUEST_NOTIFICATION_STATUS PFN_ASYNC_COMPLETION(IntPtr pvManagedHttpContext, int hr, int bytes);
|
|
public delegate REQUEST_NOTIFICATION_STATUS PFN_WEBSOCKET_ASYNC_COMPLETION(IntPtr pInProcessHandler, IntPtr completionInfo, IntPtr pvCompletionContext);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_post_completion(IntPtr pInProcessHandler, int cbBytes);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_set_completion_status(IntPtr pInProcessHandler, REQUEST_NOTIFICATION_STATUS rquestNotificationStatus);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern void http_indicate_completion(IntPtr pInProcessHandler, REQUEST_NOTIFICATION_STATUS notificationStatus);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int register_callbacks(IntPtr pInProcessApplication,
|
|
PFN_REQUEST_HANDLER requestCallback,
|
|
PFN_SHUTDOWN_HANDLER shutdownCallback,
|
|
PFN_DISCONNECT_HANDLER disconnectCallback,
|
|
PFN_ASYNC_COMPLETION asyncCallback,
|
|
IntPtr pvRequestContext,
|
|
IntPtr pvShutdownContext);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern unsafe int http_write_response_bytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_flush_response_bytes(IntPtr pInProcessHandler, out bool fCompletionExpected);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern unsafe HttpApiTypes.HTTP_REQUEST_V2* http_get_raw_request(IntPtr pInProcessHandler);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_stop_calls_into_managed(IntPtr pInProcessApplication);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_stop_incoming_requests(IntPtr pInProcessApplication);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_disable_buffering(IntPtr pInProcessApplication);
|
|
|
|
[DllImport(AspNetCoreModuleDll, CharSet = CharSet.Ansi)]
|
|
private static extern int http_set_response_status_code(IntPtr pInProcessHandler, ushort statusCode, string pszReason);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern unsafe int http_read_request_bytes(IntPtr pInProcessHandler, byte* pvBuffer, int cbBuffer, out int dwBytesReceived, out bool fCompletionExpected);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern void http_get_completion_info(IntPtr pCompletionInfo, out int cbBytes, out int hr);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_set_managed_context(IntPtr pInProcessHandler, IntPtr pvManagedContext);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_get_server_variable(
|
|
IntPtr pInProcessHandler,
|
|
[MarshalAs(UnmanagedType.LPStr)] string variableName,
|
|
[MarshalAs(UnmanagedType.BStr)] out string value);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_set_server_variable(
|
|
IntPtr pInProcessHandler,
|
|
[MarshalAs(UnmanagedType.LPStr)] string variableName,
|
|
[MarshalAs(UnmanagedType.LPWStr)] string value);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern unsafe int http_websockets_read_bytes(
|
|
IntPtr pInProcessHandler,
|
|
byte* pvBuffer,
|
|
int cbBuffer,
|
|
PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback,
|
|
IntPtr pvCompletionContext,
|
|
out int dwBytesReceived,
|
|
out bool fCompletionExpected);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern unsafe int http_websockets_write_bytes(
|
|
IntPtr pInProcessHandler,
|
|
HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks,
|
|
int nChunks,
|
|
PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback,
|
|
IntPtr pvCompletionContext,
|
|
out bool fCompletionExpected);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_enable_websockets(IntPtr pInProcessHandler);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_cancel_io(IntPtr pInProcessHandler);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_close_connection(IntPtr pInProcessHandler);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern unsafe int http_response_set_unknown_header(IntPtr pInProcessHandler, byte* pszHeaderName, byte* pszHeaderValue, ushort usHeaderValueLength, bool fReplace);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern unsafe int http_response_set_known_header(IntPtr pInProcessHandler, int headerId, byte* pHeaderValue, ushort length, bool fReplace);
|
|
|
|
[DllImport(AspNetCoreModuleDll)]
|
|
private static extern int http_get_authentication_information(IntPtr pInProcessHandler, [MarshalAs(UnmanagedType.BStr)] out string authType, out IntPtr token);
|
|
|
|
public static void HttpPostCompletion(IntPtr pInProcessHandler, int cbBytes)
|
|
{
|
|
Validate(http_post_completion(pInProcessHandler, cbBytes));
|
|
}
|
|
|
|
public static void HttpSetCompletionStatus(IntPtr pInProcessHandler, REQUEST_NOTIFICATION_STATUS rquestNotificationStatus)
|
|
{
|
|
Validate(http_set_completion_status(pInProcessHandler, rquestNotificationStatus));
|
|
}
|
|
|
|
public static void HttpRegisterCallbacks(IntPtr pInProcessApplication,
|
|
PFN_REQUEST_HANDLER requestCallback,
|
|
PFN_SHUTDOWN_HANDLER shutdownCallback,
|
|
PFN_DISCONNECT_HANDLER disconnectCallback,
|
|
PFN_ASYNC_COMPLETION asyncCallback,
|
|
IntPtr pvRequestContext,
|
|
IntPtr pvShutdownContext)
|
|
{
|
|
Validate(register_callbacks(pInProcessApplication, requestCallback, shutdownCallback, disconnectCallback, asyncCallback, pvRequestContext, pvShutdownContext));
|
|
}
|
|
|
|
public static unsafe int HttpWriteResponseBytes(IntPtr pInProcessHandler, HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks, int nChunks, out bool fCompletionExpected)
|
|
{
|
|
return http_write_response_bytes(pInProcessHandler, pDataChunks, nChunks, out fCompletionExpected);
|
|
}
|
|
|
|
public static int HttpFlushResponseBytes(IntPtr pInProcessHandler, out bool fCompletionExpected)
|
|
{
|
|
return http_flush_response_bytes(pInProcessHandler, out fCompletionExpected);
|
|
}
|
|
|
|
public static unsafe HttpApiTypes.HTTP_REQUEST_V2* HttpGetRawRequest(IntPtr pInProcessHandler)
|
|
{
|
|
return http_get_raw_request(pInProcessHandler);
|
|
}
|
|
|
|
public static void HttpStopCallsIntoManaged(IntPtr pInProcessApplication)
|
|
{
|
|
Validate(http_stop_calls_into_managed(pInProcessApplication));
|
|
}
|
|
|
|
public static void HttpStopIncomingRequests(IntPtr pInProcessApplication)
|
|
{
|
|
Validate(http_stop_incoming_requests(pInProcessApplication));
|
|
}
|
|
|
|
public static void HttpDisableBuffering(IntPtr pInProcessApplication)
|
|
{
|
|
Validate(http_disable_buffering(pInProcessApplication));
|
|
}
|
|
|
|
public static void HttpSetResponseStatusCode(IntPtr pInProcessHandler, ushort statusCode, string pszReason)
|
|
{
|
|
Validate(http_set_response_status_code(pInProcessHandler, statusCode, pszReason));
|
|
}
|
|
|
|
public static unsafe int HttpReadRequestBytes(IntPtr pInProcessHandler, byte* pvBuffer, int cbBuffer, out int dwBytesReceived, out bool fCompletionExpected)
|
|
{
|
|
return http_read_request_bytes(pInProcessHandler, pvBuffer, cbBuffer, out dwBytesReceived, out fCompletionExpected);
|
|
}
|
|
|
|
public static void HttpGetCompletionInfo(IntPtr pCompletionInfo, out int cbBytes, out int hr)
|
|
{
|
|
http_get_completion_info(pCompletionInfo, out cbBytes, out hr);
|
|
}
|
|
|
|
public static void HttpSetManagedContext(IntPtr pInProcessHandler, IntPtr pvManagedContext)
|
|
{
|
|
Validate(http_set_managed_context(pInProcessHandler, pvManagedContext));
|
|
}
|
|
|
|
public static IISConfigurationData HttpGetApplicationProperties()
|
|
{
|
|
var iisConfigurationData = new IISConfigurationData();
|
|
Validate(http_get_application_properties(ref iisConfigurationData));
|
|
return iisConfigurationData;
|
|
}
|
|
|
|
public static bool HttpTryGetServerVariable(IntPtr pInProcessHandler, string variableName, out string value)
|
|
{
|
|
return http_get_server_variable(pInProcessHandler, variableName, out value) == 0;
|
|
}
|
|
|
|
public static void HttpSetServerVariable(IntPtr pInProcessHandler, string variableName, string value)
|
|
{
|
|
Validate(http_set_server_variable(pInProcessHandler, variableName, value));
|
|
}
|
|
|
|
public static unsafe int HttpWebsocketsReadBytes(
|
|
IntPtr pInProcessHandler,
|
|
byte* pvBuffer,
|
|
int cbBuffer,
|
|
PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback,
|
|
IntPtr pvCompletionContext, out int dwBytesReceived,
|
|
out bool fCompletionExpected)
|
|
{
|
|
return http_websockets_read_bytes(pInProcessHandler, pvBuffer, cbBuffer, pfnCompletionCallback, pvCompletionContext, out dwBytesReceived, out fCompletionExpected);
|
|
}
|
|
|
|
public static unsafe int HttpWebsocketsWriteBytes(
|
|
IntPtr pInProcessHandler,
|
|
HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks,
|
|
int nChunks,
|
|
PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback,
|
|
IntPtr pvCompletionContext,
|
|
out bool fCompletionExpected)
|
|
{
|
|
return http_websockets_write_bytes(pInProcessHandler, pDataChunks, nChunks, pfnCompletionCallback, pvCompletionContext, out fCompletionExpected);
|
|
}
|
|
|
|
public static void HttpEnableWebsockets(IntPtr pInProcessHandler)
|
|
{
|
|
Validate(http_enable_websockets(pInProcessHandler));
|
|
}
|
|
|
|
public static bool HttpTryCancelIO(IntPtr pInProcessHandler)
|
|
{
|
|
var hr = http_cancel_io(pInProcessHandler);
|
|
// Async operation finished
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363792(v=vs.85).aspx
|
|
if (hr == ERROR_NOT_FOUND)
|
|
{
|
|
return false;
|
|
}
|
|
Validate(hr);
|
|
return true;
|
|
}
|
|
|
|
public static void HttpCloseConnection(IntPtr pInProcessHandler)
|
|
{
|
|
Validate(http_close_connection(pInProcessHandler));
|
|
}
|
|
|
|
public static unsafe void HttpResponseSetUnknownHeader(IntPtr pInProcessHandler, byte* pszHeaderName, byte* pszHeaderValue, ushort usHeaderValueLength, bool fReplace)
|
|
{
|
|
Validate(http_response_set_unknown_header(pInProcessHandler, pszHeaderName, pszHeaderValue, usHeaderValueLength, fReplace));
|
|
}
|
|
|
|
public static unsafe void HttpResponseSetKnownHeader(IntPtr pInProcessHandler, int headerId, byte* pHeaderValue, ushort length, bool fReplace)
|
|
{
|
|
Validate(http_response_set_known_header(pInProcessHandler, headerId, pHeaderValue, length, fReplace));
|
|
}
|
|
|
|
public static void HttpGetAuthenticationInformation(IntPtr pInProcessHandler, out string authType, out IntPtr token)
|
|
{
|
|
Validate(http_get_authentication_information(pInProcessHandler, out authType, out token));
|
|
}
|
|
|
|
private static void Validate(int hr)
|
|
{
|
|
if (hr != HR_OK)
|
|
{
|
|
throw Marshal.GetExceptionForHR(hr);
|
|
}
|
|
}
|
|
}
|
|
}
|