diff --git a/src/Microsoft.Net.Http.Server/AsyncAcceptContext.cs b/src/Microsoft.Net.Http.Server/AsyncAcceptContext.cs index ba34877b2a..d42a66e605 100644 --- a/src/Microsoft.Net.Http.Server/AsyncAcceptContext.cs +++ b/src/Microsoft.Net.Http.Server/AsyncAcceptContext.cs @@ -164,10 +164,10 @@ namespace Microsoft.Net.Http.Server { retry = false; uint bytesTransferred = 0; - statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveHttpRequest( + statusCode = HttpApi.HttpReceiveHttpRequest( Server.RequestQueue.Handle, _nativeRequestContext.RequestBlob->RequestId, - (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY, + (uint)HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY, _nativeRequestContext.RequestBlob, _nativeRequestContext.Size, &bytesTransferred, diff --git a/src/Microsoft.Net.Http.Server/AuthenticationManager.cs b/src/Microsoft.Net.Http.Server/AuthenticationManager.cs index cad91f8c30..c1f0ed0ac1 100644 --- a/src/Microsoft.Net.Http.Server/AuthenticationManager.cs +++ b/src/Microsoft.Net.Http.Server/AuthenticationManager.cs @@ -40,7 +40,7 @@ namespace Microsoft.Net.Http.Server public sealed class AuthenticationManager { private static readonly int AuthInfoSize = - Marshal.SizeOf(); + Marshal.SizeOf(); private WebListener _server; private AuthenticationSchemes _authSchemes; @@ -73,12 +73,12 @@ namespace Microsoft.Net.Http.Server private unsafe void SetServerSecurity() { - UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_AUTHENTICATION_INFO authInfo = - new UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_AUTHENTICATION_INFO(); + HttpApi.HTTP_SERVER_AUTHENTICATION_INFO authInfo = + new HttpApi.HTTP_SERVER_AUTHENTICATION_INFO(); - authInfo.Flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT; - var authSchemes = (UnsafeNclNativeMethods.HttpApi.HTTP_AUTH_TYPES)_authSchemes; - if (authSchemes != UnsafeNclNativeMethods.HttpApi.HTTP_AUTH_TYPES.NONE) + authInfo.Flags = HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT; + var authSchemes = (HttpApi.HTTP_AUTH_TYPES)_authSchemes; + if (authSchemes != HttpApi.HTTP_AUTH_TYPES.NONE) { authInfo.AuthSchemes = authSchemes; @@ -92,7 +92,7 @@ namespace Microsoft.Net.Http.Server IntPtr infoptr = new IntPtr(&authInfo); _server.UrlGroup.SetProperty( - UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY.HttpServerAuthenticationProperty, + HttpApi.HTTP_SERVER_PROPERTY.HttpServerAuthenticationProperty, infoptr, (uint)AuthInfoSize); } } @@ -144,25 +144,25 @@ namespace Microsoft.Net.Http.Server } } - internal static unsafe bool CheckAuthenticated(UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO* requestInfo) + internal static unsafe bool CheckAuthenticated(HttpApi.HTTP_REQUEST_INFO* requestInfo) { if (requestInfo != null - && requestInfo->InfoType == UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth - && requestInfo->pInfo->AuthStatus == UnsafeNclNativeMethods.HttpApi.HTTP_AUTH_STATUS.HttpAuthStatusSuccess) + && requestInfo->InfoType == HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth + && requestInfo->pInfo->AuthStatus == HttpApi.HTTP_AUTH_STATUS.HttpAuthStatusSuccess) { return true; } return false; } - internal static unsafe ClaimsPrincipal GetUser(UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO* requestInfo, int infoCount) + internal static unsafe ClaimsPrincipal GetUser(HttpApi.HTTP_REQUEST_INFO* requestInfo, int infoCount) { for (int i = 0; i < infoCount; i++) { var info = &requestInfo[i]; if (requestInfo != null - && info->InfoType == UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth - && info->pInfo->AuthStatus == UnsafeNclNativeMethods.HttpApi.HTTP_AUTH_STATUS.HttpAuthStatusSuccess) + && info->InfoType == HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth + && info->pInfo->AuthStatus == HttpApi.HTTP_AUTH_STATUS.HttpAuthStatusSuccess) { return new WindowsPrincipal(new WindowsIdentity(info->pInfo->AccessToken, GetAuthTypeFromRequest(info->pInfo->AuthType).ToString())); @@ -171,19 +171,19 @@ namespace Microsoft.Net.Http.Server return new ClaimsPrincipal(new ClaimsIdentity()); // Anonymous / !IsAuthenticated } - private static AuthenticationSchemes GetAuthTypeFromRequest(UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_AUTH_TYPE input) + private static AuthenticationSchemes GetAuthTypeFromRequest(HttpApi.HTTP_REQUEST_AUTH_TYPE input) { switch (input) { - case UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeBasic: + case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeBasic: return AuthenticationSchemes.Basic; - // case UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeDigest: + // case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeDigest: // return AuthenticationSchemes.Digest; - case UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeNTLM: + case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeNTLM: return AuthenticationSchemes.NTLM; - case UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeNegotiate: + case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeNegotiate: return AuthenticationSchemes.Negotiate; - case UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeKerberos: + case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeKerberos: return AuthenticationSchemes.Kerberos; default: throw new NotImplementedException(input.ToString()); diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/DisconnectListener.cs b/src/Microsoft.Net.Http.Server/NativeInterop/DisconnectListener.cs index 478a343177..ff45668da9 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/DisconnectListener.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/DisconnectListener.cs @@ -105,7 +105,7 @@ namespace Microsoft.Net.Http.Server uint statusCode; try { - statusCode = UnsafeNclNativeMethods.HttpApi.HttpWaitForDisconnectEx(requestQueueHandle: _requestQueue.Handle, + statusCode = HttpApi.HttpWaitForDisconnectEx(requestQueueHandle: _requestQueue.Handle, connectionId: connectionId, reserved: 0, overlapped: nativeOverlapped); } catch (Win32Exception exception) diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/HttpApi.cs b/src/Microsoft.Net.Http.Server/NativeInterop/HttpApi.cs new file mode 100644 index 0000000000..74f4de4788 --- /dev/null +++ b/src/Microsoft.Net.Http.Server/NativeInterop/HttpApi.cs @@ -0,0 +1,1078 @@ +// Copyright (c) .NET Foundation. +// All Rights Reserved +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING +// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF +// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR +// NON-INFRINGEMENT. +// See the Apache 2 License for the specific language governing +// permissions and limitations under the License. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Net.Http.Server +{ + internal static unsafe class HttpApi + { + private const string HTTPAPI = "httpapi.dll"; + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpInitialize(HTTPAPI_VERSION version, uint flags, void* pReserved); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpReceiveRequestEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, IntPtr pEntityBuffer, uint entityBufferLength, out uint bytesReturned, SafeNativeOverlapped pOverlapped); + + [DllImport(HTTPAPI, EntryPoint = "HttpReceiveRequestEntityBody", ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpReceiveRequestEntityBody2(SafeHandle requestQueueHandle, ulong requestId, uint flags, void* pEntityBuffer, uint entityBufferLength, out uint bytesReturned, [In] SafeHandle pOverlapped); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, HTTP_SSL_CLIENT_CERT_INFO* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, SafeNativeOverlapped pOverlapped); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, SafeNativeOverlapped pOverlapped); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, SafeNativeOverlapped pOverlapped); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpSendHttpResponse(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE_V2* pHttpResponse, HTTP_CACHE_POLICY* pCachePolicy, uint* pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, SafeNativeOverlapped pOverlapped, IntPtr pLogData); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpSendResponseEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, HTTP_DATA_CHUNK* pEntityChunks, uint* pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, SafeNativeOverlapped pOverlapped, IntPtr pLogData); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpCancelHttpRequest(SafeHandle requestQueueHandle, ulong requestId, IntPtr pOverlapped); + + [DllImport(HTTPAPI, EntryPoint = "HttpSendResponseEntityBody", ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpSendResponseEntityBody2(SafeHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, IntPtr pEntityChunks, out uint pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, SafeHandle pOverlapped, IntPtr pLogData); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpWaitForDisconnectEx(SafeHandle requestQueueHandle, ulong connectionId, uint reserved, SafeNativeOverlapped overlapped); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpCreateServerSession(HTTPAPI_VERSION version, ulong* serverSessionId, uint reserved); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpCreateUrlGroup(ulong serverSessionId, ulong* urlGroupId, uint reserved); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern uint HttpAddUrlToUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, ulong context, uint pReserved); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpSetUrlGroupProperty(ulong urlGroupId, HTTP_SERVER_PROPERTY serverProperty, IntPtr pPropertyInfo, uint propertyInfoLength); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern uint HttpRemoveUrlFromUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, uint flags); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpCloseServerSession(ulong serverSessionId); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpCloseUrlGroup(ulong urlGroupId); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern uint HttpSetRequestQueueProperty(SafeHandle requestQueueHandle, HTTP_SERVER_PROPERTY serverProperty, IntPtr pPropertyInfo, uint propertyInfoLength, uint reserved, IntPtr pReserved); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern unsafe uint HttpCreateRequestQueue(HTTPAPI_VERSION version, string pName, + UnsafeNclNativeMethods.SECURITY_ATTRIBUTES pSecurityAttributes, uint flags, out HttpRequestQueueV2Handle pReqQueueHandle); + + [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern unsafe uint HttpCloseRequestQueue(IntPtr pReqQueueHandle); + + internal enum HTTP_API_VERSION + { + Invalid, + Version10, + Version20, + } + + // see http.w for definitions + internal enum HTTP_SERVER_PROPERTY + { + HttpServerAuthenticationProperty, + HttpServerLoggingProperty, + HttpServerQosProperty, + HttpServerTimeoutsProperty, + HttpServerQueueLengthProperty, + HttpServerStateProperty, + HttpServer503VerbosityProperty, + HttpServerBindingProperty, + HttpServerExtendedAuthenticationProperty, + HttpServerListenEndpointProperty, + HttpServerChannelBindProperty, + HttpServerProtectionLevelProperty, + } + + // Currently only one request info type is supported but the enum is for future extensibility. + + internal enum HTTP_REQUEST_INFO_TYPE + { + HttpRequestInfoTypeAuth, + HttpRequestInfoTypeChannelBind, + HttpRequestInfoTypeSslProtocol, + HttpRequestInfoTypeSslTokenBinding + } + + internal enum HTTP_RESPONSE_INFO_TYPE + { + HttpResponseInfoTypeMultipleKnownHeaders, + HttpResponseInfoTypeAuthenticationProperty, + HttpResponseInfoTypeQosProperty, + } + + internal enum HTTP_TIMEOUT_TYPE + { + EntityBody, + DrainEntityBody, + RequestQueue, + IdleConnection, + HeaderWait, + MinSendRate, + } + + internal const int MaxTimeout = 6; + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_VERSION + { + internal ushort MajorVersion; + internal ushort MinorVersion; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_KNOWN_HEADER + { + internal ushort RawValueLength; + internal sbyte* pRawValue; + } + + [StructLayout(LayoutKind.Explicit)] + internal struct HTTP_DATA_CHUNK + { + [FieldOffset(0)] + internal HTTP_DATA_CHUNK_TYPE DataChunkType; + + [FieldOffset(8)] + internal FromMemory fromMemory; + + [FieldOffset(8)] + internal FromFileHandle fromFile; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct FromMemory + { + // 4 bytes for 32bit, 8 bytes for 64bit + internal IntPtr pBuffer; + internal uint BufferLength; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct FromFileHandle + { + internal ulong offset; + internal ulong count; + internal IntPtr fileHandle; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTPAPI_VERSION + { + internal ushort HttpApiMajorVersion; + internal ushort HttpApiMinorVersion; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_COOKED_URL + { + internal ushort FullUrlLength; + internal ushort HostLength; + internal ushort AbsPathLength; + internal ushort QueryStringLength; + internal ushort* pFullUrl; + internal ushort* pHost; + internal ushort* pAbsPath; + internal ushort* pQueryString; + } + + // Only cache unauthorized GETs + HEADs. + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_CACHE_POLICY + { + internal HTTP_CACHE_POLICY_TYPE Policy; + internal uint SecondsToLive; + } + + internal enum HTTP_CACHE_POLICY_TYPE : int + { + HttpCachePolicyNocache = 0, + HttpCachePolicyUserInvalidates = 1, + HttpCachePolicyTimeToLive = 2, + } + + [StructLayout(LayoutKind.Sequential)] + internal struct SOCKADDR + { + internal ushort sa_family; + internal byte sa_data; + internal byte sa_data_02; + internal byte sa_data_03; + internal byte sa_data_04; + internal byte sa_data_05; + internal byte sa_data_06; + internal byte sa_data_07; + internal byte sa_data_08; + internal byte sa_data_09; + internal byte sa_data_10; + internal byte sa_data_11; + internal byte sa_data_12; + internal byte sa_data_13; + internal byte sa_data_14; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_TRANSPORT_ADDRESS + { + internal SOCKADDR* pRemoteAddress; + internal SOCKADDR* pLocalAddress; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_SSL_CLIENT_CERT_INFO + { + internal uint CertFlags; + internal uint CertEncodedSize; + internal byte* pCertEncoded; + internal void* Token; + internal byte CertDeniedByMapper; + } + + internal enum HTTP_SERVICE_BINDING_TYPE : uint + { + HttpServiceBindingTypeNone = 0, + HttpServiceBindingTypeW, + HttpServiceBindingTypeA + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_SERVICE_BINDING_BASE + { + internal HTTP_SERVICE_BINDING_TYPE Type; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_REQUEST_CHANNEL_BIND_STATUS + { + internal IntPtr ServiceName; + internal IntPtr ChannelToken; + internal uint ChannelTokenSize; + internal uint Flags; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_UNKNOWN_HEADER + { + internal ushort NameLength; + internal ushort RawValueLength; + internal sbyte* pName; + internal sbyte* pRawValue; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_SSL_INFO + { + internal ushort ServerCertKeySize; + internal ushort ConnectionKeySize; + internal uint ServerCertIssuerSize; + internal uint ServerCertSubjectSize; + internal sbyte* pServerCertIssuer; + internal sbyte* pServerCertSubject; + internal HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo; + internal uint SslClientCertNegotiated; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_RESPONSE_HEADERS + { + internal ushort UnknownHeaderCount; + internal HTTP_UNKNOWN_HEADER* pUnknownHeaders; + internal ushort TrailerCount; + internal HTTP_UNKNOWN_HEADER* pTrailers; + internal HTTP_KNOWN_HEADER KnownHeaders; + internal HTTP_KNOWN_HEADER KnownHeaders_02; + internal HTTP_KNOWN_HEADER KnownHeaders_03; + internal HTTP_KNOWN_HEADER KnownHeaders_04; + internal HTTP_KNOWN_HEADER KnownHeaders_05; + internal HTTP_KNOWN_HEADER KnownHeaders_06; + internal HTTP_KNOWN_HEADER KnownHeaders_07; + internal HTTP_KNOWN_HEADER KnownHeaders_08; + internal HTTP_KNOWN_HEADER KnownHeaders_09; + internal HTTP_KNOWN_HEADER KnownHeaders_10; + internal HTTP_KNOWN_HEADER KnownHeaders_11; + internal HTTP_KNOWN_HEADER KnownHeaders_12; + internal HTTP_KNOWN_HEADER KnownHeaders_13; + internal HTTP_KNOWN_HEADER KnownHeaders_14; + internal HTTP_KNOWN_HEADER KnownHeaders_15; + internal HTTP_KNOWN_HEADER KnownHeaders_16; + internal HTTP_KNOWN_HEADER KnownHeaders_17; + internal HTTP_KNOWN_HEADER KnownHeaders_18; + internal HTTP_KNOWN_HEADER KnownHeaders_19; + internal HTTP_KNOWN_HEADER KnownHeaders_20; + internal HTTP_KNOWN_HEADER KnownHeaders_21; + internal HTTP_KNOWN_HEADER KnownHeaders_22; + internal HTTP_KNOWN_HEADER KnownHeaders_23; + internal HTTP_KNOWN_HEADER KnownHeaders_24; + internal HTTP_KNOWN_HEADER KnownHeaders_25; + internal HTTP_KNOWN_HEADER KnownHeaders_26; + internal HTTP_KNOWN_HEADER KnownHeaders_27; + internal HTTP_KNOWN_HEADER KnownHeaders_28; + internal HTTP_KNOWN_HEADER KnownHeaders_29; + internal HTTP_KNOWN_HEADER KnownHeaders_30; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_REQUEST_HEADERS + { + internal ushort UnknownHeaderCount; + internal HTTP_UNKNOWN_HEADER* pUnknownHeaders; + internal ushort TrailerCount; + internal HTTP_UNKNOWN_HEADER* pTrailers; + internal HTTP_KNOWN_HEADER KnownHeaders; + internal HTTP_KNOWN_HEADER KnownHeaders_02; + internal HTTP_KNOWN_HEADER KnownHeaders_03; + internal HTTP_KNOWN_HEADER KnownHeaders_04; + internal HTTP_KNOWN_HEADER KnownHeaders_05; + internal HTTP_KNOWN_HEADER KnownHeaders_06; + internal HTTP_KNOWN_HEADER KnownHeaders_07; + internal HTTP_KNOWN_HEADER KnownHeaders_08; + internal HTTP_KNOWN_HEADER KnownHeaders_09; + internal HTTP_KNOWN_HEADER KnownHeaders_10; + internal HTTP_KNOWN_HEADER KnownHeaders_11; + internal HTTP_KNOWN_HEADER KnownHeaders_12; + internal HTTP_KNOWN_HEADER KnownHeaders_13; + internal HTTP_KNOWN_HEADER KnownHeaders_14; + internal HTTP_KNOWN_HEADER KnownHeaders_15; + internal HTTP_KNOWN_HEADER KnownHeaders_16; + internal HTTP_KNOWN_HEADER KnownHeaders_17; + internal HTTP_KNOWN_HEADER KnownHeaders_18; + internal HTTP_KNOWN_HEADER KnownHeaders_19; + internal HTTP_KNOWN_HEADER KnownHeaders_20; + internal HTTP_KNOWN_HEADER KnownHeaders_21; + internal HTTP_KNOWN_HEADER KnownHeaders_22; + internal HTTP_KNOWN_HEADER KnownHeaders_23; + internal HTTP_KNOWN_HEADER KnownHeaders_24; + internal HTTP_KNOWN_HEADER KnownHeaders_25; + internal HTTP_KNOWN_HEADER KnownHeaders_26; + internal HTTP_KNOWN_HEADER KnownHeaders_27; + internal HTTP_KNOWN_HEADER KnownHeaders_28; + internal HTTP_KNOWN_HEADER KnownHeaders_29; + internal HTTP_KNOWN_HEADER KnownHeaders_30; + internal HTTP_KNOWN_HEADER KnownHeaders_31; + internal HTTP_KNOWN_HEADER KnownHeaders_32; + internal HTTP_KNOWN_HEADER KnownHeaders_33; + internal HTTP_KNOWN_HEADER KnownHeaders_34; + internal HTTP_KNOWN_HEADER KnownHeaders_35; + internal HTTP_KNOWN_HEADER KnownHeaders_36; + internal HTTP_KNOWN_HEADER KnownHeaders_37; + internal HTTP_KNOWN_HEADER KnownHeaders_38; + internal HTTP_KNOWN_HEADER KnownHeaders_39; + internal HTTP_KNOWN_HEADER KnownHeaders_40; + internal HTTP_KNOWN_HEADER KnownHeaders_41; + } + + internal enum HTTP_VERB : int + { + HttpVerbUnparsed = 0, + HttpVerbUnknown = 1, + HttpVerbInvalid = 2, + HttpVerbOPTIONS = 3, + HttpVerbGET = 4, + HttpVerbHEAD = 5, + HttpVerbPOST = 6, + HttpVerbPUT = 7, + HttpVerbDELETE = 8, + HttpVerbTRACE = 9, + HttpVerbCONNECT = 10, + HttpVerbTRACK = 11, + HttpVerbMOVE = 12, + HttpVerbCOPY = 13, + HttpVerbPROPFIND = 14, + HttpVerbPROPPATCH = 15, + HttpVerbMKCOL = 16, + HttpVerbLOCK = 17, + HttpVerbUNLOCK = 18, + HttpVerbSEARCH = 19, + HttpVerbMaximum = 20, + } + + internal static readonly string[] HttpVerbs = new string[] + { + null, + "Unknown", + "Invalid", + "OPTIONS", + "GET", + "HEAD", + "POST", + "PUT", + "DELETE", + "TRACE", + "CONNECT", + "TRACK", + "MOVE", + "COPY", + "PROPFIND", + "PROPPATCH", + "MKCOL", + "LOCK", + "UNLOCK", + "SEARCH", + }; + + internal enum HTTP_DATA_CHUNK_TYPE : int + { + HttpDataChunkFromMemory = 0, + HttpDataChunkFromFileHandle = 1, + HttpDataChunkFromFragmentCache = 2, + HttpDataChunkMaximum = 3, + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_RESPONSE_INFO + { + internal HTTP_RESPONSE_INFO_TYPE Type; + internal uint Length; + internal HTTP_MULTIPLE_KNOWN_HEADERS* pInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_RESPONSE + { + internal uint Flags; + internal HTTP_VERSION Version; + internal ushort StatusCode; + internal ushort ReasonLength; + internal sbyte* pReason; + internal HTTP_RESPONSE_HEADERS Headers; + internal ushort EntityChunkCount; + internal HTTP_DATA_CHUNK* pEntityChunks; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_RESPONSE_V2 + { + internal HTTP_RESPONSE Response_V1; + internal ushort ResponseInfoCount; + internal HTTP_RESPONSE_INFO* pResponseInfo; + } + + internal enum HTTP_RESPONSE_INFO_FLAGS : uint + { + None = 0, + PreserveOrder = 1, + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_MULTIPLE_KNOWN_HEADERS + { + internal HTTP_RESPONSE_HEADER_ID.Enum HeaderId; + internal HTTP_RESPONSE_INFO_FLAGS Flags; + internal ushort KnownHeaderCount; + internal HTTP_KNOWN_HEADER* KnownHeaders; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_REQUEST_AUTH_INFO + { + internal HTTP_AUTH_STATUS AuthStatus; + internal uint SecStatus; + internal uint Flags; + internal HTTP_REQUEST_AUTH_TYPE AuthType; + internal IntPtr AccessToken; + internal uint ContextAttributes; + internal uint PackedContextLength; + internal uint PackedContextType; + internal IntPtr PackedContext; + internal uint MutualAuthDataLength; + internal char* pMutualAuthData; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_REQUEST_INFO + { + internal HTTP_REQUEST_INFO_TYPE InfoType; + internal uint InfoLength; + internal HTTP_REQUEST_AUTH_INFO* pInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_REQUEST + { + internal uint Flags; + internal ulong ConnectionId; + internal ulong RequestId; + internal ulong UrlContext; + internal HTTP_VERSION Version; + internal HTTP_VERB Verb; + internal ushort UnknownVerbLength; + internal ushort RawUrlLength; + internal sbyte* pUnknownVerb; + internal sbyte* pRawUrl; + internal HTTP_COOKED_URL CookedUrl; + internal HTTP_TRANSPORT_ADDRESS Address; + internal HTTP_REQUEST_HEADERS Headers; + internal ulong BytesReceived; + internal ushort EntityChunkCount; + internal HTTP_DATA_CHUNK* pEntityChunks; + internal ulong RawConnectionId; + internal HTTP_SSL_INFO* pSslInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_REQUEST_V2 + { + internal HTTP_REQUEST Request; + internal ushort RequestInfoCount; + internal HTTP_REQUEST_INFO* pRequestInfo; + } + + internal enum HTTP_AUTH_STATUS + { + HttpAuthStatusSuccess, + HttpAuthStatusNotAuthenticated, + HttpAuthStatusFailure, + } + + internal enum HTTP_REQUEST_AUTH_TYPE + { + HttpRequestAuthTypeNone = 0, + HttpRequestAuthTypeBasic, + HttpRequestAuthTypeDigest, + HttpRequestAuthTypeNTLM, + HttpRequestAuthTypeNegotiate, + HttpRequestAuthTypeKerberos + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_SERVER_AUTHENTICATION_INFO + { + internal HTTP_FLAGS Flags; + internal HTTP_AUTH_TYPES AuthSchemes; + internal bool ReceiveMutualAuth; + internal bool ReceiveContextHandle; + internal bool DisableNTLMCredentialCaching; + internal ulong ExFlags; + HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS DigestParams; + HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS BasicParams; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS + { + internal ushort DomainNameLength; + internal char* DomainName; + internal ushort RealmLength; + internal char* Realm; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS + { + ushort RealmLength; + char* Realm; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_REQUEST_TOKEN_BINDING_INFO + { + public byte* TokenBinding; + public uint TokenBindingSize; + + public byte* TlsUnique; + public uint TlsUniqueSize; + + public char* KeyType; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_TIMEOUT_LIMIT_INFO + { + internal HTTP_FLAGS Flags; + internal ushort EntityBody; + internal ushort DrainEntityBody; + internal ushort RequestQueue; + internal ushort IdleConnection; + internal ushort HeaderWait; + internal uint MinSendRate; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HTTP_BINDING_INFO + { + internal HTTP_FLAGS Flags; + internal IntPtr RequestQueueHandle; + } + + // see http.w for definitions + [Flags] + internal enum HTTP_FLAGS : uint + { + NONE = 0x00000000, + HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY = 0x00000001, + HTTP_RECEIVE_SECURE_CHANNEL_TOKEN = 0x00000001, + HTTP_SEND_RESPONSE_FLAG_DISCONNECT = 0x00000001, + HTTP_SEND_RESPONSE_FLAG_MORE_DATA = 0x00000002, + HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA = 0x00000004, + HTTP_SEND_RESPONSE_FLAG_RAW_HEADER = 0x00000004, + HTTP_SEND_REQUEST_FLAG_MORE_DATA = 0x00000001, + HTTP_PROPERTY_FLAG_PRESENT = 0x00000001, + HTTP_INITIALIZE_SERVER = 0x00000001, + HTTP_INITIALIZE_CBT = 0x00000004, + HTTP_SEND_RESPONSE_FLAG_OPAQUE = 0x00000040, + } + + [Flags] + internal enum HTTP_AUTH_TYPES : uint + { + NONE = 0x00000000, + HTTP_AUTH_ENABLE_BASIC = 0x00000001, + HTTP_AUTH_ENABLE_DIGEST = 0x00000002, + HTTP_AUTH_ENABLE_NTLM = 0x00000004, + HTTP_AUTH_ENABLE_NEGOTIATE = 0x00000008, + HTTP_AUTH_ENABLE_KERBEROS = 0x00000010, + } + + private const int HttpHeaderRequestMaximum = (int)HttpSysRequestHeader.UserAgent + 1; + private const int HttpHeaderResponseMaximum = (int)HttpSysResponseHeader.WwwAuthenticate + 1; + + internal static class HTTP_REQUEST_HEADER_ID + { + internal static string ToString(int position) + { + return _strings[position]; + } + + private static string[] _strings = + { + "Cache-Control", + "Connection", + "Date", + "Keep-Alive", + "Pragma", + "Trailer", + "Transfer-Encoding", + "Upgrade", + "Via", + "Warning", + + "Allow", + "Content-Length", + "Content-Type", + "Content-Encoding", + "Content-Language", + "Content-Location", + "Content-MD5", + "Content-Range", + "Expires", + "Last-Modified", + + "Accept", + "Accept-Charset", + "Accept-Encoding", + "Accept-Language", + "Authorization", + "Cookie", + "Expect", + "From", + "Host", + "If-Match", + + "If-Modified-Since", + "If-None-Match", + "If-Range", + "If-Unmodified-Since", + "Max-Forwards", + "Proxy-Authorization", + "Referer", + "Range", + "Te", + "Translate", + "User-Agent", + }; + } + + internal static class HTTP_RESPONSE_HEADER_ID + { + private static string[] _strings = + { + "Cache-Control", + "Connection", + "Date", + "Keep-Alive", + "Pragma", + "Trailer", + "Transfer-Encoding", + "Upgrade", + "Via", + "Warning", + + "Allow", + "Content-Length", + "Content-Type", + "Content-Encoding", + "Content-Language", + "Content-Location", + "Content-MD5", + "Content-Range", + "Expires", + "Last-Modified", + + "Accept-Ranges", + "Age", + "ETag", + "Location", + "Proxy-Authenticate", + "Retry-After", + "Server", + "Set-Cookie", + "Vary", + "WWW-Authenticate", + }; + + private static Dictionary _lookupTable = CreateLookupTable(); + + private static Dictionary CreateLookupTable() + { + Dictionary lookupTable = new Dictionary((int)Enum.HttpHeaderResponseMaximum, StringComparer.OrdinalIgnoreCase); + for (int i = 0; i < (int)Enum.HttpHeaderResponseMaximum; i++) + { + lookupTable.Add(_strings[i], i); + } + return lookupTable; + } + + internal static int IndexOfKnownHeader(string HeaderName) + { + int index; + return _lookupTable.TryGetValue(HeaderName, out index) ? index : -1; + } + + internal static string ToString(int position) + { + return _strings[position]; + } + + internal enum Enum + { + HttpHeaderCacheControl = 0, // general-header [section 4.5] + HttpHeaderConnection = 1, // general-header [section 4.5] + HttpHeaderDate = 2, // general-header [section 4.5] + HttpHeaderKeepAlive = 3, // general-header [not in rfc] + HttpHeaderPragma = 4, // general-header [section 4.5] + HttpHeaderTrailer = 5, // general-header [section 4.5] + HttpHeaderTransferEncoding = 6, // general-header [section 4.5] + HttpHeaderUpgrade = 7, // general-header [section 4.5] + HttpHeaderVia = 8, // general-header [section 4.5] + HttpHeaderWarning = 9, // general-header [section 4.5] + + HttpHeaderAllow = 10, // entity-header [section 7.1] + HttpHeaderContentLength = 11, // entity-header [section 7.1] + HttpHeaderContentType = 12, // entity-header [section 7.1] + HttpHeaderContentEncoding = 13, // entity-header [section 7.1] + HttpHeaderContentLanguage = 14, // entity-header [section 7.1] + HttpHeaderContentLocation = 15, // entity-header [section 7.1] + HttpHeaderContentMd5 = 16, // entity-header [section 7.1] + HttpHeaderContentRange = 17, // entity-header [section 7.1] + HttpHeaderExpires = 18, // entity-header [section 7.1] + HttpHeaderLastModified = 19, // entity-header [section 7.1] + + // Response Headers + + HttpHeaderAcceptRanges = 20, // response-header [section 6.2] + HttpHeaderAge = 21, // response-header [section 6.2] + HttpHeaderEtag = 22, // response-header [section 6.2] + HttpHeaderLocation = 23, // response-header [section 6.2] + HttpHeaderProxyAuthenticate = 24, // response-header [section 6.2] + HttpHeaderRetryAfter = 25, // response-header [section 6.2] + HttpHeaderServer = 26, // response-header [section 6.2] + HttpHeaderSetCookie = 27, // response-header [not in rfc] + HttpHeaderVary = 28, // response-header [section 6.2] + HttpHeaderWwwAuthenticate = 29, // response-header [section 6.2] + + HttpHeaderResponseMaximum = 30, + + HttpHeaderMaximum = 41 + } + } + + private static HTTPAPI_VERSION version; + + // This property is used by HttpListener to pass the version structure to the native layer in API + // calls. + + internal static HTTPAPI_VERSION Version + { + get + { + return version; + } + } + + // This property is used by HttpListener to get the Api version in use so that it uses appropriate + // Http APIs. + + internal static HTTP_API_VERSION ApiVersion + { + get + { + if (version.HttpApiMajorVersion == 2 && version.HttpApiMinorVersion == 0) + { + return HTTP_API_VERSION.Version20; + } + else if (version.HttpApiMajorVersion == 1 && version.HttpApiMinorVersion == 0) + { + return HTTP_API_VERSION.Version10; + } + else + { + return HTTP_API_VERSION.Invalid; + } + } + } + + static HttpApi() + { + InitHttpApi(2, 0); + } + + private static void InitHttpApi(ushort majorVersion, ushort minorVersion) + { + version.HttpApiMajorVersion = majorVersion; + version.HttpApiMinorVersion = minorVersion; + + var statusCode = HttpInitialize(version, (uint)HTTP_FLAGS.HTTP_INITIALIZE_SERVER, null); + + supported = statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS; + } + + private static volatile bool supported; + internal static bool Supported + { + get + { + return supported; + } + } + + // Server API + + internal static void GetUnknownHeaders(IDictionary unknownHeaders, byte[] memoryBlob, + int requestOffset, IntPtr originalAddress) + { + // Return value. + fixed (byte* pMemoryBlob = memoryBlob) + { + HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset); + long fixup = pMemoryBlob - (byte*)originalAddress; + int index; + + // unknown headers + if (request->Headers.UnknownHeaderCount != 0) + { + HTTP_UNKNOWN_HEADER* pUnknownHeader = (HTTP_UNKNOWN_HEADER*)(fixup + (byte*)request->Headers.pUnknownHeaders); + for (index = 0; index < request->Headers.UnknownHeaderCount; index++) + { + // For unknown headers, when header value is empty, RawValueLength will be 0 and + // pRawValue will be null. + if (pUnknownHeader->pName != null && pUnknownHeader->NameLength > 0) + { + string headerName = HeaderEncoding.GetString(pUnknownHeader->pName + fixup, pUnknownHeader->NameLength); + string headerValue; + if (pUnknownHeader->pRawValue != null && pUnknownHeader->RawValueLength > 0) + { + headerValue = HeaderEncoding.GetString(pUnknownHeader->pRawValue + fixup, pUnknownHeader->RawValueLength); + } + else + { + headerValue = string.Empty; + } + // Note that Http.Sys currently collapses all headers of the same name to a single coma seperated string, + // so we can just call Set. + unknownHeaders[headerName] = headerValue; + } + pUnknownHeader++; + } + } + } + } + + private static string GetKnownHeader(HTTP_REQUEST* request, long fixup, int headerIndex) + { + string header = null; + + HTTP_KNOWN_HEADER* pKnownHeader = (&request->Headers.KnownHeaders) + headerIndex; + // For known headers, when header value is empty, RawValueLength will be 0 and + // pRawValue will point to empty string ("\0") + if (pKnownHeader->pRawValue != null) + { + header = HeaderEncoding.GetString(pKnownHeader->pRawValue + fixup, pKnownHeader->RawValueLength); + } + + return header; + } + + internal static string GetKnownHeader(byte[] memoryBlob, int requestOffset, IntPtr originalAddress, int headerIndex) + { + fixed (byte* pMemoryBlob = memoryBlob) + { + return GetKnownHeader( + (HTTP_REQUEST*)(pMemoryBlob + requestOffset), pMemoryBlob - (byte*)originalAddress, headerIndex); + } + } + + // This requires the HTTP_REQUEST to still be pinned in its original location. + internal static unsafe string GetVerb(HTTP_REQUEST* request) + { + string verb = null; + + if ((int)request->Verb > (int)HTTP_VERB.HttpVerbUnknown && (int)request->Verb < (int)HTTP_VERB.HttpVerbMaximum) + { + verb = HttpVerbs[(int)request->Verb]; + } + else if (request->Verb == HTTP_VERB.HttpVerbUnknown && request->pUnknownVerb != null) + { + verb = HeaderEncoding.GetString(request->pUnknownVerb, request->UnknownVerbLength); + } + + return verb; + } + + internal static uint GetChunks(byte[] memoryBlob, int requestOffset, IntPtr originalAddress, + ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size) + { + // Return value. + uint dataRead = 0; + fixed (byte* pMemoryBlob = memoryBlob) + { + HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset); + long fixup = pMemoryBlob - (byte*)originalAddress; + + if (request->EntityChunkCount > 0 && dataChunkIndex < request->EntityChunkCount && dataChunkIndex != -1) + { + HTTP_DATA_CHUNK* pDataChunk = (HTTP_DATA_CHUNK*)(fixup + (byte*)&request->pEntityChunks[dataChunkIndex]); + + fixed (byte* pReadBuffer = buffer) + { + byte* pTo = &pReadBuffer[offset]; + + while (dataChunkIndex < request->EntityChunkCount && dataRead < size) + { + if (dataChunkOffset >= pDataChunk->fromMemory.BufferLength) + { + dataChunkOffset = 0; + dataChunkIndex++; + pDataChunk++; + } + else + { + byte* pFrom = (byte*)pDataChunk->fromMemory.pBuffer + dataChunkOffset + fixup; + + uint bytesToRead = pDataChunk->fromMemory.BufferLength - (uint)dataChunkOffset; + if (bytesToRead > (uint)size) + { + bytesToRead = (uint)size; + } + for (uint i = 0; i < bytesToRead; i++) + { + *(pTo++) = *(pFrom++); + } + dataRead += bytesToRead; + dataChunkOffset += bytesToRead; + } + } + } + } + // we're finished. + if (dataChunkIndex == request->EntityChunkCount) + { + dataChunkIndex = -1; + } + } + + return dataRead; + } + + internal static SocketAddress GetRemoteEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress) + { + fixed (byte* pMemoryBlob = memoryBlob) + { + HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset); + return GetEndPoint(memoryBlob, requestOffset, originalAddress, (byte*)request->Address.pRemoteAddress); + } + } + + internal static SocketAddress GetLocalEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress) + { + fixed (byte* pMemoryBlob = memoryBlob) + { + HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset); + return GetEndPoint(memoryBlob, requestOffset, originalAddress, (byte*)request->Address.pLocalAddress); + } + } + + internal static SocketAddress GetEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress, byte* source) + { + fixed (byte* pMemoryBlob = memoryBlob) + { + IntPtr address = source != null ? + (IntPtr)(pMemoryBlob + requestOffset - (byte*)originalAddress + source) : IntPtr.Zero; + return CopyOutAddress(address); + } + } + + private static SocketAddress CopyOutAddress(IntPtr address) + { + if (address != IntPtr.Zero) + { + ushort addressFamily = *((ushort*)address); + if (addressFamily == (ushort)AddressFamily.InterNetwork) + { + SocketAddress v4address = new SocketAddress(AddressFamily.InterNetwork, SocketAddress.IPv4AddressSize); + fixed (byte* pBuffer = v4address.Buffer) + { + for (int index = 2; index < SocketAddress.IPv4AddressSize; index++) + { + pBuffer[index] = ((byte*)address)[index]; + } + } + return v4address; + } + if (addressFamily == (ushort)AddressFamily.InterNetworkV6) + { + SocketAddress v6address = new SocketAddress(AddressFamily.InterNetworkV6, SocketAddress.IPv6AddressSize); + fixed (byte* pBuffer = v6address.Buffer) + { + for (int index = 2; index < SocketAddress.IPv6AddressSize; index++) + { + pBuffer[index] = ((byte*)address)[index]; + } + } + return v6address; + } + } + + return null; + } + } +} diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/HttpRequestQueueV2Handle.cs b/src/Microsoft.Net.Http.Server/NativeInterop/HttpRequestQueueV2Handle.cs index bcf8890704..8b78d4e14a 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/HttpRequestQueueV2Handle.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/HttpRequestQueueV2Handle.cs @@ -35,7 +35,7 @@ namespace Microsoft.Net.Http.Server protected override bool ReleaseHandle() { - return (UnsafeNclNativeMethods.SafeNetHandles.HttpCloseRequestQueue(handle) == + return (HttpApi.HttpCloseRequestQueue(handle) == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS); } } diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/HttpServerSessionHandle.cs b/src/Microsoft.Net.Http.Server/NativeInterop/HttpServerSessionHandle.cs index 6300ef684b..1bdfafb8f7 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/HttpServerSessionHandle.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/HttpServerSessionHandle.cs @@ -55,7 +55,7 @@ namespace Microsoft.Net.Http.Server if (Interlocked.Increment(ref disposed) == 1) { // Closing server session also closes all open url groups under that server session. - return (UnsafeNclNativeMethods.HttpApi.HttpCloseServerSession(serverSessionId) == + return (HttpApi.HttpCloseServerSession(serverSessionId) == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS); } } diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/RequestQueue.cs b/src/Microsoft.Net.Http.Server/NativeInterop/RequestQueue.cs index 6b3ef07665..87b07e5996 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/RequestQueue.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/RequestQueue.cs @@ -28,7 +28,7 @@ namespace Microsoft.Net.Http.Server internal class RequestQueue { private static readonly int BindingInfoSize = - Marshal.SizeOf(); + Marshal.SizeOf(); private readonly UrlGroup _urlGroup; private readonly ILogger _logger; @@ -39,8 +39,8 @@ namespace Microsoft.Net.Http.Server _logger = logger; HttpRequestQueueV2Handle requestQueueHandle = null; - var statusCode = UnsafeNclNativeMethods.SafeNetHandles.HttpCreateRequestQueue( - UnsafeNclNativeMethods.HttpApi.Version, null, null, 0, out requestQueueHandle); + var statusCode = HttpApi.HttpCreateRequestQueue( + HttpApi.Version, null, null, 0, out requestQueueHandle); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { @@ -69,13 +69,13 @@ namespace Microsoft.Net.Http.Server // Set the association between request queue and url group. After this, requests for registered urls will // get delivered to this request queue. - var info = new UnsafeNclNativeMethods.HttpApi.HTTP_BINDING_INFO(); - info.Flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT; + var info = new HttpApi.HTTP_BINDING_INFO(); + info.Flags = HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT; info.RequestQueueHandle = Handle.DangerousGetHandle(); var infoptr = new IntPtr(&info); - _urlGroup.SetProperty(UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY.HttpServerBindingProperty, + _urlGroup.SetProperty(HttpApi.HTTP_SERVER_PROPERTY.HttpServerBindingProperty, infoptr, (uint)BindingInfoSize); } @@ -87,21 +87,21 @@ namespace Microsoft.Net.Http.Server // is fine since http.sys allows to set HttpServerBindingProperty multiple times for valid // Url groups. - var info = new UnsafeNclNativeMethods.HttpApi.HTTP_BINDING_INFO(); - info.Flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE; + var info = new HttpApi.HTTP_BINDING_INFO(); + info.Flags = HttpApi.HTTP_FLAGS.NONE; info.RequestQueueHandle = IntPtr.Zero; var infoptr = new IntPtr(&info); - _urlGroup.SetProperty(UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY.HttpServerBindingProperty, + _urlGroup.SetProperty(HttpApi.HTTP_SERVER_PROPERTY.HttpServerBindingProperty, infoptr, (uint)BindingInfoSize, throwOnError: false); } // The listener must be active for this to work. internal unsafe void SetLengthLimit(long length) { - var result = UnsafeNclNativeMethods.HttpApi.HttpSetRequestQueueProperty(Handle, - UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY.HttpServerQueueLengthProperty, + var result = HttpApi.HttpSetRequestQueueProperty(Handle, + HttpApi.HTTP_SERVER_PROPERTY.HttpServerQueueLengthProperty, new IntPtr((void*)&length), (uint)Marshal.SizeOf(), 0, IntPtr.Zero); if (result != 0) diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/ServerSession.cs b/src/Microsoft.Net.Http.Server/NativeInterop/ServerSession.cs index 1640efb500..9c2a0e846e 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/ServerSession.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/ServerSession.cs @@ -25,8 +25,8 @@ namespace Microsoft.Net.Http.Server internal unsafe ServerSession() { ulong serverSessionId = 0; - var statusCode = UnsafeNclNativeMethods.HttpApi.HttpCreateServerSession( - UnsafeNclNativeMethods.HttpApi.Version, &serverSessionId, 0); + var statusCode = HttpApi.HttpCreateServerSession( + HttpApi.Version, &serverSessionId, 0); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/TokenBindingUtil.cs b/src/Microsoft.Net.Http.Server/NativeInterop/TokenBindingUtil.cs index 08aaeb2973..eeeb1ed395 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/TokenBindingUtil.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/TokenBindingUtil.cs @@ -17,7 +17,7 @@ using System; using System.Runtime.InteropServices; -using static Microsoft.Net.Http.Server.UnsafeNclNativeMethods.HttpApi; +using static Microsoft.Net.Http.Server.HttpApi; using static Microsoft.Net.Http.Server.UnsafeNclNativeMethods.TokenBinding; namespace Microsoft.Net.Http.Server diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/UnsafeNativeMethods.cs b/src/Microsoft.Net.Http.Server/NativeInterop/UnsafeNativeMethods.cs index b9e2c71f72..0fd9a632b7 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/UnsafeNativeMethods.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/UnsafeNativeMethods.cs @@ -22,17 +22,13 @@ //------------------------------------------------------------------------------ using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; -using Microsoft.Extensions.Primitives; namespace Microsoft.Net.Http.Server { internal static unsafe class UnsafeNclNativeMethods { - private const string HTTPAPI = "httpapi.dll"; - #if NETSTANDARD1_3 private const string sspicli_LIB = "sspicli.dll"; private const string api_ms_win_core_processthreads_LIB = "api-ms-win-core-processthreads-l1-1-1.dll"; @@ -63,13 +59,6 @@ namespace Microsoft.Net.Http.Server internal const uint ERROR_CONNECTION_INVALID = 1229; } -#if NETSTANDARD1_3 - [DllImport(api_ms_win_core_processthreads_LIB, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] -#else - [DllImport(KERNEL32, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] -#endif - internal static extern uint GetCurrentThreadId(); - #if NETSTANDARD1_3 [DllImport(api_ms_win_core_io_LIB, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] #else @@ -140,13 +129,6 @@ namespace Microsoft.Net.Http.Server [In] ContextAttribute attribute, [In] void* buffer); - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe uint HttpCreateRequestQueue(HttpApi.HTTPAPI_VERSION version, string pName, - Microsoft.Net.Http.Server.UnsafeNclNativeMethods.SECURITY_ATTRIBUTES pSecurityAttributes, uint flags, out HttpRequestQueueV2Handle pReqQueueHandle); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern unsafe uint HttpCloseRequestQueue(IntPtr pReqQueueHandle); - #if NETSTANDARD1_3 [DllImport(api_ms_win_core_handle_LIB, ExactSpelling = true, SetLastError = true)] #else @@ -191,1055 +173,6 @@ namespace Microsoft.Net.Http.Server internal static extern unsafe bool FreeLibrary([In] IntPtr hModule); } - internal static unsafe class HttpApi - { - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpInitialize(HTTPAPI_VERSION version, uint flags, void* pReserved); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpReceiveRequestEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, IntPtr pEntityBuffer, uint entityBufferLength, out uint bytesReturned, SafeNativeOverlapped pOverlapped); - - [DllImport(HTTPAPI, EntryPoint = "HttpReceiveRequestEntityBody", ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpReceiveRequestEntityBody2(SafeHandle requestQueueHandle, ulong requestId, uint flags, void* pEntityBuffer, uint entityBufferLength, out uint bytesReturned, [In] SafeHandle pOverlapped); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, HTTP_SSL_CLIENT_CERT_INFO* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, SafeNativeOverlapped pOverlapped); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, SafeNativeOverlapped pOverlapped); - - [SuppressMessage("Microsoft.Interoperability", "CA1415:DeclarePInvokesCorrectly", Justification = "NativeOverlapped is now wrapped by SafeNativeOverlapped")] - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, SafeNativeOverlapped pOverlapped); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpSendHttpResponse(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE_V2* pHttpResponse, HTTP_CACHE_POLICY* pCachePolicy, uint* pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, SafeNativeOverlapped pOverlapped, IntPtr pLogData); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpSendResponseEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, HTTP_DATA_CHUNK* pEntityChunks, uint* pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, SafeNativeOverlapped pOverlapped, IntPtr pLogData); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpCancelHttpRequest(SafeHandle requestQueueHandle, ulong requestId, IntPtr pOverlapped); - - [DllImport(HTTPAPI, EntryPoint = "HttpSendResponseEntityBody", ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpSendResponseEntityBody2(SafeHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, IntPtr pEntityChunks, out uint pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, SafeHandle pOverlapped, IntPtr pLogData); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpWaitForDisconnectEx(SafeHandle requestQueueHandle, ulong connectionId, uint reserved, SafeNativeOverlapped overlapped); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpCreateServerSession(HTTPAPI_VERSION version, ulong* serverSessionId, uint reserved); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpCreateUrlGroup(ulong serverSessionId, ulong* urlGroupId, uint reserved); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern uint HttpAddUrlToUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, ulong context, uint pReserved); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpSetUrlGroupProperty(ulong urlGroupId, HTTP_SERVER_PROPERTY serverProperty, IntPtr pPropertyInfo, uint propertyInfoLength); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern uint HttpRemoveUrlFromUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, uint flags); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpCloseServerSession(ulong serverSessionId); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpCloseUrlGroup(ulong urlGroupId); - - [DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - internal static extern uint HttpSetRequestQueueProperty(SafeHandle requestQueueHandle, HTTP_SERVER_PROPERTY serverProperty, IntPtr pPropertyInfo, uint propertyInfoLength, uint reserved, IntPtr pReserved); - - internal enum HTTP_API_VERSION - { - Invalid, - Version10, - Version20, - } - - // see http.w for definitions - internal enum HTTP_SERVER_PROPERTY - { - HttpServerAuthenticationProperty, - HttpServerLoggingProperty, - HttpServerQosProperty, - HttpServerTimeoutsProperty, - HttpServerQueueLengthProperty, - HttpServerStateProperty, - HttpServer503VerbosityProperty, - HttpServerBindingProperty, - HttpServerExtendedAuthenticationProperty, - HttpServerListenEndpointProperty, - HttpServerChannelBindProperty, - HttpServerProtectionLevelProperty, - } - - // Currently only one request info type is supported but the enum is for future extensibility. - - internal enum HTTP_REQUEST_INFO_TYPE - { - HttpRequestInfoTypeAuth, - HttpRequestInfoTypeChannelBind, - HttpRequestInfoTypeSslProtocol, - HttpRequestInfoTypeSslTokenBinding - } - - internal enum HTTP_RESPONSE_INFO_TYPE - { - HttpResponseInfoTypeMultipleKnownHeaders, - HttpResponseInfoTypeAuthenticationProperty, - HttpResponseInfoTypeQosProperty, - } - - internal enum HTTP_TIMEOUT_TYPE - { - EntityBody, - DrainEntityBody, - RequestQueue, - IdleConnection, - HeaderWait, - MinSendRate, - } - - internal const int MaxTimeout = 6; - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_VERSION - { - internal ushort MajorVersion; - internal ushort MinorVersion; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_KNOWN_HEADER - { - internal ushort RawValueLength; - internal sbyte* pRawValue; - } - - [StructLayout(LayoutKind.Explicit)] - internal struct HTTP_DATA_CHUNK - { - [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Used natively")] - [FieldOffset(0)] - internal HTTP_DATA_CHUNK_TYPE DataChunkType; - - [FieldOffset(8)] - internal FromMemory fromMemory; - - [FieldOffset(8)] - internal FromFileHandle fromFile; - } - - [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable", - Justification = "This type does not own the native buffer")] - [StructLayout(LayoutKind.Sequential)] - internal struct FromMemory - { - // 4 bytes for 32bit, 8 bytes for 64bit - internal IntPtr pBuffer; - internal uint BufferLength; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FromFileHandle - { - internal ulong offset; - internal ulong count; - internal IntPtr fileHandle; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTPAPI_VERSION - { - internal ushort HttpApiMajorVersion; - internal ushort HttpApiMinorVersion; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_COOKED_URL - { - internal ushort FullUrlLength; - internal ushort HostLength; - internal ushort AbsPathLength; - internal ushort QueryStringLength; - internal ushort* pFullUrl; - internal ushort* pHost; - internal ushort* pAbsPath; - internal ushort* pQueryString; - } - - // Only cache unauthorized GETs + HEADs. - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_CACHE_POLICY - { - internal HTTP_CACHE_POLICY_TYPE Policy; - internal uint SecondsToLive; - } - - internal enum HTTP_CACHE_POLICY_TYPE : int - { - HttpCachePolicyNocache = 0, - HttpCachePolicyUserInvalidates = 1, - HttpCachePolicyTimeToLive = 2, - } - - [StructLayout(LayoutKind.Sequential)] - internal struct SOCKADDR - { - internal ushort sa_family; - internal byte sa_data; - internal byte sa_data_02; - internal byte sa_data_03; - internal byte sa_data_04; - internal byte sa_data_05; - internal byte sa_data_06; - internal byte sa_data_07; - internal byte sa_data_08; - internal byte sa_data_09; - internal byte sa_data_10; - internal byte sa_data_11; - internal byte sa_data_12; - internal byte sa_data_13; - internal byte sa_data_14; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_TRANSPORT_ADDRESS - { - internal SOCKADDR* pRemoteAddress; - internal SOCKADDR* pLocalAddress; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_SSL_CLIENT_CERT_INFO - { - internal uint CertFlags; - internal uint CertEncodedSize; - internal byte* pCertEncoded; - internal void* Token; - internal byte CertDeniedByMapper; - } - - internal enum HTTP_SERVICE_BINDING_TYPE : uint - { - HttpServiceBindingTypeNone = 0, - HttpServiceBindingTypeW, - HttpServiceBindingTypeA - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_SERVICE_BINDING_BASE - { - internal HTTP_SERVICE_BINDING_TYPE Type; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_REQUEST_CHANNEL_BIND_STATUS - { - internal IntPtr ServiceName; - internal IntPtr ChannelToken; - internal uint ChannelTokenSize; - internal uint Flags; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_UNKNOWN_HEADER - { - internal ushort NameLength; - internal ushort RawValueLength; - internal sbyte* pName; - internal sbyte* pRawValue; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_SSL_INFO - { - internal ushort ServerCertKeySize; - internal ushort ConnectionKeySize; - internal uint ServerCertIssuerSize; - internal uint ServerCertSubjectSize; - internal sbyte* pServerCertIssuer; - internal sbyte* pServerCertSubject; - internal HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo; - internal uint SslClientCertNegotiated; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_RESPONSE_HEADERS - { - internal ushort UnknownHeaderCount; - internal HTTP_UNKNOWN_HEADER* pUnknownHeaders; - internal ushort TrailerCount; - internal HTTP_UNKNOWN_HEADER* pTrailers; - internal HTTP_KNOWN_HEADER KnownHeaders; - internal HTTP_KNOWN_HEADER KnownHeaders_02; - internal HTTP_KNOWN_HEADER KnownHeaders_03; - internal HTTP_KNOWN_HEADER KnownHeaders_04; - internal HTTP_KNOWN_HEADER KnownHeaders_05; - internal HTTP_KNOWN_HEADER KnownHeaders_06; - internal HTTP_KNOWN_HEADER KnownHeaders_07; - internal HTTP_KNOWN_HEADER KnownHeaders_08; - internal HTTP_KNOWN_HEADER KnownHeaders_09; - internal HTTP_KNOWN_HEADER KnownHeaders_10; - internal HTTP_KNOWN_HEADER KnownHeaders_11; - internal HTTP_KNOWN_HEADER KnownHeaders_12; - internal HTTP_KNOWN_HEADER KnownHeaders_13; - internal HTTP_KNOWN_HEADER KnownHeaders_14; - internal HTTP_KNOWN_HEADER KnownHeaders_15; - internal HTTP_KNOWN_HEADER KnownHeaders_16; - internal HTTP_KNOWN_HEADER KnownHeaders_17; - internal HTTP_KNOWN_HEADER KnownHeaders_18; - internal HTTP_KNOWN_HEADER KnownHeaders_19; - internal HTTP_KNOWN_HEADER KnownHeaders_20; - internal HTTP_KNOWN_HEADER KnownHeaders_21; - internal HTTP_KNOWN_HEADER KnownHeaders_22; - internal HTTP_KNOWN_HEADER KnownHeaders_23; - internal HTTP_KNOWN_HEADER KnownHeaders_24; - internal HTTP_KNOWN_HEADER KnownHeaders_25; - internal HTTP_KNOWN_HEADER KnownHeaders_26; - internal HTTP_KNOWN_HEADER KnownHeaders_27; - internal HTTP_KNOWN_HEADER KnownHeaders_28; - internal HTTP_KNOWN_HEADER KnownHeaders_29; - internal HTTP_KNOWN_HEADER KnownHeaders_30; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_REQUEST_HEADERS - { - internal ushort UnknownHeaderCount; - internal HTTP_UNKNOWN_HEADER* pUnknownHeaders; - internal ushort TrailerCount; - internal HTTP_UNKNOWN_HEADER* pTrailers; - internal HTTP_KNOWN_HEADER KnownHeaders; - internal HTTP_KNOWN_HEADER KnownHeaders_02; - internal HTTP_KNOWN_HEADER KnownHeaders_03; - internal HTTP_KNOWN_HEADER KnownHeaders_04; - internal HTTP_KNOWN_HEADER KnownHeaders_05; - internal HTTP_KNOWN_HEADER KnownHeaders_06; - internal HTTP_KNOWN_HEADER KnownHeaders_07; - internal HTTP_KNOWN_HEADER KnownHeaders_08; - internal HTTP_KNOWN_HEADER KnownHeaders_09; - internal HTTP_KNOWN_HEADER KnownHeaders_10; - internal HTTP_KNOWN_HEADER KnownHeaders_11; - internal HTTP_KNOWN_HEADER KnownHeaders_12; - internal HTTP_KNOWN_HEADER KnownHeaders_13; - internal HTTP_KNOWN_HEADER KnownHeaders_14; - internal HTTP_KNOWN_HEADER KnownHeaders_15; - internal HTTP_KNOWN_HEADER KnownHeaders_16; - internal HTTP_KNOWN_HEADER KnownHeaders_17; - internal HTTP_KNOWN_HEADER KnownHeaders_18; - internal HTTP_KNOWN_HEADER KnownHeaders_19; - internal HTTP_KNOWN_HEADER KnownHeaders_20; - internal HTTP_KNOWN_HEADER KnownHeaders_21; - internal HTTP_KNOWN_HEADER KnownHeaders_22; - internal HTTP_KNOWN_HEADER KnownHeaders_23; - internal HTTP_KNOWN_HEADER KnownHeaders_24; - internal HTTP_KNOWN_HEADER KnownHeaders_25; - internal HTTP_KNOWN_HEADER KnownHeaders_26; - internal HTTP_KNOWN_HEADER KnownHeaders_27; - internal HTTP_KNOWN_HEADER KnownHeaders_28; - internal HTTP_KNOWN_HEADER KnownHeaders_29; - internal HTTP_KNOWN_HEADER KnownHeaders_30; - internal HTTP_KNOWN_HEADER KnownHeaders_31; - internal HTTP_KNOWN_HEADER KnownHeaders_32; - internal HTTP_KNOWN_HEADER KnownHeaders_33; - internal HTTP_KNOWN_HEADER KnownHeaders_34; - internal HTTP_KNOWN_HEADER KnownHeaders_35; - internal HTTP_KNOWN_HEADER KnownHeaders_36; - internal HTTP_KNOWN_HEADER KnownHeaders_37; - internal HTTP_KNOWN_HEADER KnownHeaders_38; - internal HTTP_KNOWN_HEADER KnownHeaders_39; - internal HTTP_KNOWN_HEADER KnownHeaders_40; - internal HTTP_KNOWN_HEADER KnownHeaders_41; - } - - internal enum HTTP_VERB : int - { - HttpVerbUnparsed = 0, - HttpVerbUnknown = 1, - HttpVerbInvalid = 2, - HttpVerbOPTIONS = 3, - HttpVerbGET = 4, - HttpVerbHEAD = 5, - HttpVerbPOST = 6, - HttpVerbPUT = 7, - HttpVerbDELETE = 8, - HttpVerbTRACE = 9, - HttpVerbCONNECT = 10, - HttpVerbTRACK = 11, - HttpVerbMOVE = 12, - HttpVerbCOPY = 13, - HttpVerbPROPFIND = 14, - HttpVerbPROPPATCH = 15, - HttpVerbMKCOL = 16, - HttpVerbLOCK = 17, - HttpVerbUNLOCK = 18, - HttpVerbSEARCH = 19, - HttpVerbMaximum = 20, - } - - internal static readonly string[] HttpVerbs = new string[] - { - null, - "Unknown", - "Invalid", - "OPTIONS", - "GET", - "HEAD", - "POST", - "PUT", - "DELETE", - "TRACE", - "CONNECT", - "TRACK", - "MOVE", - "COPY", - "PROPFIND", - "PROPPATCH", - "MKCOL", - "LOCK", - "UNLOCK", - "SEARCH", - }; - - internal enum HTTP_DATA_CHUNK_TYPE : int - { - HttpDataChunkFromMemory = 0, - HttpDataChunkFromFileHandle = 1, - HttpDataChunkFromFragmentCache = 2, - HttpDataChunkMaximum = 3, - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_RESPONSE_INFO - { - internal HTTP_RESPONSE_INFO_TYPE Type; - internal uint Length; - internal HTTP_MULTIPLE_KNOWN_HEADERS* pInfo; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_RESPONSE - { - internal uint Flags; - internal HTTP_VERSION Version; - internal ushort StatusCode; - internal ushort ReasonLength; - internal sbyte* pReason; - internal HTTP_RESPONSE_HEADERS Headers; - internal ushort EntityChunkCount; - internal HTTP_DATA_CHUNK* pEntityChunks; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_RESPONSE_V2 - { - internal HTTP_RESPONSE Response_V1; - internal ushort ResponseInfoCount; - internal HTTP_RESPONSE_INFO* pResponseInfo; - } - - internal enum HTTP_RESPONSE_INFO_FLAGS : uint - { - None = 0, - PreserveOrder = 1, - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_MULTIPLE_KNOWN_HEADERS - { - internal HTTP_RESPONSE_HEADER_ID.Enum HeaderId; - internal HTTP_RESPONSE_INFO_FLAGS Flags; - internal ushort KnownHeaderCount; - internal HTTP_KNOWN_HEADER* KnownHeaders; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_REQUEST_AUTH_INFO - { - internal HTTP_AUTH_STATUS AuthStatus; - internal uint SecStatus; - internal uint Flags; - internal HTTP_REQUEST_AUTH_TYPE AuthType; - internal IntPtr AccessToken; - internal uint ContextAttributes; - internal uint PackedContextLength; - internal uint PackedContextType; - internal IntPtr PackedContext; - internal uint MutualAuthDataLength; - internal char* pMutualAuthData; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_REQUEST_INFO - { - internal HTTP_REQUEST_INFO_TYPE InfoType; - internal uint InfoLength; - internal HTTP_REQUEST_AUTH_INFO* pInfo; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_REQUEST - { - internal uint Flags; - internal ulong ConnectionId; - internal ulong RequestId; - internal ulong UrlContext; - internal HTTP_VERSION Version; - internal HTTP_VERB Verb; - internal ushort UnknownVerbLength; - internal ushort RawUrlLength; - internal sbyte* pUnknownVerb; - internal sbyte* pRawUrl; - internal HTTP_COOKED_URL CookedUrl; - internal HTTP_TRANSPORT_ADDRESS Address; - internal HTTP_REQUEST_HEADERS Headers; - internal ulong BytesReceived; - internal ushort EntityChunkCount; - internal HTTP_DATA_CHUNK* pEntityChunks; - internal ulong RawConnectionId; - internal HTTP_SSL_INFO* pSslInfo; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_REQUEST_V2 - { - internal HTTP_REQUEST Request; - internal ushort RequestInfoCount; - internal HTTP_REQUEST_INFO* pRequestInfo; - } - - internal enum HTTP_AUTH_STATUS - { - HttpAuthStatusSuccess, - HttpAuthStatusNotAuthenticated, - HttpAuthStatusFailure, - } - - internal enum HTTP_REQUEST_AUTH_TYPE - { - HttpRequestAuthTypeNone = 0, - HttpRequestAuthTypeBasic, - HttpRequestAuthTypeDigest, - HttpRequestAuthTypeNTLM, - HttpRequestAuthTypeNegotiate, - HttpRequestAuthTypeKerberos - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_SERVER_AUTHENTICATION_INFO - { - internal HTTP_FLAGS Flags; - internal HTTP_AUTH_TYPES AuthSchemes; - internal bool ReceiveMutualAuth; - internal bool ReceiveContextHandle; - internal bool DisableNTLMCredentialCaching; - internal ulong ExFlags; - HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS DigestParams; - HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS BasicParams; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS - { - internal ushort DomainNameLength; - internal char* DomainName; - internal ushort RealmLength; - internal char* Realm; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS - { - ushort RealmLength; - char* Realm; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_REQUEST_TOKEN_BINDING_INFO - { - public byte* TokenBinding; - public uint TokenBindingSize; - - public byte* TlsUnique; - public uint TlsUniqueSize; - - public char* KeyType; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_TIMEOUT_LIMIT_INFO - { - internal HTTP_FLAGS Flags; - internal ushort EntityBody; - internal ushort DrainEntityBody; - internal ushort RequestQueue; - internal ushort IdleConnection; - internal ushort HeaderWait; - internal uint MinSendRate; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct HTTP_BINDING_INFO - { - internal HTTP_FLAGS Flags; - internal IntPtr RequestQueueHandle; - } - - // see http.w for definitions - [Flags] - internal enum HTTP_FLAGS : uint - { - NONE = 0x00000000, - HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY = 0x00000001, - HTTP_RECEIVE_SECURE_CHANNEL_TOKEN = 0x00000001, - HTTP_SEND_RESPONSE_FLAG_DISCONNECT = 0x00000001, - HTTP_SEND_RESPONSE_FLAG_MORE_DATA = 0x00000002, - HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA = 0x00000004, - HTTP_SEND_RESPONSE_FLAG_RAW_HEADER = 0x00000004, - HTTP_SEND_REQUEST_FLAG_MORE_DATA = 0x00000001, - HTTP_PROPERTY_FLAG_PRESENT = 0x00000001, - HTTP_INITIALIZE_SERVER = 0x00000001, - HTTP_INITIALIZE_CBT = 0x00000004, - HTTP_SEND_RESPONSE_FLAG_OPAQUE = 0x00000040, - } - - [Flags] - internal enum HTTP_AUTH_TYPES : uint - { - NONE = 0x00000000, - HTTP_AUTH_ENABLE_BASIC = 0x00000001, - HTTP_AUTH_ENABLE_DIGEST = 0x00000002, - HTTP_AUTH_ENABLE_NTLM = 0x00000004, - HTTP_AUTH_ENABLE_NEGOTIATE = 0x00000008, - HTTP_AUTH_ENABLE_KERBEROS = 0x00000010, - } - - private const int HttpHeaderRequestMaximum = (int)HttpSysRequestHeader.UserAgent + 1; - private const int HttpHeaderResponseMaximum = (int)HttpSysResponseHeader.WwwAuthenticate + 1; - - internal static class HTTP_REQUEST_HEADER_ID - { - internal static string ToString(int position) - { - return _strings[position]; - } - - private static string[] _strings = - { - "Cache-Control", - "Connection", - "Date", - "Keep-Alive", - "Pragma", - "Trailer", - "Transfer-Encoding", - "Upgrade", - "Via", - "Warning", - - "Allow", - "Content-Length", - "Content-Type", - "Content-Encoding", - "Content-Language", - "Content-Location", - "Content-MD5", - "Content-Range", - "Expires", - "Last-Modified", - - "Accept", - "Accept-Charset", - "Accept-Encoding", - "Accept-Language", - "Authorization", - "Cookie", - "Expect", - "From", - "Host", - "If-Match", - - "If-Modified-Since", - "If-None-Match", - "If-Range", - "If-Unmodified-Since", - "Max-Forwards", - "Proxy-Authorization", - "Referer", - "Range", - "Te", - "Translate", - "User-Agent", - }; - } - - internal static class HTTP_RESPONSE_HEADER_ID - { - private static string[] _strings = - { - "Cache-Control", - "Connection", - "Date", - "Keep-Alive", - "Pragma", - "Trailer", - "Transfer-Encoding", - "Upgrade", - "Via", - "Warning", - - "Allow", - "Content-Length", - "Content-Type", - "Content-Encoding", - "Content-Language", - "Content-Location", - "Content-MD5", - "Content-Range", - "Expires", - "Last-Modified", - - "Accept-Ranges", - "Age", - "ETag", - "Location", - "Proxy-Authenticate", - "Retry-After", - "Server", - "Set-Cookie", - "Vary", - "WWW-Authenticate", - }; - - private static Dictionary _lookupTable = CreateLookupTable(); - - private static Dictionary CreateLookupTable() - { - Dictionary lookupTable = new Dictionary((int)Enum.HttpHeaderResponseMaximum, StringComparer.OrdinalIgnoreCase); - for (int i = 0; i < (int)Enum.HttpHeaderResponseMaximum; i++) - { - lookupTable.Add(_strings[i], i); - } - return lookupTable; - } - - internal static int IndexOfKnownHeader(string HeaderName) - { - int index; - return _lookupTable.TryGetValue(HeaderName, out index) ? index : -1; - } - - internal static string ToString(int position) - { - return _strings[position]; - } - - internal enum Enum - { - HttpHeaderCacheControl = 0, // general-header [section 4.5] - HttpHeaderConnection = 1, // general-header [section 4.5] - HttpHeaderDate = 2, // general-header [section 4.5] - HttpHeaderKeepAlive = 3, // general-header [not in rfc] - HttpHeaderPragma = 4, // general-header [section 4.5] - HttpHeaderTrailer = 5, // general-header [section 4.5] - HttpHeaderTransferEncoding = 6, // general-header [section 4.5] - HttpHeaderUpgrade = 7, // general-header [section 4.5] - HttpHeaderVia = 8, // general-header [section 4.5] - HttpHeaderWarning = 9, // general-header [section 4.5] - - HttpHeaderAllow = 10, // entity-header [section 7.1] - HttpHeaderContentLength = 11, // entity-header [section 7.1] - HttpHeaderContentType = 12, // entity-header [section 7.1] - HttpHeaderContentEncoding = 13, // entity-header [section 7.1] - HttpHeaderContentLanguage = 14, // entity-header [section 7.1] - HttpHeaderContentLocation = 15, // entity-header [section 7.1] - HttpHeaderContentMd5 = 16, // entity-header [section 7.1] - HttpHeaderContentRange = 17, // entity-header [section 7.1] - HttpHeaderExpires = 18, // entity-header [section 7.1] - HttpHeaderLastModified = 19, // entity-header [section 7.1] - - // Response Headers - - HttpHeaderAcceptRanges = 20, // response-header [section 6.2] - HttpHeaderAge = 21, // response-header [section 6.2] - HttpHeaderEtag = 22, // response-header [section 6.2] - HttpHeaderLocation = 23, // response-header [section 6.2] - HttpHeaderProxyAuthenticate = 24, // response-header [section 6.2] - HttpHeaderRetryAfter = 25, // response-header [section 6.2] - HttpHeaderServer = 26, // response-header [section 6.2] - HttpHeaderSetCookie = 27, // response-header [not in rfc] - HttpHeaderVary = 28, // response-header [section 6.2] - HttpHeaderWwwAuthenticate = 29, // response-header [section 6.2] - - HttpHeaderResponseMaximum = 30, - - HttpHeaderMaximum = 41 - } - } - - private static HTTPAPI_VERSION version; - - // This property is used by HttpListener to pass the version structure to the native layer in API - // calls. - - internal static HTTPAPI_VERSION Version - { - get - { - return version; - } - } - - // This property is used by HttpListener to get the Api version in use so that it uses appropriate - // Http APIs. - - internal static HTTP_API_VERSION ApiVersion - { - get - { - if (version.HttpApiMajorVersion == 2 && version.HttpApiMinorVersion == 0) - { - return HTTP_API_VERSION.Version20; - } - else if (version.HttpApiMajorVersion == 1 && version.HttpApiMinorVersion == 0) - { - return HTTP_API_VERSION.Version10; - } - else - { - return HTTP_API_VERSION.Invalid; - } - } - } - - static HttpApi() - { - InitHttpApi(2, 0); - } - - private static void InitHttpApi(ushort majorVersion, ushort minorVersion) - { - version.HttpApiMajorVersion = majorVersion; - version.HttpApiMinorVersion = minorVersion; - - var statusCode = HttpApi.HttpInitialize(version, (uint)HTTP_FLAGS.HTTP_INITIALIZE_SERVER, null); - - supported = statusCode == ErrorCodes.ERROR_SUCCESS; - } - - private static volatile bool supported; - internal static bool Supported - { - get - { - return supported; - } - } - - // Server API - - internal static void GetUnknownHeaders(IDictionary unknownHeaders, byte[] memoryBlob, - int requestOffset, IntPtr originalAddress) - { - // Return value. - fixed (byte* pMemoryBlob = memoryBlob) - { - HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset); - long fixup = pMemoryBlob - (byte*)originalAddress; - int index; - - // unknown headers - if (request->Headers.UnknownHeaderCount != 0) - { - HTTP_UNKNOWN_HEADER* pUnknownHeader = (HTTP_UNKNOWN_HEADER*)(fixup + (byte*)request->Headers.pUnknownHeaders); - for (index = 0; index < request->Headers.UnknownHeaderCount; index++) - { - // For unknown headers, when header value is empty, RawValueLength will be 0 and - // pRawValue will be null. - if (pUnknownHeader->pName != null && pUnknownHeader->NameLength > 0) - { - string headerName = HeaderEncoding.GetString(pUnknownHeader->pName + fixup, pUnknownHeader->NameLength); - string headerValue; - if (pUnknownHeader->pRawValue != null && pUnknownHeader->RawValueLength > 0) - { - headerValue = HeaderEncoding.GetString(pUnknownHeader->pRawValue + fixup, pUnknownHeader->RawValueLength); - } - else - { - headerValue = string.Empty; - } - // Note that Http.Sys currently collapses all headers of the same name to a single coma seperated string, - // so we can just call Set. - unknownHeaders[headerName] = headerValue; - } - pUnknownHeader++; - } - } - } - } - - private static string GetKnownHeader(HTTP_REQUEST* request, long fixup, int headerIndex) - { - string header = null; - - HTTP_KNOWN_HEADER* pKnownHeader = (&request->Headers.KnownHeaders) + headerIndex; - // For known headers, when header value is empty, RawValueLength will be 0 and - // pRawValue will point to empty string ("\0") - if (pKnownHeader->pRawValue != null) - { - header = HeaderEncoding.GetString(pKnownHeader->pRawValue + fixup, pKnownHeader->RawValueLength); - } - - return header; - } - - internal static string GetKnownHeader(byte[] memoryBlob, int requestOffset, IntPtr originalAddress, int headerIndex) - { - fixed (byte* pMemoryBlob = memoryBlob) - { - return GetKnownHeader( - (HTTP_REQUEST*)(pMemoryBlob + requestOffset), pMemoryBlob - (byte*)originalAddress, headerIndex); - } - } - - // This requires the HTTP_REQUEST to still be pinned in its original location. - internal static unsafe string GetVerb(HTTP_REQUEST* request) - { - string verb = null; - - if ((int)request->Verb > (int)HTTP_VERB.HttpVerbUnknown && (int)request->Verb < (int)HTTP_VERB.HttpVerbMaximum) - { - verb = HttpVerbs[(int)request->Verb]; - } - else if (request->Verb == HTTP_VERB.HttpVerbUnknown && request->pUnknownVerb != null) - { - verb = HeaderEncoding.GetString(request->pUnknownVerb, request->UnknownVerbLength); - } - - return verb; - } - - internal static uint GetChunks(byte[] memoryBlob, int requestOffset, IntPtr originalAddress, - ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size) - { - // Return value. - uint dataRead = 0; - fixed (byte* pMemoryBlob = memoryBlob) - { - HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset); - long fixup = pMemoryBlob - (byte*)originalAddress; - - if (request->EntityChunkCount > 0 && dataChunkIndex < request->EntityChunkCount && dataChunkIndex != -1) - { - HTTP_DATA_CHUNK* pDataChunk = (HTTP_DATA_CHUNK*)(fixup + (byte*)&request->pEntityChunks[dataChunkIndex]); - - fixed (byte* pReadBuffer = buffer) - { - byte* pTo = &pReadBuffer[offset]; - - while (dataChunkIndex < request->EntityChunkCount && dataRead < size) - { - if (dataChunkOffset >= pDataChunk->fromMemory.BufferLength) - { - dataChunkOffset = 0; - dataChunkIndex++; - pDataChunk++; - } - else - { - byte* pFrom = (byte*)pDataChunk->fromMemory.pBuffer + dataChunkOffset + fixup; - - uint bytesToRead = pDataChunk->fromMemory.BufferLength - (uint)dataChunkOffset; - if (bytesToRead > (uint)size) - { - bytesToRead = (uint)size; - } - for (uint i = 0; i < bytesToRead; i++) - { - *(pTo++) = *(pFrom++); - } - dataRead += bytesToRead; - dataChunkOffset += bytesToRead; - } - } - } - } - // we're finished. - if (dataChunkIndex == request->EntityChunkCount) - { - dataChunkIndex = -1; - } - } - - return dataRead; - } - - internal static SocketAddress GetRemoteEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress) - { - fixed (byte* pMemoryBlob = memoryBlob) - { - HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset); - return GetEndPoint(memoryBlob, requestOffset, originalAddress, (byte*)request->Address.pRemoteAddress); - } - } - - internal static SocketAddress GetLocalEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress) - { - fixed (byte* pMemoryBlob = memoryBlob) - { - HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset); - return GetEndPoint(memoryBlob, requestOffset, originalAddress, (byte*)request->Address.pLocalAddress); - } - } - - internal static SocketAddress GetEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress, byte* source) - { - fixed (byte* pMemoryBlob = memoryBlob) - { - IntPtr address = source != null ? - (IntPtr)(pMemoryBlob + requestOffset - (byte*)originalAddress + source) : IntPtr.Zero; - return CopyOutAddress(address); - } - } - - private static SocketAddress CopyOutAddress(IntPtr address) - { - if (address != IntPtr.Zero) - { - ushort addressFamily = *((ushort*)address); - if (addressFamily == (ushort)AddressFamily.InterNetwork) - { - SocketAddress v4address = new SocketAddress(AddressFamily.InterNetwork, SocketAddress.IPv4AddressSize); - fixed (byte* pBuffer = v4address.Buffer) - { - for (int index = 2; index < SocketAddress.IPv4AddressSize; index++) - { - pBuffer[index] = ((byte*)address)[index]; - } - } - return v4address; - } - if (addressFamily == (ushort)AddressFamily.InterNetworkV6) - { - SocketAddress v6address = new SocketAddress(AddressFamily.InterNetworkV6, SocketAddress.IPv6AddressSize); - fixed (byte* pBuffer = v6address.Buffer) - { - for (int index = 2; index < SocketAddress.IPv6AddressSize; index++) - { - pBuffer[index] = ((byte*)address)[index]; - } - } - return v6address; - } - } - - return null; - } - } - // from tokenbinding.h internal static class TokenBinding { diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/UrlGroup.cs b/src/Microsoft.Net.Http.Server/NativeInterop/UrlGroup.cs index cb4af099df..385c7c61fa 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/UrlGroup.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/UrlGroup.cs @@ -33,7 +33,7 @@ namespace Microsoft.Net.Http.Server _logger = logger; ulong urlGroupId = 0; - var statusCode = UnsafeNclNativeMethods.HttpApi.HttpCreateUrlGroup( + var statusCode = HttpApi.HttpCreateUrlGroup( _serverSession.Id.DangerousGetServerSessionId(), &urlGroupId, 0); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) @@ -47,11 +47,11 @@ namespace Microsoft.Net.Http.Server internal ulong Id { get; private set; } - internal void SetProperty(UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize, bool throwOnError = true) + internal void SetProperty(HttpApi.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize, bool throwOnError = true) { Debug.Assert(info != IntPtr.Zero, "SetUrlGroupProperty called with invalid pointer"); - var statusCode = UnsafeNclNativeMethods.HttpApi.HttpSetUrlGroupProperty(Id, property, info, infosize); + var statusCode = HttpApi.HttpSetUrlGroupProperty(Id, property, info, infosize); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { @@ -68,7 +68,7 @@ namespace Microsoft.Net.Http.Server { LogHelper.LogInfo(_logger, "Listening on prefix: " + uriPrefix); - var statusCode = UnsafeNclNativeMethods.HttpApi.HttpAddUrlToUrlGroup(Id, uriPrefix, (ulong)contextId, 0); + var statusCode = HttpApi.HttpAddUrlToUrlGroup(Id, uriPrefix, (ulong)contextId, 0); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { @@ -87,7 +87,7 @@ namespace Microsoft.Net.Http.Server { LogHelper.LogInfo(_logger, "Stop listening on prefix: " + uriPrefix); - var statusCode = UnsafeNclNativeMethods.HttpApi.HttpRemoveUrlFromUrlGroup(Id, uriPrefix, 0); + var statusCode = HttpApi.HttpRemoveUrlFromUrlGroup(Id, uriPrefix, 0); if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_NOT_FOUND) { @@ -107,7 +107,7 @@ namespace Microsoft.Net.Http.Server Debug.Assert(Id != 0, "HttpCloseUrlGroup called with invalid url group id"); - uint statusCode = UnsafeNclNativeMethods.HttpApi.HttpCloseUrlGroup(Id); + uint statusCode = HttpApi.HttpCloseUrlGroup(Id); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/ClientCertLoader.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/ClientCertLoader.cs index 63df5bdc89..f3c60389bb 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/ClientCertLoader.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/ClientCertLoader.cs @@ -43,11 +43,11 @@ namespace Microsoft.Net.Http.Server private const uint CertBoblSize = 1500; private static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(WaitCallback); private static readonly int RequestChannelBindStatusSize = - Marshal.SizeOf(); + Marshal.SizeOf(); private SafeNativeOverlapped _overlapped; private byte[] _backingBuffer; - private UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* _memoryBlob; + private HttpApi.HTTP_SSL_CLIENT_CERT_INFO* _memoryBlob; private uint _size; private TaskCompletionSource _tcs; private RequestContext _requestContext; @@ -124,7 +124,7 @@ namespace Microsoft.Net.Http.Server } } - private UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* RequestBlob + private HttpApi.HTTP_SSL_CLIENT_CERT_INFO* RequestBlob { get { @@ -154,7 +154,7 @@ namespace Microsoft.Net.Http.Server var boundHandle = RequestContext.Server.RequestQueue.BoundHandle; _overlapped = new SafeNativeOverlapped(boundHandle, boundHandle.AllocateNativeOverlapped(IOCallback, this, _backingBuffer)); - _memoryBlob = (UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO*)Marshal.UnsafeAddrOfPinnedArrayElement(_backingBuffer, 0); + _memoryBlob = (HttpApi.HTTP_SSL_CLIENT_CERT_INFO*)Marshal.UnsafeAddrOfPinnedArrayElement(_backingBuffer, 0); } // When you use netsh to configure HTTP.SYS with clientcertnegotiation = enable @@ -185,10 +185,10 @@ namespace Microsoft.Net.Http.Server uint bytesReceived = 0; uint statusCode = - UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate( + HttpApi.HttpReceiveClientCertificate( RequestQueueHandle, RequestContext.Request.UConnectionId, - (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE, + (uint)HttpApi.HTTP_FLAGS.NONE, RequestBlob, size, &bytesReceived, @@ -196,7 +196,7 @@ namespace Microsoft.Net.Http.Server if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA) { - UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = RequestBlob; + HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = RequestBlob; size = bytesReceived + pClientCertInfo->CertEncodedSize; Reset(size); retry = true; @@ -259,15 +259,15 @@ namespace Microsoft.Net.Http.Server // return the size of the initial cert structure. To get the full size, // we need to add the certificate encoding size as well. - UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult.RequestBlob; + HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult.RequestBlob; asyncResult.Reset(numBytes + pClientCertInfo->CertEncodedSize); uint bytesReceived = 0; errorCode = - UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate( + HttpApi.HttpReceiveClientCertificate( requestContext.Server.RequestQueue.Handle, requestContext.Request.UConnectionId, - (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE, + (uint)HttpApi.HTTP_FLAGS.NONE, asyncResult._memoryBlob, asyncResult._size, &bytesReceived, @@ -291,7 +291,7 @@ namespace Microsoft.Net.Http.Server } else { - UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult._memoryBlob; + HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult._memoryBlob; if (pClientCertInfo == null) { asyncResult.Complete(0, null); @@ -391,10 +391,10 @@ namespace Microsoft.Net.Http.Server { // Http.sys team: ServiceName will always be null if // HTTP_RECEIVE_SECURE_CHANNEL_TOKEN flag is set. - statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate( + statusCode = HttpApi.HttpReceiveClientCertificate( requestQueue.Handle, connectionId, - (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_SECURE_CHANNEL_TOKEN, + (uint)HttpApi.HTTP_FLAGS.HTTP_RECEIVE_SECURE_CHANNEL_TOKEN, blobPtr, (uint)size, &bytesReceived, @@ -438,7 +438,7 @@ namespace Microsoft.Net.Http.Server private static int GetTokenOffsetFromBlob(IntPtr blob) { Debug.Assert(blob != IntPtr.Zero); - IntPtr tokenPointer = Marshal.ReadIntPtr(blob, (int)Marshal.OffsetOf("ChannelToken")); + IntPtr tokenPointer = Marshal.ReadIntPtr(blob, (int)Marshal.OffsetOf("ChannelToken")); Debug.Assert(tokenPointer != IntPtr.Zero); return (int)IntPtrHelper.Subtract(tokenPointer, blob); } @@ -446,7 +446,7 @@ namespace Microsoft.Net.Http.Server private static int GetTokenSizeFromBlob(IntPtr blob) { Debug.Assert(blob != IntPtr.Zero); - return Marshal.ReadInt32(blob, (int)Marshal.OffsetOf("ChannelTokenSize")); + return Marshal.ReadInt32(blob, (int)Marshal.OffsetOf("ChannelTokenSize")); } } } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/NativeRequestContext.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/NativeRequestContext.cs index 49355872f6..5072342c42 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/NativeRequestContext.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/NativeRequestContext.cs @@ -32,7 +32,7 @@ namespace Microsoft.Net.Http.Server { private const int DefaultBufferSize = 4096; private const int AlignmentPadding = 8; - private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* _memoryBlob; + private HttpApi.HTTP_REQUEST* _memoryBlob; private IntPtr _originalBlobAddress; private byte[] _backingBuffer; private int _bufferAlignment; @@ -42,7 +42,7 @@ namespace Microsoft.Net.Http.Server internal NativeRequestContext(AsyncAcceptContext result) { _acceptResult = result; - UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* requestBlob = Allocate(0); + HttpApi.HTTP_REQUEST* requestBlob = Allocate(0); if (requestBlob == null) { GC.SuppressFinalize(this); @@ -61,7 +61,7 @@ namespace Microsoft.Net.Http.Server } } - internal UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* RequestBlob + internal HttpApi.HTTP_REQUEST* RequestBlob { get { @@ -98,7 +98,7 @@ namespace Microsoft.Net.Http.Server { get { - UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* blob = _memoryBlob; + HttpApi.HTTP_REQUEST* blob = _memoryBlob; return blob == null ? _originalBlobAddress : (IntPtr)blob; } } @@ -138,7 +138,7 @@ namespace Microsoft.Net.Http.Server } } - private void SetBlob(UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* requestBlob) + private void SetBlob(HttpApi.HTTP_REQUEST* requestBlob) { Debug.Assert(_memoryBlob != null || _backingBuffer == null, "RequestContextBase::Dispose()|SetBlob() called after ReleasePins()."); if (requestBlob == null) @@ -170,7 +170,7 @@ namespace Microsoft.Net.Http.Server _backingBuffer = new byte[size + AlignmentPadding]; } - private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* Allocate(uint size) + private HttpApi.HTTP_REQUEST* Allocate(uint size) { // We can't reuse overlapped objects if (_nativeOverlapped != null) @@ -191,7 +191,7 @@ namespace Microsoft.Net.Http.Server var requestAddress = Marshal.UnsafeAddrOfPinnedArrayElement(RequestBuffer, 0); _bufferAlignment = (int)(requestAddress.ToInt64() & 0x07); - return (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST*)(requestAddress + _bufferAlignment); + return (HttpApi.HTTP_REQUEST*)(requestAddress + _bufferAlignment); } internal void Reset(ulong requestId, uint size) diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/Request.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/Request.cs index f812891410..0d46ac9f77 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/Request.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/Request.cs @@ -68,7 +68,7 @@ namespace Microsoft.Net.Http.Server RawUrl = Marshal.PtrToStringAnsi((IntPtr)memoryBlob.RequestBlob->pRawUrl, memoryBlob.RequestBlob->RawUrlLength); } - UnsafeNclNativeMethods.HttpApi.HTTP_COOKED_URL cookedUrl = memoryBlob.RequestBlob->CookedUrl; + HttpApi.HTTP_COOKED_URL cookedUrl = memoryBlob.RequestBlob->CookedUrl; if (cookedUrl.pHost != null && cookedUrl.HostLength > 0) { // TODO: Unused @@ -119,10 +119,10 @@ namespace Microsoft.Net.Http.Server } KnownMethod = memoryBlob.RequestBlob->Verb; - Method = UnsafeNclNativeMethods.HttpApi.GetVerb(memoryBlob.RequestBlob); + Method = HttpApi.GetVerb(memoryBlob.RequestBlob); Headers = new HeaderCollection(new RequestHeaders(_nativeRequestContext)); - var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)memoryBlob.RequestBlob; + var requestV2 = (HttpApi.HTTP_REQUEST_V2*)memoryBlob.RequestBlob; User = AuthenticationManager.GetUser(requestV2->pRequestInfo, requestV2->RequestInfoCount); GetTlsTokenBindingInfo(); @@ -207,9 +207,9 @@ namespace Microsoft.Net.Http.Server public HeaderCollection Headers { get; } - internal UnsafeNclNativeMethods.HttpApi.HTTP_VERB KnownMethod { get; } + internal HttpApi.HTTP_VERB KnownMethod { get; } - public bool IsHeadMethod => KnownMethod == UnsafeNclNativeMethods.HttpApi.HTTP_VERB.HttpVerbHEAD; + public bool IsHeadMethod => KnownMethod == HttpApi.HTTP_VERB.HttpVerbHEAD; public string Method { get; } @@ -251,7 +251,7 @@ namespace Microsoft.Net.Http.Server { if (_remoteEndPoint == null) { - _remoteEndPoint = UnsafeNclNativeMethods.HttpApi.GetRemoteEndPoint(RequestBuffer, BufferAlignment, OriginalBlobAddress); + _remoteEndPoint = HttpApi.GetRemoteEndPoint(RequestBuffer, BufferAlignment, OriginalBlobAddress); } return _remoteEndPoint; @@ -264,7 +264,7 @@ namespace Microsoft.Net.Http.Server { if (_localEndPoint == null) { - _localEndPoint = UnsafeNclNativeMethods.HttpApi.GetLocalEndPoint(RequestBuffer, BufferAlignment, OriginalBlobAddress); + _localEndPoint = HttpApi.GetLocalEndPoint(RequestBuffer, BufferAlignment, OriginalBlobAddress); } return _localEndPoint; @@ -349,13 +349,13 @@ namespace Microsoft.Net.Http.Server // Value: "iexplore.exe"=dword:00000001 private unsafe void GetTlsTokenBindingInfo() { - var nativeRequest = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)_nativeRequestContext.RequestBlob; + var nativeRequest = (HttpApi.HTTP_REQUEST_V2*)_nativeRequestContext.RequestBlob; for (int i = 0; i < nativeRequest->RequestInfoCount; i++) { var pThisInfo = &nativeRequest->pRequestInfo[i]; - if (pThisInfo->InfoType == UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslTokenBinding) + if (pThisInfo->InfoType == HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslTokenBinding) { - var pTokenBindingInfo = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO*)pThisInfo->pInfo; + var pTokenBindingInfo = (HttpApi.HTTP_REQUEST_TOKEN_BINDING_INFO*)pThisInfo->pInfo; _providedTokenBindingId = TokenBindingUtil.GetProvidedTokenIdFromBindingInfo(pTokenBindingInfo, out _referredTokenBindingId); } } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestContext.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestContext.cs index 6f588fae19..5ad6bbf78d 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestContext.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestContext.cs @@ -136,7 +136,7 @@ namespace Microsoft.Net.Http.Server return false; } - if (Request.KnownMethod != UnsafeNclNativeMethods.HttpApi.HTTP_VERB.HttpVerbGET) + if (Request.KnownMethod != HttpApi.HTTP_VERB.HttpVerbGET) { return false; } @@ -186,7 +186,7 @@ namespace Microsoft.Net.Http.Server throw new InvalidOperationException("This request is not a valid upgrade request."); } - if (Request.KnownMethod != UnsafeNclNativeMethods.HttpApi.HTTP_VERB.HttpVerbGET) + if (Request.KnownMethod != HttpApi.HTTP_VERB.HttpVerbGET) { throw new InvalidOperationException("This request is not a valid upgrade request; invalid verb: " + Request.Method); } @@ -352,7 +352,7 @@ namespace Microsoft.Net.Http.Server { try { - var statusCode = UnsafeNclNativeMethods.HttpApi.HttpCancelHttpRequest(Server.RequestQueue.Handle, + var statusCode = HttpApi.HttpCancelHttpRequest(Server.RequestQueue.Handle, Request.RequestId, IntPtr.Zero); // Either the connection has already dropped, or the last write is in progress. diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.cs index 1680f723d5..a1c526d68b 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.cs @@ -85,13 +85,13 @@ namespace Microsoft.Net.Http.Server private string GetKnownHeader(HttpSysRequestHeader header) { - return UnsafeNclNativeMethods.HttpApi.GetKnownHeader(_requestMemoryBlob.RequestBuffer, + return HttpApi.GetKnownHeader(_requestMemoryBlob.RequestBuffer, _requestMemoryBlob.BufferAlignment, _requestMemoryBlob.OriginalBlobAddress, (int)header); } private void GetUnknownHeaders(IDictionary extra) { - UnsafeNclNativeMethods.HttpApi.GetUnknownHeaders(extra, _requestMemoryBlob.RequestBuffer, + HttpApi.GetUnknownHeaders(extra, _requestMemoryBlob.RequestBuffer, _requestMemoryBlob.BufferAlignment, _requestMemoryBlob.OriginalBlobAddress); } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestStream.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestStream.cs index 460471838a..16324aa487 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestStream.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestStream.cs @@ -154,7 +154,7 @@ namespace Microsoft.Net.Http.Server if (_dataChunkIndex != -1) { - dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, + dataRead = HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.BufferAlignment, _requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size); } @@ -179,7 +179,7 @@ namespace Microsoft.Net.Http.Server uint flags = 0; statusCode = - UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( + HttpApi.HttpReceiveRequestEntityBody( RequestQueueHandle, RequestId, flags, @@ -232,7 +232,7 @@ namespace Microsoft.Net.Http.Server uint dataRead = 0; if (_dataChunkIndex != -1) { - dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.BufferAlignment, + dataRead = HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.BufferAlignment, _requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size); if (_dataChunkIndex != -1 && dataRead == size) @@ -262,7 +262,7 @@ namespace Microsoft.Net.Http.Server uint flags = 0; statusCode = - UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( + HttpApi.HttpReceiveRequestEntityBody( RequestQueueHandle, RequestId, flags, @@ -350,7 +350,7 @@ namespace Microsoft.Net.Http.Server uint dataRead = 0; if (_dataChunkIndex != -1) { - dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.BufferAlignment, + dataRead = HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.BufferAlignment, _requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size); if (_dataChunkIndex != -1 && dataRead == size) { @@ -386,7 +386,7 @@ namespace Microsoft.Net.Http.Server uint flags = 0; statusCode = - UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( + HttpApi.HttpReceiveRequestEntityBody( RequestQueueHandle, RequestId, flags, diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/ResponseStream.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/ResponseStream.cs index 119f87d949..1b3c94883a 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/ResponseStream.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/ResponseStream.cs @@ -406,9 +406,9 @@ namespace Microsoft.Net.Http.Server _requestContext.Abort(); } - private UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS ComputeLeftToWrite(bool endOfRequest = false) + private HttpApi.HTTP_FLAGS ComputeLeftToWrite(bool endOfRequest = false) { - UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE; + HttpApi.HTTP_FLAGS flags = HttpApi.HTTP_FLAGS.NONE; if (!_requestContext.Response.ComputedHeaders) { flags = _requestContext.Response.ComputeHeaders(endOfRequest, _buffer.TotalBytes); @@ -565,7 +565,7 @@ namespace Microsoft.Net.Http.Server internal unsafe Task SendFileAsyncCore(string fileName, long offset, long? count, CancellationToken cancellationToken) { _requestContext.Response.Start(); - UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); + HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (count == 0 && _leftToWrite != 0) { return Helpers.CompletedTask(); diff --git a/src/Microsoft.Net.Http.Server/TimeoutManager.cs b/src/Microsoft.Net.Http.Server/TimeoutManager.cs index 94f3625fc0..8c7155f710 100644 --- a/src/Microsoft.Net.Http.Server/TimeoutManager.cs +++ b/src/Microsoft.Net.Http.Server/TimeoutManager.cs @@ -35,7 +35,7 @@ namespace Microsoft.Net.Http.Server public sealed class TimeoutManager { private static readonly int TimeoutLimitSize = - Marshal.SizeOf(); + Marshal.SizeOf(); private WebListener _server; private int[] _timeouts; @@ -69,11 +69,11 @@ namespace Microsoft.Net.Http.Server { get { - return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.EntityBody); + return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.EntityBody); } set { - SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.EntityBody, value); + SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.EntityBody, value); } } @@ -92,11 +92,11 @@ namespace Microsoft.Net.Http.Server { get { - return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody); + return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody); } set { - SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody, value); + SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody, value); } } @@ -110,11 +110,11 @@ namespace Microsoft.Net.Http.Server { get { - return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue); + return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue); } set { - SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue, value); + SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue, value); } } @@ -129,11 +129,11 @@ namespace Microsoft.Net.Http.Server { get { - return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection); + return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection); } set { - SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection, value); + SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection, value); } } @@ -149,11 +149,11 @@ namespace Microsoft.Net.Http.Server { get { - return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait); + return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait); } set { - SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait, value); + SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait, value); } } @@ -189,13 +189,13 @@ namespace Microsoft.Net.Http.Server #region Helpers - private TimeSpan GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE type) + private TimeSpan GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE type) { // Since we maintain local state, GET is local. return new TimeSpan(0, 0, (int)_timeouts[(int)type]); } - private void SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE type, TimeSpan value) + private void SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE type, TimeSpan value) { // All timeouts are defined as USHORT in native layer (except MinSendRate, which is ULONG). Make sure that // timeout value is within range. @@ -217,25 +217,25 @@ namespace Microsoft.Net.Http.Server private unsafe void SetServerTimeouts(int[] timeouts, uint minSendBytesPerSecond) { - var timeoutinfo = new UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_LIMIT_INFO(); + var timeoutinfo = new HttpApi.HTTP_TIMEOUT_LIMIT_INFO(); - timeoutinfo.Flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT; + timeoutinfo.Flags = HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT; timeoutinfo.DrainEntityBody = - (ushort)timeouts[(int)UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody]; + (ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody]; timeoutinfo.EntityBody = - (ushort)timeouts[(int)UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.EntityBody]; + (ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.EntityBody]; timeoutinfo.RequestQueue = - (ushort)timeouts[(int)UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue]; + (ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue]; timeoutinfo.IdleConnection = - (ushort)timeouts[(int)UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection]; + (ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection]; timeoutinfo.HeaderWait = - (ushort)timeouts[(int)UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait]; + (ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait]; timeoutinfo.MinSendRate = minSendBytesPerSecond; var infoptr = new IntPtr(&timeoutinfo); _server.UrlGroup.SetProperty( - UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY.HttpServerTimeoutsProperty, + HttpApi.HTTP_SERVER_PROPERTY.HttpServerTimeoutsProperty, infoptr, (uint)TimeoutLimitSize); } diff --git a/src/Microsoft.Net.Http.Server/WebListener.cs b/src/Microsoft.Net.Http.Server/WebListener.cs index 960373d82e..be2e30dbb8 100644 --- a/src/Microsoft.Net.Http.Server/WebListener.cs +++ b/src/Microsoft.Net.Http.Server/WebListener.cs @@ -81,15 +81,15 @@ namespace Microsoft.Net.Http.Server public WebListener(ILoggerFactory factory) { - if (!UnsafeNclNativeMethods.HttpApi.Supported) + if (!HttpApi.Supported) { throw new PlatformNotSupportedException(); } _logger = LogHelper.CreateLogger(factory, typeof(WebListener)); - Debug.Assert(UnsafeNclNativeMethods.HttpApi.ApiVersion == - UnsafeNclNativeMethods.HttpApi.HTTP_API_VERSION.Version20, "Invalid Http api version"); + Debug.Assert(HttpApi.ApiVersion == + HttpApi.HTTP_API_VERSION.Version20, "Invalid Http api version"); _state = State.Stopped; _internalLock = new object(); @@ -399,7 +399,7 @@ namespace Microsoft.Net.Http.Server internal unsafe bool ValidateAuth(NativeRequestContext requestMemory) { - var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)requestMemory.RequestBlob; + var requestV2 = (HttpApi.HTTP_REQUEST_V2*)requestMemory.RequestBlob; if (!AuthenticationManager.AllowAnonymous && !AuthenticationManager.CheckAuthenticated(requestV2->pRequestInfo)) { SendError(requestMemory.RequestBlob->RequestId, HttpStatusCode.Unauthorized, @@ -411,8 +411,8 @@ namespace Microsoft.Net.Http.Server private unsafe void SendError(ulong requestId, HttpStatusCode httpStatusCode, IList authChallenges) { - UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_V2 httpResponse = new UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_V2(); - httpResponse.Response_V1.Version = new UnsafeNclNativeMethods.HttpApi.HTTP_VERSION(); + HttpApi.HTTP_RESPONSE_V2 httpResponse = new HttpApi.HTTP_RESPONSE_V2(); + httpResponse.Response_V1.Version = new HttpApi.HTTP_VERSION(); httpResponse.Response_V1.Version.MajorVersion = (ushort)1; httpResponse.Response_V1.Version.MinorVersion = (ushort)1; @@ -425,25 +425,25 @@ namespace Microsoft.Net.Http.Server { pinnedHeaders = new List(); - UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_INFO[] knownHeaderInfo = null; - knownHeaderInfo = new UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_INFO[1]; + HttpApi.HTTP_RESPONSE_INFO[] knownHeaderInfo = null; + knownHeaderInfo = new HttpApi.HTTP_RESPONSE_INFO[1]; gcHandle = GCHandle.Alloc(knownHeaderInfo, GCHandleType.Pinned); pinnedHeaders.Add(gcHandle); - httpResponse.pResponseInfo = (UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_INFO*)gcHandle.AddrOfPinnedObject(); + httpResponse.pResponseInfo = (HttpApi.HTTP_RESPONSE_INFO*)gcHandle.AddrOfPinnedObject(); - knownHeaderInfo[httpResponse.ResponseInfoCount].Type = UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_INFO_TYPE.HttpResponseInfoTypeMultipleKnownHeaders; + knownHeaderInfo[httpResponse.ResponseInfoCount].Type = HttpApi.HTTP_RESPONSE_INFO_TYPE.HttpResponseInfoTypeMultipleKnownHeaders; knownHeaderInfo[httpResponse.ResponseInfoCount].Length = - (uint)Marshal.SizeOf(); + (uint)Marshal.SizeOf(); - UnsafeNclNativeMethods.HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS header = new UnsafeNclNativeMethods.HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS(); + HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS header = new HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS(); - header.HeaderId = UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderWwwAuthenticate; - header.Flags = UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // The docs say this is for www-auth only. + header.HeaderId = HttpApi.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderWwwAuthenticate; + header.Flags = HttpApi.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // The docs say this is for www-auth only. - UnsafeNclNativeMethods.HttpApi.HTTP_KNOWN_HEADER[] nativeHeaderValues = new UnsafeNclNativeMethods.HttpApi.HTTP_KNOWN_HEADER[authChallenges.Count]; + HttpApi.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApi.HTTP_KNOWN_HEADER[authChallenges.Count]; gcHandle = GCHandle.Alloc(nativeHeaderValues, GCHandleType.Pinned); pinnedHeaders.Add(gcHandle); - header.KnownHeaders = (UnsafeNclNativeMethods.HttpApi.HTTP_KNOWN_HEADER*)gcHandle.AddrOfPinnedObject(); + header.KnownHeaders = (HttpApi.HTTP_KNOWN_HEADER*)gcHandle.AddrOfPinnedObject(); for (int headerValueIndex = 0; headerValueIndex < authChallenges.Count; headerValueIndex++) { @@ -460,7 +460,7 @@ namespace Microsoft.Net.Http.Server // This type is a struct, not an object, so pinning it causes a boxed copy to be created. We can't do that until after all the fields are set. gcHandle = GCHandle.Alloc(header, GCHandleType.Pinned); pinnedHeaders.Add(gcHandle); - knownHeaderInfo[0].pInfo = (UnsafeNclNativeMethods.HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS*)gcHandle.AddrOfPinnedObject(); + knownHeaderInfo[0].pInfo = (HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS*)gcHandle.AddrOfPinnedObject(); httpResponse.ResponseInfoCount = 1; } @@ -483,7 +483,7 @@ namespace Microsoft.Net.Http.Server httpResponse.Response_V1.Headers.UnknownHeaderCount = 0; statusCode = - UnsafeNclNativeMethods.HttpApi.HttpSendHttpResponse( + HttpApi.HttpSendHttpResponse( _requestQueue.Handle, requestId, 0, @@ -499,7 +499,7 @@ namespace Microsoft.Net.Http.Server if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { // if we fail to send a 401 something's seriously wrong, abort the request - UnsafeNclNativeMethods.HttpApi.HttpCancelHttpRequest(_requestQueue.Handle, requestId, IntPtr.Zero); + HttpApi.HttpCancelHttpRequest(_requestQueue.Handle, requestId, IntPtr.Zero); } } finally diff --git a/src/Microsoft.Net.Http.Server/fx/System/Diagnostics/TraceEventType.cs b/src/Microsoft.Net.Http.Server/fx/System/Diagnostics/TraceEventType.cs deleted file mode 100644 index 89ded72c3a..0000000000 --- a/src/Microsoft.Net.Http.Server/fx/System/Diagnostics/TraceEventType.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. -// All Rights Reserved -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING -// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF -// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR -// NON-INFRINGEMENT. -// See the Apache 2 License for the specific language governing -// permissions and limitations under the License. - -//------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//------------------------------------------------------------------------------ - -#if NETSTANDARD1_3 - -using System; -using System.ComponentModel; - -namespace System.Diagnostics -{ - internal enum TraceEventType - { - Critical = 0x01, - Error = 0x02, - Warning = 0x04, - Information = 0x08, - Verbose = 0x10, - - [EditorBrowsable(EditorBrowsableState.Advanced)] - Start = 0x0100, - [EditorBrowsable(EditorBrowsableState.Advanced)] - Stop = 0x0200, - [EditorBrowsable(EditorBrowsableState.Advanced)] - Suspend = 0x0400, - [EditorBrowsable(EditorBrowsableState.Advanced)] - Resume = 0x0800, - [EditorBrowsable(EditorBrowsableState.Advanced)] - Transfer = 0x1000, - } -} - -#endif diff --git a/src/Microsoft.Net.Http.Server/fx/System/ExternDll.cs b/src/Microsoft.Net.Http.Server/fx/System/ExternDll.cs deleted file mode 100644 index 989211c70c..0000000000 --- a/src/Microsoft.Net.Http.Server/fx/System/ExternDll.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. -// All Rights Reserved -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING -// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF -// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR -// NON-INFRINGEMENT. -// See the Apache 2 License for the specific language governing -// permissions and limitations under the License. - -//------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//------------------------------------------------------------------------------ - -#if NETSTANDARD1_3 - -namespace System -{ - internal static class ExternDll - { - public const string api_ms_win_core_localization_LIB = "api-ms-win-core-localization-l2-1-0.dll"; - } -} -#endif diff --git a/src/Microsoft.Net.Http.Server/fx/System/Runtime/InteropServices/ExternalException.cs b/src/Microsoft.Net.Http.Server/fx/System/Runtime/InteropServices/ExternalException.cs deleted file mode 100644 index 807bdd2a60..0000000000 --- a/src/Microsoft.Net.Http.Server/fx/System/Runtime/InteropServices/ExternalException.cs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. -// All Rights Reserved -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING -// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF -// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR -// NON-INFRINGEMENT. -// See the Apache 2 License for the specific language governing -// permissions and limitations under the License. - -// ==++== -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// ==--== -/*============================================================================= -** -** Class: ExternalException -** -** -** Purpose: Exception base class for all errors from Interop or Structured -** Exception Handling code. -** -** -=============================================================================*/ - -#if NETSTANDARD1_3 - -namespace System.Runtime.InteropServices -{ - using System; - using System.Globalization; - - // Base exception for COM Interop errors &; Structured Exception Handler - // exceptions. - // - internal class ExternalException : Exception - { - public ExternalException() - { - SetErrorCode(__HResults.E_FAIL); - } - - public ExternalException(String message) - : base(message) - { - SetErrorCode(__HResults.E_FAIL); - } - - public ExternalException(String message, Exception inner) - : base(message, inner) - { - SetErrorCode(__HResults.E_FAIL); - } - - public ExternalException(String message, int errorCode) - : base(message) - { - SetErrorCode(errorCode); - } - - private void SetErrorCode(int errorCode) - { - HResult = ErrorCode; - } - - private static class __HResults - { - internal const int E_FAIL = unchecked((int)0x80004005); - } - - public virtual int ErrorCode - { - get - { - return HResult; - } - } - - public override String ToString() - { - String message = Message; - String s; - String _className = GetType().ToString(); - s = _className + " (0x" + HResult.ToString("X8", CultureInfo.InvariantCulture) + ")"; - - if (!(String.IsNullOrEmpty(message))) - { - s = s + ": " + message; - } - - Exception _innerException = InnerException; - - if (_innerException != null) - { - s = s + " ---> " + _innerException.ToString(); - } - - - if (StackTrace != null) - s += Environment.NewLine + StackTrace; - - return s; - } - } -} - -#endif diff --git a/src/Microsoft.Net.Http.Server/fx/System/SafeNativeMethods.cs b/src/Microsoft.Net.Http.Server/fx/System/SafeNativeMethods.cs deleted file mode 100644 index 27a17a745c..0000000000 --- a/src/Microsoft.Net.Http.Server/fx/System/SafeNativeMethods.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. -// All Rights Reserved -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING -// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF -// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR -// NON-INFRINGEMENT. -// See the Apache 2 License for the specific language governing -// permissions and limitations under the License. - -//------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//------------------------------------------------------------------------------ - -#if NETSTANDARD1_3 -using System.Runtime.InteropServices; -using System.Text; - -namespace System -{ - internal static class SafeNativeMethods - { - public const int - FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100, - FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200, - FORMAT_MESSAGE_FROM_STRING = 0x00000400, - FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000, - FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000; - - [DllImport(ExternDll.api_ms_win_core_localization_LIB, CharSet = System.Runtime.InteropServices.CharSet.Unicode, SetLastError = true, BestFitMapping = true)] - public static unsafe extern int FormatMessage(int dwFlags, IntPtr lpSource_mustBeNull, uint dwMessageId, - int dwLanguageId, StringBuilder lpBuffer, int nSize, IntPtr[] arguments); - } -} -#endif