|
//------------------------------------------------------------------------------
// <copyright file="UnsafeNativeMethods.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Net {
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Text;
using System.Net.Sockets;
using System.Net.Cache;
using System.Threading;
using System.ComponentModel;
using System.Collections;
using System.Runtime.ConstrainedExecution;
using System.Security;
using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.IO;
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class UnsafeNclNativeMethods {
#if FEATURE_PAL
#if !PLATFORM_UNIX
internal const String DLLPREFIX = "";
internal const String DLLSUFFIX = ".dll";
#else // !PLATFORM_UNIX
#if __APPLE__
internal const String DLLPREFIX = "lib";
internal const String DLLSUFFIX = ".dylib";
#elif _AIX
internal const String DLLPREFIX = "lib";
internal const String DLLSUFFIX = ".a";
#elif __hppa__ || IA64
internal const String DLLPREFIX = "lib";
internal const String DLLSUFFIX = ".sl";
#else
internal const String DLLPREFIX = "lib";
internal const String DLLSUFFIX = ".so";
#endif
#endif // !PLATFORM_UNIX
internal const String ROTOR_PAL = DLLPREFIX + "rotor_pal" + DLLSUFFIX;
internal const String ROTOR_PALRT = DLLPREFIX + "rotor_palrt" + DLLSUFFIX;
private const String KERNEL32 = ROTOR_PAL;
#else
private const string KERNEL32 = "kernel32.dll";
#endif // !FEATURE_PAL
#if !FEATURE_PAL
private const string WS2_32 = "ws2_32.dll";
#else
private const string WS2_32 = ExternDll.Kernel32; // Resolves to rotor_pal
#endif // !FEATURE_PAL
private const string SECUR32 = "secur32.dll";
private const string CRYPT32 = "crypt32.dll";
private const string ADVAPI32 = "advapi32.dll";
private const string HTTPAPI = "httpapi.dll";
private const string SCHANNEL = "schannel.dll";
private const string RASAPI32 = "rasapi32.dll";
private const string WININET = "wininet.dll";
private const string WINHTTP = "winhttp.dll";
private const string BCRYPT = "bcrypt.dll";
private const string USER32 = "user32.dll";
private const string TOKENBINDING = "tokenbinding.dll";
#if !FEATURE_PAL
private const string OLE32 = "ole32.dll";
#endif
[DllImport(KERNEL32)]
internal static extern IntPtr CreateSemaphore([In] IntPtr lpSemaphoreAttributes, [In] int lInitialCount, [In] int lMaximumCount, [In] IntPtr lpName);
#if DEBUG
[DllImport(KERNEL32)]
internal static extern bool ReleaseSemaphore([In] IntPtr hSemaphore, [In] int lReleaseCount, [Out] out int lpPreviousCount);
#else
[DllImport(KERNEL32)]
internal static extern bool ReleaseSemaphore([In] IntPtr hSemaphore, [In] int lReleaseCount, [In] IntPtr lpPreviousCount);
#endif
//
internal static class ErrorCodes
{
internal const uint ERROR_SUCCESS = 0;
internal const uint ERROR_HANDLE_EOF = 38;
internal const uint ERROR_NOT_SUPPORTED = 50;
internal const uint ERROR_INVALID_PARAMETER = 87;
internal const uint ERROR_ALREADY_EXISTS = 183;
internal const uint ERROR_MORE_DATA = 234;
internal const uint ERROR_OPERATION_ABORTED = 995;
internal const uint ERROR_IO_PENDING = 997;
internal const uint ERROR_NOT_FOUND = 1168;
internal const uint ERROR_CONNECTION_INVALID = 1229;
}
internal static class NTStatus
{
internal const uint STATUS_SUCCESS = 0x00000000;
internal const uint STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034;
}
[DllImport(KERNEL32, ExactSpelling=true, CallingConvention=CallingConvention.StdCall, SetLastError=true)]
internal static extern uint GetCurrentThreadId();
[DllImport(KERNEL32, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static unsafe extern uint CancelIoEx(CriticalHandle handle, NativeOverlapped* overlapped);
[DllImport(KERNEL32, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static unsafe extern uint CancelIoEx(SafeHandle handle, IntPtr overlapped);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(KERNEL32, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static unsafe extern bool SetFileCompletionNotificationModes(CriticalHandle handle, FileCompletionNotificationModes modes);
[DllImport(KERNEL32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
internal static extern IntPtr GetProcessHeap();
[DllImport(KERNEL32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
internal static extern bool HeapFree([In] IntPtr hHeap, [In] uint dwFlags, [In] IntPtr lpMem);
[System.Security.SecurityCritical]
[DllImport(KERNEL32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
internal extern static IntPtr GetProcAddress(SafeLoadLibrary hModule, string entryPoint);
[System.Security.SecurityCritical]
[DllImport(KERNEL32, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
internal extern static IntPtr GetProcAddress(IntPtr hModule, string entryPoint);
[Flags]
internal enum FileCompletionNotificationModes : byte
{
None = 0,
SkipCompletionPortOnSuccess = 1,
SkipSetEventOnHandle = 2
}
#if STRESS || !DEBUG
[DllImport(KERNEL32, ExactSpelling = true)]
internal static extern void DebugBreak();
#endif
#if FEATURE_PAL
[DllImport(ROTOR_PALRT, CharSet=CharSet.Unicode, SetLastError=true, EntryPoint="PAL_FetchConfigurationStringW")]
internal static extern bool FetchConfigurationString(bool perMachine, String parameterName, StringBuilder parameterValue, int parameterValueLength);
#endif // FEATURE_PAL
#if !FEATURE_PAL
[SuppressUnmanagedCodeSecurity]
internal unsafe static class RegistryHelper
{
internal const uint REG_NOTIFY_CHANGE_LAST_SET = 4;
internal const uint REG_BINARY = 3;
internal const uint KEY_READ = 0x00020019;
internal static readonly IntPtr HKEY_CURRENT_USER = (IntPtr) unchecked((int) 0x80000001L);
internal static readonly IntPtr HKEY_LOCAL_MACHINE = (IntPtr) unchecked((int) 0x80000002L);
// RELIABILITY:
// this out parameter in this API, resultSubKey, is an allocated handle to a registry sub-key.
// it must be a SafeHandle so we can guarantee that it is released correctly and never leaked.
[DllImport(ADVAPI32, BestFitMapping=false, ThrowOnUnmappableChar=true, ExactSpelling=false, CharSet=CharSet.Auto, SetLastError=true)]
internal static extern uint RegOpenKeyEx(IntPtr key, string subKey, uint ulOptions, uint samDesired, out SafeRegistryHandle resultSubKey);
[DllImport(ADVAPI32, BestFitMapping=false, ThrowOnUnmappableChar=true, ExactSpelling=false, CharSet=CharSet.Auto, SetLastError=true)]
internal static extern uint RegOpenKeyEx(SafeRegistryHandle key, string subKey, uint ulOptions, uint samDesired, out SafeRegistryHandle resultSubKey);
[DllImport(ADVAPI32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern uint RegCloseKey(IntPtr key);
[DllImport(ADVAPI32, ExactSpelling=true, SetLastError=true)]
internal static extern uint RegNotifyChangeKeyValue(SafeRegistryHandle key, bool watchSubTree, uint notifyFilter, SafeWaitHandle regEvent, bool async);
[DllImport(ADVAPI32, ExactSpelling=true, SetLastError=true)]
internal static extern uint RegOpenCurrentUser(uint samDesired, out SafeRegistryHandle resultKey);
[DllImport(ADVAPI32, BestFitMapping=false, ThrowOnUnmappableChar=true, ExactSpelling=false, CharSet=CharSet.Auto, SetLastError=true)]
internal static extern uint RegQueryValueEx(SafeRegistryHandle key, string valueName, IntPtr reserved, out uint type, [Out] byte[] data, [In][Out] ref uint size);
}
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal unsafe class RasHelper
{
private static readonly bool s_RasSupported;
private ManualResetEvent m_RasEvent;
private bool m_Suppressed;
/* Consider removing
internal void Close()
{
ManualResetEvent rasEvent = m_RasEvent;
m_RasEvent = null;
m_Suppressed = false;
if (rasEvent != null)
{
rasEvent.Close();
}
}
*/
static RasHelper()
{
if (ComNetOS.InstallationType == WindowsInstallationType.ServerCore)
{
// if InstallationType == WindowsSku.Unknown we'll support RAS, since older OS (like XP)
// don't have an "Installation Type" Registry value
s_RasSupported = false;
}
else
{
s_RasSupported = true;
}
if (Logging.On)
Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_proxy_ras_supported, s_RasSupported));
}
internal RasHelper()
{
if (!s_RasSupported)
{
throw new InvalidOperationException(SR.GetString(SR.net_log_proxy_ras_notsupported_exception));
}
m_RasEvent = new ManualResetEvent(false);
// Use -1 as a handle, to receive all RAS notifications for the local machine.
uint statusCode = RasConnectionNotification((IntPtr)(-1), m_RasEvent.SafeWaitHandle, RASCN_Connection | RASCN_Disconnection);
GlobalLog.Print("RasHelper::RasHelper() RasConnectionNotification() statusCode:" + statusCode);
if (statusCode != 0)
{
GlobalLog.Print("RasHelper::RasHelper() RasConnectionNotification() Marshal.GetLastWin32Error():" + Marshal.GetLastWin32Error());
m_Suppressed = true;
m_RasEvent.Close();
m_RasEvent = null;
}
}
internal static bool RasSupported
{
get { return s_RasSupported; }
}
internal bool HasChanged
{
get
{
if (m_Suppressed)
{
return false;
}
ManualResetEvent rasEvent = m_RasEvent;
if (rasEvent == null)
{
throw new ObjectDisposedException(GetType().FullName);
}
return rasEvent.WaitOne(0, false);
}
}
internal void Reset()
{
if (!m_Suppressed)
{
ManualResetEvent rasEvent = m_RasEvent;
if (rasEvent == null)
{
throw new ObjectDisposedException(GetType().FullName);
}
rasEvent.Reset();
}
}
internal static string GetCurrentConnectoid()
{
uint dwSize = (uint) Marshal.SizeOf(typeof(RASCONN));
GlobalLog.Print("RasHelper::GetCurrentConnectoid() using struct size dwSize:" + dwSize);
if (!s_RasSupported)
{
// if RAS is not supported, behave as if no dial-up/VPN connection is in use
// (which is actually the case, since without RAS dial-up/VPN doesn't work)
return null;
}
uint count = 4;
uint statusCode = 0;
RASCONN[] connections = null;
while (true)
{
uint cb = checked(dwSize * count);
connections = new RASCONN[count];
connections[0].dwSize = dwSize;
statusCode = RasEnumConnections(connections, ref cb, ref count);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() called RasEnumConnections() count:" + count + " statusCode: " + statusCode + " cb:" + cb);
if (statusCode != ERROR_BUFFER_TOO_SMALL)
{
break;
}
count = checked(cb + dwSize - 1) / dwSize;
}
if (count == 0 || statusCode != 0)
{
return null;
}
for (uint i=0; i < count; i++)
{
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "]");
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].dwSize: " + connections[i].dwSize);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].hrasconn: " + connections[i].hrasconn);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].szEntryName: " + connections[i].szEntryName);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].szDeviceType: " + connections[i].szDeviceType);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].szDeviceName: " + connections[i].szDeviceName);
RASCONNSTATUS connectionStatus = new RASCONNSTATUS();
connectionStatus.dwSize = (uint)Marshal.SizeOf(connectionStatus);
// RELIABILITY:
// the 'hrasconn' field is an IntPtr because it's defined as a handle
// that said, its use is that of a opaque ID, so we're not
// allocating anything that needs to be released for reliability.
statusCode = RasGetConnectStatus(connections[i].hrasconn, ref connectionStatus);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() called RasGetConnectStatus() statusCode: " + statusCode + " dwSize: " + connectionStatus.dwSize);
if (statusCode==0) {
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].RASCONNSTATUS.dwSize: " + connectionStatus.dwSize);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].RASCONNSTATUS.rasconnstate: " + connectionStatus.rasconnstate);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].RASCONNSTATUS.dwError: " + connectionStatus.dwError);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].RASCONNSTATUS.szDeviceType: " + connectionStatus.szDeviceType);
GlobalLog.Print("RasHelper::GetCurrentConnectoid() RASCONN[" + i + "].RASCONNSTATUS.szDeviceName: " + connectionStatus.szDeviceName);
if (connectionStatus.rasconnstate==RASCONNSTATE.RASCS_Connected) {
return connections[i].szEntryName;
}
}
}
return null;
}
[DllImport(RASAPI32, ExactSpelling = false, CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = false)]
private static extern uint RasEnumConnections([In, Out] RASCONN[] lprasconn, ref uint lpcb, ref uint lpcConnections);
[DllImport(RASAPI32, ExactSpelling=false, CharSet=CharSet.Auto, BestFitMapping=false, ThrowOnUnmappableChar=true, SetLastError=false)]
private static extern uint RasGetConnectStatus([In] IntPtr hrasconn, [In, Out] ref RASCONNSTATUS lprasconnstatus);
[DllImport(RASAPI32, ExactSpelling=false, CharSet=CharSet.Auto, BestFitMapping=false, ThrowOnUnmappableChar=true, SetLastError=false)]
private static extern uint RasConnectionNotification([In] IntPtr hrasconn, [In] SafeWaitHandle hEvent, uint dwFlags);
const int RAS_MaxEntryName = 256;
const int RAS_MaxDeviceType = 16;
const int RAS_MaxDeviceName = 128;
const int RAS_MaxPhoneNumber = 128;
const int RAS_MaxCallbackNumber = 128;
const uint RASCN_Connection = 0x00000001;
const uint RASCN_Disconnection = 0x00000002;
const int UNLEN = 256;
const int PWLEN = 256;
const int DNLEN = 15;
const int MAX_PATH = 260;
const uint RASBASE = 600;
const uint ERROR_DIAL_ALREADY_IN_PROGRESS = (RASBASE+156);
const uint ERROR_BUFFER_TOO_SMALL = (RASBASE+3);
[StructLayout(LayoutKind.Sequential, Pack=4, CharSet=CharSet.Auto)]
struct RASCONN {
internal uint dwSize;
internal IntPtr hrasconn;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxEntryName + 1)]
internal string szEntryName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxDeviceType + 1)]
internal string szDeviceType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxDeviceName + 1)]
internal string szDeviceName;
/* None of these are supported on Windows 98.
MSDN lies twice: there is no dwSessionId at all, and szPhonebook and dwSubEntry are not on Win98.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
internal string szPhonebook;
internal uint dwSubEntry;
internal Guid guidEntry;
internal uint dwFlags;
internal ulong luid;
*/
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct RASCONNSTATUS {
internal uint dwSize;
internal RASCONNSTATE rasconnstate;
internal uint dwError;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxDeviceType + 1)]
internal string szDeviceType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxDeviceName + 1)]
internal string szDeviceName;
/* Not supported on Windows 98.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxPhoneNumber + 1)]
internal string szPhoneNumber;
*/
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct RASDIALPARAMS {
internal uint dwSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxEntryName + 1)]
internal string szEntryName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxPhoneNumber + 1)]
internal string szPhoneNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=RAS_MaxCallbackNumber + 1)]
internal string szCallbackNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=UNLEN + 1)]
internal string szUserName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=PWLEN + 1)]
internal string szPassword;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=DNLEN + 1)]
internal string szDomain;
/* Not supported on Windows 98.
internal uint dwSubEntry;
internal uint dwCallbackId;
*/
}
const int RASCS_PAUSED = 0x1000;
const int RASCS_DONE = 0x2000;
enum RASCONNSTATE {
RASCS_OpenPort = 0,
RASCS_PortOpened,
RASCS_ConnectDevice,
RASCS_DeviceConnected,
RASCS_AllDevicesConnected,
RASCS_Authenticate,
RASCS_AuthNotify,
RASCS_AuthRetry,
RASCS_AuthCallback,
RASCS_AuthChangePassword,
RASCS_AuthProject,
RASCS_AuthLinkSpeed,
RASCS_AuthAck,
RASCS_ReAuthenticate,
RASCS_Authenticated,
RASCS_PrepareForCallback,
RASCS_WaitForModemReset,
RASCS_WaitForCallback,
RASCS_Projected,
RASCS_StartAuthentication, // Windows 95 only
RASCS_CallbackComplete, // Windows 95 only
RASCS_LogonNetwork, // Windows 95 only
RASCS_SubEntryConnected,
RASCS_SubEntryDisconnected,
RASCS_Interactive = RASCS_PAUSED,
RASCS_RetryAuthentication,
RASCS_CallbackSetByCaller,
RASCS_PasswordExpired,
RASCS_InvokeEapUI,
RASCS_Connected = RASCS_DONE,
RASCS_Disconnected
}
}
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class SafeNetHandles_SECURITY {
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern int FreeContextBuffer(
[In] IntPtr contextBuffer);
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern int FreeCredentialsHandle(
ref SSPIHandle handlePtr
);
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern int DeleteSecurityContext(
ref SSPIHandle handlePtr
);
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal unsafe static extern int AcceptSecurityContext(
ref SSPIHandle credentialHandle,
[In] void* inContextPtr,
[In] SecurityBufferDescriptor inputBuffer,
[In] ContextFlags inFlags,
[In] Endianness endianness,
ref SSPIHandle outContextPtr,
[In, Out] SecurityBufferDescriptor outputBuffer,
[In, Out] ref ContextFlags attributes,
out long timeStamp
);
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal unsafe static extern int QueryContextAttributesW(
ref SSPIHandle contextHandle,
[In] ContextAttribute attribute,
[In] void* buffer);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal unsafe static extern int SetContextAttributesW(
ref SSPIHandle contextHandle,
[In] ContextAttribute attribute,
[In] byte[] buffer,
[In] int bufferSize);
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
internal static extern int EnumerateSecurityPackagesW(
[Out] out int pkgnum,
[Out] out SafeFreeContextBuffer_SECURITY handle);
[DllImport(SECUR32, ExactSpelling=true, CharSet=CharSet.Unicode, SetLastError=true)]
internal unsafe static extern int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] ref AuthIdentity authdata,
[In] void* keyCallback,
[In] void* keyArgument,
ref SSPIHandle handlePtr,
[Out] out long timeStamp
);
[DllImport(SECUR32, ExactSpelling=true, CharSet=CharSet.Unicode, SetLastError=true)]
internal unsafe static extern int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] IntPtr zero,
[In] void* keyCallback,
[In] void* keyArgument,
ref SSPIHandle handlePtr,
[Out] out long timeStamp
);
// Win7+
[DllImport(SECUR32, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal unsafe static extern int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] SafeSspiAuthDataHandle authdata,
[In] void* keyCallback,
[In] void* keyArgument,
ref SSPIHandle handlePtr,
[Out] out long timeStamp
);
[DllImport(SECUR32, ExactSpelling=true, CharSet=CharSet.Unicode, SetLastError=true)]
internal unsafe static extern int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] ref SecureCredential authData,
[In] void* keyCallback,
[In] void* keyArgument,
ref SSPIHandle handlePtr,
[Out] out long timeStamp
);
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal unsafe static extern int InitializeSecurityContextW(
ref SSPIHandle credentialHandle,
[In] void* inContextPtr,
[In] byte* targetName,
[In] ContextFlags inFlags,
[In] int reservedI,
[In] Endianness endianness,
[In] SecurityBufferDescriptor inputBuffer,
[In] int reservedII,
ref SSPIHandle outContextPtr,
[In, Out] SecurityBufferDescriptor outputBuffer,
[In, Out] ref ContextFlags attributes,
out long timeStamp
);
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal unsafe static extern int CompleteAuthToken(
[In] void* inContextPtr,
[In, Out] SecurityBufferDescriptor inputBuffers
);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal unsafe static extern int ApplyControlToken(
[In] void* inContextPtr,
[In, Out] SecurityBufferDescriptor inputBuffers
);
}
#endif // !FEATURE_PAL
// Because the regular SafeNetHandles has a LocalAlloc with a different return type.
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class SafeNetHandlesSafeOverlappedFree {
[DllImport(ExternDll.Kernel32, ExactSpelling=true, SetLastError=true)]
internal static extern SafeOverlappedFree LocalAlloc(int uFlags, UIntPtr sizetdwBytes);
}
#if !FEATURE_PAL
// Because the regular SafeNetHandles tries to bind this MustRun method on type initialization, failing
// on legacy platforms.
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class SafeNetHandlesXPOrLater {
[DllImport(WS2_32, ExactSpelling = true, CharSet = CharSet.Unicode, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)]
internal static extern int GetAddrInfoW(
[In] string nodename,
[In] string servicename,
[In] ref AddressInfo hints,
[Out] out SafeFreeAddrInfo handle
);
[DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern void freeaddrinfo([In] IntPtr info );
}
#endif
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class SafeNetHandles {
#if !FEATURE_PAL
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
internal static extern int QuerySecurityContextToken(ref SSPIHandle phContext, [Out] out SafeCloseHandle handle);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[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.Win32.NativeMethods.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);
#endif
[DllImport(ExternDll.Kernel32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern bool CloseHandle(IntPtr handle);
[DllImport(ExternDll.Kernel32, ExactSpelling=true, SetLastError=true)]
internal static extern SafeLocalFree LocalAlloc(int uFlags, UIntPtr sizetdwBytes);
[DllImport(ExternDll.Kernel32, EntryPoint = "LocalAlloc", SetLastError = true)]
internal static extern SafeLocalFreeChannelBinding LocalAllocChannelBinding(int uFlags, UIntPtr sizetdwBytes);
[DllImport(ExternDll.Kernel32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern IntPtr LocalFree(IntPtr handle);
#if !FEATURE_PAL
[DllImport(KERNEL32, ExactSpelling=true, CharSet=CharSet.Unicode, SetLastError=true)]
internal static extern unsafe SafeLoadLibrary LoadLibraryExW([In] string lpwLibFileName, [In] void* hFile, [In] uint dwFlags);
[DllImport(KERNEL32, ExactSpelling=true, CharSet=CharSet.Unicode, SetLastError=true)]
public static extern IntPtr GetModuleHandleW(string modName);
#endif // !FEATURE_PAL
[DllImport(KERNEL32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern unsafe bool FreeLibrary([In] IntPtr hModule);
#if !FEATURE_PAL
/*
// Consider removing.
[DllImport(CRYPT32, ExactSpelling=true, SetLastError=true)]
internal static extern bool CertGetCertificateChain(
[In] IntPtr chainEngine,
[In] SafeFreeCertContext certContext,
[In] IntPtr time,
[In] SafeCloseStore additionalStore,
[In] ref ChainParameters certCP,
[In] int flags,
[In] IntPtr reserved,
[Out] out SafeFreeCertChain chainContext);
*/
[DllImport(CRYPT32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern void CertFreeCertificateChain(
[In] IntPtr pChainContext);
[DllImport(CRYPT32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern void CertFreeCertificateChainList(
[In] IntPtr ppChainContext);
[DllImport(CRYPT32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern bool CertFreeCertificateContext( // Suppressing returned status check, it's always==TRUE,
[In] IntPtr certContext);
/*
// Consider removing.
[DllImport(CRYPT32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern bool CertCloseStore(
[In] IntPtr hCertStore,
[In] int dwFlags);
*/
#endif // !FEATURE_PAL
[DllImport(ExternDll.Kernel32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern IntPtr GlobalFree(IntPtr handle);
// Blocking call - requires IntPtr instead of SafeCloseSocket.
[DllImport(WS2_32, ExactSpelling=true, SetLastError=true)]
internal static extern SafeCloseSocket.InnerSafeCloseSocket accept(
[In] IntPtr socketHandle,
[Out] byte[] socketAddress,
[In, Out] ref int socketAddressSize
);
[DllImport(WS2_32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern SocketError closesocket(
[In] IntPtr socketHandle
);
[DllImport(WS2_32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern SocketError ioctlsocket(
[In] IntPtr handle,
[In] int cmd,
[In, Out] ref int argp
);
[DllImport(WS2_32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern SocketError WSAEventSelect(
[In] IntPtr handle,
[In] IntPtr Event,
[In] AsyncEventBits NetworkEvents
);
[DllImport(WS2_32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern SocketError setsockopt(
[In] IntPtr handle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[In] ref Linger linger,
[In] int optionLength
);
/* Consider removing
[DllImport(WS2_32, ExactSpelling=true, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern SocketError setsockopt(
[In] IntPtr handle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[In] ref int optionValue,
[In] int optionLength
);
*/
#if !FEATURE_PAL
[DllImport(WININET, ExactSpelling=true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
unsafe internal static extern bool RetrieveUrlCacheEntryFileW(
[In] char* urlName,
[In] byte* entryPtr, //was [Out]
[In, Out] ref int entryBufSize,
[In] int dwReserved //must be 0
);
[DllImport(WININET, ExactSpelling=true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
unsafe internal static extern bool UnlockUrlCacheEntryFileW(
[In] char* urlName,
[In] int dwReserved //must be 0
);
#endif // !FEATURE_PAL
}
//
// UnsafeNclNativeMethods.OSSOCK class contains all Unsafe() calls and should all be protected
// by the appropriate SocketPermission() to connect/accept to/from remote
// peers over the network and to perform name resolution.
// te following calls deal mainly with:
// 1) socket calls
// 2) DNS calls
//
//
// here's a brief explanation of all possible decorations we use for PInvoke.
// these are used in such a way that we hope to gain maximum performance from the
// unmanaged/managed/unmanaged transition we need to undergo when calling into winsock:
//
// [In] (Note: this is similar to what msdn will show)
// the managed data will be marshalled so that the unmanaged function can read it but even
// if it is changed in unmanaged world, the changes won't be propagated to the managed data
//
// [Out] (Note: this is similar to what msdn will show)
// the managed data will not be marshalled so that the unmanaged function will not see the
// managed data, if the data changes in unmanaged world, these changes will be propagated by
// the marshaller to the managed data
//
// objects are marshalled differently if they're:
//
// 1) structs
// for structs, by default, the whole layout is pushed on the stack as it is.
// in order to pass a pointer to the managed layout, we need to specify either the ref or out keyword.
//
// a) for IN and OUT:
// [In, Out] ref Struct ([In, Out] is optional here)
//
// b) for IN only (the managed data will be marshalled so that the unmanaged
// function can read it but even if it changes it the change won't be propagated
// to the managed struct)
// [In] ref Struct
//
// c) for OUT only (the managed data will not be marshalled so that the
// unmanaged function cannot read, the changes done in unmanaged code will be
// propagated to the managed struct)
// [Out] out Struct ([Out] is optional here)
//
// 2) array or classes
// for array or classes, by default, a pointer to the managed layout is passed.
// we don't need to specify neither the ref nor the out keyword.
//
// a) for IN and OUT:
// [In, Out] byte[]
//
// b) for IN only (the managed data will be marshalled so that the unmanaged
// function can read it but even if it changes it the change won't be propagated
// to the managed struct)
// [In] byte[] ([In] is optional here)
//
// c) for OUT only (the managed data will not be marshalled so that the
// unmanaged function cannot read, the changes done in unmanaged code will be
// propagated to the managed struct)
// [Out] byte[]
//
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class OSSOCK {
#if FEATURE_PAL
private const string WS2_32 = ROTOR_PAL;
#else
private const string WS2_32 = "ws2_32.dll";
private const string mswsock = "mswsock.dll";
#endif
//
// IPv6 Changes: These are initialized in InitializeSockets - don't set them here or
// there will be an ordering problem with the call above that will
// result in both being set to false !
//
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct WSAPROTOCOLCHAIN {
internal int ChainLen; /* the length of the chain, */
[MarshalAs(UnmanagedType.ByValArray, SizeConst=7)]
internal uint[] ChainEntries; /* a list of dwCatalogEntryIds */
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct WSAPROTOCOL_INFO {
internal uint dwServiceFlags1;
internal uint dwServiceFlags2;
internal uint dwServiceFlags3;
internal uint dwServiceFlags4;
internal uint dwProviderFlags;
Guid ProviderId;
internal uint dwCatalogEntryId;
WSAPROTOCOLCHAIN ProtocolChain;
internal int iVersion;
internal AddressFamily iAddressFamily;
internal int iMaxSockAddr;
internal int iMinSockAddr;
internal int iSocketType;
internal int iProtocol;
internal int iProtocolMaxOffset;
internal int iNetworkByteOrder;
internal int iSecurityScheme;
internal uint dwMessageSize;
internal uint dwProviderReserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
internal string szProtocol;
}
[StructLayout(LayoutKind.Sequential)]
internal struct ControlData {
internal UIntPtr length;
internal uint level;
internal uint type;
internal uint address;
internal uint index;
}
[StructLayout(LayoutKind.Sequential)]
internal struct ControlDataIPv6 {
internal UIntPtr length;
internal uint level;
internal uint type;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=16)]
internal byte[] address;
internal uint index;
}
[StructLayout(LayoutKind.Sequential)]
internal struct WSAMsg {
internal IntPtr socketAddress;
internal uint addressLength;
internal IntPtr buffers;
internal uint count;
internal WSABuffer controlBuffer;
internal SocketFlags flags;
}
//
// Flags equivalent to winsock TRANSMIT_PACKETS_ELEMENT flags
// #define TP_ELEMENT_MEMORY 1
// #define TP_ELEMENT_FILE 2
// #define TP_ELEMENT_EOP 4
//
[Flags]
internal enum TransmitPacketsElementFlags : uint {
None = 0x00,
Memory = 0x01,
File = 0x02,
EndOfPacket = 0x04
}
// Structure equivalent to TRANSMIT_PACKETS_ELEMENT
//
// typedef struct _TRANSMIT_PACKETS_ELEMENT {
// ULONG dwElFlags;
// ULONG cLength;
// union {
// struct {
// LARGE_INTEGER nFileOffset;
// HANDLE hFile;
// };
// PVOID pBuffer;
// }
// };
// } TRANSMIT_PACKETS_ELEMENT;
//
[StructLayout(LayoutKind.Explicit)]
internal struct TransmitPacketsElement {
[System.Runtime.InteropServices.FieldOffset(0)]
internal TransmitPacketsElementFlags flags;
[System.Runtime.InteropServices.FieldOffset(4)]
internal uint length;
[System.Runtime.InteropServices.FieldOffset(8)]
internal Int64 fileOffset;
[System.Runtime.InteropServices.FieldOffset(8)]
internal IntPtr buffer;
[System.Runtime.InteropServices.FieldOffset(16)]
internal IntPtr fileHandle;
}
/*
typedef struct _SOCKET_ADDRESS {
PSOCKADDR lpSockaddr;
INT iSockaddrLength;
} SOCKET_ADDRESS, *PSOCKET_ADDRESS;
*/
[StructLayout(LayoutKind.Sequential)]
internal struct SOCKET_ADDRESS {
internal IntPtr lpSockAddr;
internal int iSockaddrLength;
}
/*
typedef struct _SOCKET_ADDRESS_LIST {
INT iAddressCount;
SOCKET_ADDRESS Address[1];
} SOCKET_ADDRESS_LIST, *PSOCKET_ADDRESS_LIST, FAR *LPSOCKET_ADDRESS_LIST;
*/
[StructLayout(LayoutKind.Sequential)]
internal struct SOCKET_ADDRESS_LIST {
internal int iAddressCount;
internal SOCKET_ADDRESS Addresses;
}
[StructLayout(LayoutKind.Sequential)]
internal struct TransmitFileBuffersStruct {
internal IntPtr preBuffer;// Pointer to Buffer
internal int preBufferLength; // Length of Buffer
internal IntPtr postBuffer;// Pointer to Buffer
internal int postBufferLength; // Length of Buffer
}
// CharSet=Auto here since WSASocket has A and W versions. We can use Auto cause the method is not used under constrained execution region
[DllImport(WS2_32, CharSet=CharSet.Auto, SetLastError=true)]
internal static extern SafeCloseSocket.InnerSafeCloseSocket WSASocket(
[In] AddressFamily addressFamily,
[In] SocketType socketType,
[In] ProtocolType protocolType,
[In] IntPtr protocolInfo, // will be WSAProtcolInfo protocolInfo once we include QOS APIs
[In] uint group,
[In] SocketConstructorFlags flags
);
[DllImport(WS2_32, CharSet=CharSet.Auto, SetLastError=true)]
internal unsafe static extern SafeCloseSocket.InnerSafeCloseSocket WSASocket(
[In] AddressFamily addressFamily,
[In] SocketType socketType,
[In] ProtocolType protocolType,
[In] byte* pinnedBuffer, // will be WSAProtcolInfo protocolInfo once we include QOS APIs
[In] uint group,
[In] SocketConstructorFlags flags
);
[DllImport(WS2_32, CharSet=CharSet.Ansi, BestFitMapping=false, ThrowOnUnmappableChar=true, SetLastError=true)]
internal static extern SocketError WSAStartup(
[In] short wVersionRequested,
[Out] out WSAData lpWSAData
);
[DllImport(WS2_32, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static extern SocketError ioctlsocket(
[In] SafeCloseSocket socketHandle,
[In] int cmd,
[In, Out] ref int argp
);
[DllImport(WS2_32, CharSet=CharSet.Ansi, BestFitMapping=false, ThrowOnUnmappableChar=true, SetLastError=true)]
internal static extern IntPtr gethostbyname(
[In] string host
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern IntPtr gethostbyaddr(
[In] ref int addr,
[In] int len,
[In] ProtocolFamily type
);
[DllImport(WS2_32, CharSet=CharSet.Ansi, BestFitMapping=false, ThrowOnUnmappableChar=true, SetLastError=true)]
internal static extern SocketError gethostname(
[Out] StringBuilder hostName,
[In] int bufferLength
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError getpeername(
[In] SafeCloseSocket socketHandle,
[Out] byte[] socketAddress,
[In, Out] ref int socketAddressSize
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError getsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[Out] out int optionValue,
[In, Out] ref int optionLength
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError getsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[Out] byte[] optionValue,
[In, Out] ref int optionLength
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError getsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[Out] out Linger optionValue,
[In, Out] ref int optionLength
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError getsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[Out] out IPMulticastRequest optionValue,
[In, Out] ref int optionLength
);
//
// IPv6 Changes: need to receive and IPv6MulticastRequest from getsockopt
//
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError getsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[Out] out IPv6MulticastRequest optionValue,
[In, Out] ref int optionLength
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError setsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[In] ref int optionValue,
[In] int optionLength
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError setsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[In] byte[] optionValue,
[In] int optionLength
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError setsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[In] ref IntPtr pointer,
[In] int optionLength
);
[DllImport(WS2_32, SetLastError=true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static extern SocketError setsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[In] ref Linger linger,
[In] int optionLength
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError setsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[In] ref IPMulticastRequest mreq,
[In] int optionLength
);
//
// IPv6 Changes: need to pass an IPv6MulticastRequest to setsockopt
//
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError setsockopt(
[In] SafeCloseSocket socketHandle,
[In] SocketOptionLevel optionLevel,
[In] SocketOptionName optionName,
[In] ref IPv6MulticastRequest mreq,
[In] int optionLength
);
#if !FEATURE_PAL
[DllImport(mswsock, SetLastError=true)]
internal static extern bool TransmitFile(
[In] SafeCloseSocket socket,
[In] SafeHandle fileHandle,
[In] int numberOfBytesToWrite,
[In] int numberOfBytesPerSend,
[In] SafeHandle overlapped,
[In] TransmitFileBuffers buffers,
[In] TransmitFileOptions flags
);
[DllImport(mswsock, SetLastError=true, EntryPoint = "TransmitFile")]
internal static extern bool TransmitFile2(
[In] SafeCloseSocket socket,
[In] IntPtr fileHandle,
[In] int numberOfBytesToWrite,
[In] int numberOfBytesPerSend,
[In] SafeHandle overlapped,
[In] TransmitFileBuffers buffers,
[In] TransmitFileOptions flags
);
[DllImport(mswsock, SetLastError = true, EntryPoint = "TransmitFile")]
internal static extern bool TransmitFile_Blocking(
[In] IntPtr socket,
[In] SafeHandle fileHandle,
[In] int numberOfBytesToWrite,
[In] int numberOfBytesPerSend,
[In] SafeHandle overlapped,
[In] TransmitFileBuffers buffers,
[In] TransmitFileOptions flags
);
[DllImport(mswsock, SetLastError = true, EntryPoint = "TransmitFile")]
internal static extern bool TransmitFile_Blocking2(
[In] IntPtr socket,
[In] IntPtr fileHandle,
[In] int numberOfBytesToWrite,
[In] int numberOfBytesPerSend,
[In] SafeHandle overlapped,
[In] TransmitFileBuffers buffers,
[In] TransmitFileOptions flags
);
#endif // !FEATURE_PAL
// This method is always blocking, so it uses an IntPtr.
[DllImport(WS2_32, SetLastError = true)]
internal unsafe static extern int send(
[In] IntPtr socketHandle,
[In] byte* pinnedBuffer,
[In] int len,
[In] SocketFlags socketFlags
);
// This method is always blocking, so it uses an IntPtr.
[DllImport(WS2_32, SetLastError = true)]
internal unsafe static extern int recv(
[In] IntPtr socketHandle,
[In] byte* pinnedBuffer,
[In] int len,
[In] SocketFlags socketFlags
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError listen(
[In] SafeCloseSocket socketHandle,
[In] int backlog
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError bind(
[In] SafeCloseSocket socketHandle,
[In] byte[] socketAddress,
[In] int socketAddressSize
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError shutdown(
[In] SafeCloseSocket socketHandle,
[In] int how
);
// This method is always blocking, so it uses an IntPtr.
[DllImport(WS2_32, SetLastError = true)]
internal unsafe static extern int sendto(
[In] IntPtr socketHandle,
[In] byte* pinnedBuffer,
[In] int len,
[In] SocketFlags socketFlags,
[In] byte[] socketAddress,
[In] int socketAddressSize
);
// This method is always blocking, so it uses an IntPtr.
[DllImport(WS2_32, SetLastError = true)]
internal unsafe static extern int recvfrom(
[In] IntPtr socketHandle,
[In] byte* pinnedBuffer,
[In] int len,
[In] SocketFlags socketFlags,
[Out] byte[] socketAddress,
[In, Out] ref int socketAddressSize
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError getsockname(
[In] SafeCloseSocket socketHandle,
[Out] byte[] socketAddress,
[In, Out] ref int socketAddressSize
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern int select(
[In] int ignoredParameter,
[In, Out] IntPtr[] readfds,
[In, Out] IntPtr[] writefds,
[In, Out] IntPtr[] exceptfds,
[In] ref TimeValue timeout
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern int select(
[In] int ignoredParameter,
[In, Out] IntPtr[] readfds,
[In, Out] IntPtr[] writefds,
[In, Out] IntPtr[] exceptfds,
[In] IntPtr nullTimeout
);
// This function is always potentially blocking so it uses an IntPtr.
[DllImport(WS2_32, SetLastError = true)]
internal static extern SocketError WSAConnect(
[In] IntPtr socketHandle,
[In] byte[] socketAddress,
[In] int socketAddressSize,
[In] IntPtr inBuffer,
[In] IntPtr outBuffer,
[In] IntPtr sQOS,
[In] IntPtr gQOS
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError WSASend(
[In] SafeCloseSocket socketHandle,
[In] ref WSABuffer buffer,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In] SocketFlags socketFlags,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError WSASend(
[In] SafeCloseSocket socketHandle,
[In] WSABuffer[] buffersArray,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In] SocketFlags socketFlags,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError = true, EntryPoint = "WSASend")]
internal static extern SocketError WSASend_Blocking(
[In] IntPtr socketHandle,
[In] WSABuffer[] buffersArray,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In] SocketFlags socketFlags,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError = true)]
internal static extern SocketError WSASendTo(
[In] SafeCloseSocket socketHandle,
[In] ref WSABuffer buffer,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In] SocketFlags socketFlags,
[In] IntPtr socketAddress,
[In] int socketAddressSize,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError = true)]
internal static extern SocketError WSASendTo(
[In] SafeCloseSocket socketHandle,
[In] WSABuffer[] buffersArray,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In] SocketFlags socketFlags,
[In] IntPtr socketAddress,
[In] int socketAddressSize,
[In] SafeNativeOverlapped overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError WSARecv(
[In] SafeCloseSocket socketHandle,
[In] ref WSABuffer buffer,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In, Out] ref SocketFlags socketFlags,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError = true)]
internal static extern SocketError WSARecv(
[In] SafeCloseSocket socketHandle,
[In, Out] WSABuffer[] buffers,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In, Out] ref SocketFlags socketFlags,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError = true, EntryPoint = "WSARecv")]
internal static extern SocketError WSARecv_Blocking(
[In] IntPtr socketHandle,
[In, Out] WSABuffer[] buffers,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In, Out] ref SocketFlags socketFlags,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError WSARecvFrom(
[In] SafeCloseSocket socketHandle,
[In] ref WSABuffer buffer,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In, Out] ref SocketFlags socketFlags,
[In] IntPtr socketAddressPointer,
[In] IntPtr socketAddressSizePointer,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError = true)]
internal static extern SocketError WSARecvFrom(
[In] SafeCloseSocket socketHandle,
[In, Out] WSABuffer[] buffers,
[In] int bufferCount,
[Out] out int bytesTransferred,
[In, Out] ref SocketFlags socketFlags,
[In] IntPtr socketAddressPointer,
[In] IntPtr socketAddressSizePointer,
[In] SafeNativeOverlapped overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError WSAEventSelect(
[In] SafeCloseSocket socketHandle,
[In] SafeHandle Event,
[In] AsyncEventBits NetworkEvents
);
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError WSAEventSelect(
[In] SafeCloseSocket socketHandle,
[In] IntPtr Event,
[In] AsyncEventBits NetworkEvents
);
// Used with SIOGETEXTENSIONFUNCTIONPOINTER - we're assuming that will never block.
[DllImport(WS2_32, SetLastError=true)]
internal static extern SocketError WSAIoctl(
[In] SafeCloseSocket socketHandle,
[In] int ioControlCode,
[In,Out] ref Guid guid,
[In] int guidSize,
[Out] out IntPtr funcPtr,
[In] int funcPtrSize,
[Out] out int bytesTransferred,
[In] IntPtr shouldBeNull,
[In] IntPtr shouldBeNull2
);
[DllImport(WS2_32, SetLastError = true, EntryPoint = "WSAIoctl")]
internal static extern SocketError WSAIoctl_Blocking(
[In] IntPtr socketHandle,
[In] int ioControlCode,
[In] byte[] inBuffer,
[In] int inBufferSize,
[Out] byte[] outBuffer,
[In] int outBufferSize,
[Out] out int bytesTransferred,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32, SetLastError = true, EntryPoint = "WSAIoctl")]
internal static extern SocketError WSAIoctl_Blocking_Internal(
[In] IntPtr socketHandle,
[In] uint ioControlCode,
[In] IntPtr inBuffer,
[In] int inBufferSize,
[Out] IntPtr outBuffer,
[In] int outBufferSize,
[Out] out int bytesTransferred,
[In] SafeHandle overlapped,
[In] IntPtr completionRoutine
);
[DllImport(WS2_32,SetLastError=true)]
internal static extern SocketError WSAEnumNetworkEvents(
[In] SafeCloseSocket socketHandle,
[In] SafeWaitHandle Event,
[In, Out] ref NetworkEvents networkEvents
);
#if !FEATURE_PAL
[DllImport(WS2_32, SetLastError=true)]
internal unsafe static extern int WSADuplicateSocket(
[In] SafeCloseSocket socketHandle,
[In] uint targetProcessID,
[In] byte* pinnedBuffer
);
#endif // !FEATURE_PAL
[DllImport(WS2_32, SetLastError=true)]
internal static extern bool WSAGetOverlappedResult(
[In] SafeCloseSocket socketHandle,
[In] SafeHandle overlapped,
[Out] out uint bytesTransferred,
[In] bool wait,
[Out] out SocketFlags socketFlags
);
#if !FEATURE_PAL
// Don't throw, it would crash IPAddress.TryParse
[DllImport(WS2_32, CharSet=CharSet.Unicode, BestFitMapping=false, ThrowOnUnmappableChar=false, SetLastError=true)]
internal static extern SocketError WSAStringToAddress(
[In] string addressString,
[In] AddressFamily addressFamily,
[In] IntPtr lpProtocolInfo, // always passing in a 0
[Out] byte[] socketAddress,
[In, Out] ref int socketAddressSize );
[DllImport(WS2_32, CharSet=CharSet.Ansi, BestFitMapping=false, ThrowOnUnmappableChar=true, SetLastError=true)]
internal static extern SocketError WSAAddressToString(
[In] byte[] socketAddress,
[In] int socketAddressSize,
[In] IntPtr lpProtocolInfo,// always passing in a 0
[Out]StringBuilder addressString,
[In, Out] ref int addressStringLength);
[DllImport(WS2_32, CharSet=CharSet.Unicode, BestFitMapping=false, ThrowOnUnmappableChar=true, SetLastError=true)]
internal static extern SocketError GetNameInfoW(
[In] byte[] sa,
[In] int salen,
[In,Out] StringBuilder host,
[In] int hostlen,
[In,Out] StringBuilder serv,
[In] int servlen,
[In] int flags);
//if we change this back to auto, we also have to change
//WSAPROTOCOL_INFO and WSAPROTOCOLCHAIN
[DllImport(WS2_32, SetLastError=true, CharSet=CharSet.Auto, ExactSpelling=false)]
internal static extern int WSAEnumProtocols(
[MarshalAs(UnmanagedType.LPArray)]
[In] int[] lpiProtocols,
[In] SafeLocalFree lpProtocolBuffer,
[In][Out] ref uint lpdwBufferLength
);
#if SOCKETTHREADPOOL
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool BindIoCompletionCallback(
SafeCloseSocket socketHandle,
IOCompletionCallback function,
Int32 flags
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateIoCompletionPort(
SafeCloseSocket socketHandle,
IntPtr ExistingCompletionPort,
Int32 CompletionKey,
Int32 NumberOfConcurrentThreads
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateIoCompletionPort(
SafeHandle Handle,
IntPtr ExistingCompletionPort,
Int32 CompletionKey,
Int32 NumberOfConcurrentThreads
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateIoCompletionPort(
IntPtr Handle,
IntPtr ExistingCompletionPort,
Int32 CompletionKey,
Int32 NumberOfConcurrentThreads
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern unsafe bool GetQueuedCompletionStatus(
IntPtr CompletionPort,
out UInt32 lpNumberOfBytes,
out Int32 lpCompletionKey,
out NativeOverlapped* lpOverlapped,
Int32 dwMilliseconds
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool PostQueuedCompletionStatus(
IntPtr CompletionPort,
Int32 dwNumberOfBytesTransferred,
IntPtr dwCompletionKey,
IntPtr dwZero
);
#endif // SOCKETTHREADPOOL
#endif // !FEATURE_PAL
}; // class UnsafeNclNativeMethods.OSSOCK
#if !FEATURE_PAL
//
// UnsafeNclNativeMethods.NativePKI class contains methods
// imported from crypt32.dll.
// They deal mainly with certificates handling when doing https://
//
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class NativePKI {
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_OBJID_BLOB
{
public UInt32 cbData;
public IntPtr pbData;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal struct CERT_EXTENSION
{
public IntPtr pszObjId;
public UInt32 fCritical;
public CRYPT_OBJID_BLOB Value;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CERT_SELECT_CRITERIA
{
public UInt32 dwType;
public UInt32 cPara;
public IntPtr ppPara;
}
[DllImport(CRYPT32, ExactSpelling=true, SetLastError=true)]
internal static extern int CertVerifyCertificateChainPolicy(
[In] IntPtr policy,
[In] SafeFreeCertChain chainContext,
[In] ref ChainPolicyParameter cpp,
[In, Out] ref ChainPolicyStatus ps);
// Win7+
[DllImport(CRYPT32, ExactSpelling=true, SetLastError=true)]
private static extern bool CertSelectCertificateChains(
[In] IntPtr pSelectionContext, // LPCGUID
[In] CertificateSelect flags, // DWORD
[In] IntPtr pChainParameters, // PCCERT_SELECT_CHAIN_PARA
[In] int cCriteria, // DWORD
[In] SafeCertSelectCritera rgpCriteria, // PCCERT_SELECT_CRITERIA
[In] IntPtr hStore, // HCERTSTORE
[Out] out int pcSelection, // PDWORD
// **PCCERT_CHAIN_CONTEXT, Array of ptrs to contexts
[Out] out SafeFreeCertChainList pprgpSelection);
// See WinCrypt.h
[Flags]
private enum CertificateSelect : int
{
None = 0,
AllowExpired = 0x00000001,
TrustedRoot = 0x00000002,
DisallowSelfsigned = 0x00000004,
HasPrivateKey = 0x00000008,
HasKeyForSignature = 0x00000010,
HasKeyForKeyExchange = 0x00000020,
HardwareOnly = 0x00000040,
AllowDuplicates = 0x00000080,
}
// Discover available client certificates to send to the server.
// SecureChannel will handle filtering by Issuer durring the request (AcquireClientCredentials).
// See WinINet's implementation: //depot/winmain/inetcore/wininet/dll/CliauthCertselect.cxx
[FriendAccessAllowed]
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods",
Justification = "Marshalling requires DangerousGetHandle")]
internal static X509CertificateCollection FindClientCertificates()
{
if (!ComNetOS.IsWin7orLater)
{
throw new PlatformNotSupportedException();
}
X509CertificateCollection certificates = new X509CertificateCollection();
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.MaxAllowed);
int chainCount = 0;
SafeFreeCertChainList chainList = null;
SafeCertSelectCritera criteria = new SafeCertSelectCritera();
try
{
bool success = CertSelectCertificateChains(
IntPtr.Zero,
CertificateSelect.HasPrivateKey,
IntPtr.Zero,
criteria.Count, // DWORD
criteria, // PCCERT_SELECT_CRITERIA
store.StoreHandle,
out chainCount,
out chainList);
if (!success)
{
throw new Win32Exception(); // Calls GetLastError.
}
Debug.Assert(chainCount == 0 || !chainList.IsInvalid);
for (int i = 0; i < chainCount; i++)
{
// Resolve IntPtr in array.
using (SafeFreeCertChain chainRef = new SafeFreeCertChain(
Marshal.ReadIntPtr(chainList.DangerousGetHandle()
+ i * Marshal.SizeOf(typeof(IntPtr))), true))
{
Debug.Assert(!chainRef.IsInvalid);
// X509Chain will duplicate the chain by increasing its ref-count.
X509Chain chain = new X509Chain(chainRef.DangerousGetHandle());
// Copy base cert from chain.
if (chain.ChainElements.Count > 0)
{
X509Certificate2 cert = chain.ChainElements[0].Certificate;
certificates.Add(cert);
}
// Remove the X509Chain's reference prior to releasing the Chain List.
chain.Reset();
}
}
}
finally
{
// Close store.
store.Close();
chainList.Dispose();
criteria.Dispose();
}
return certificates;
}
}; // class UnsafeNclNativeMethods.NativePKI
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class NativeNTSSPI {
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[DllImport(SECUR32, ExactSpelling=true, SetLastError=true)]
internal static extern int EncryptMessage(
ref SSPIHandle contextHandle,
[In] uint qualityOfProtection,
[In, Out] SecurityBufferDescriptor inputOutput,
[In] uint sequenceNumber
);
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
internal static unsafe extern int DecryptMessage(
[In] ref SSPIHandle contextHandle,
[In, Out] SecurityBufferDescriptor inputOutput,
[In] uint sequenceNumber,
uint *qualityOfProtection
);
}; // class UnsafeNclNativeMethods.NativeNTSSPI
// The replacement for WinInet, WinHttp is preferred where it's available. We require version 5.1.
[SuppressUnmanagedCodeSecurity]
internal static class WinHttp
{
[DllImport(WINHTTP, ExactSpelling=true, SetLastError=true)]
internal static extern bool WinHttpDetectAutoProxyConfigUrl(AutoDetectType autoDetectFlags,
out SafeGlobalFree autoConfigUrl);
[DllImport(WINHTTP, SetLastError = true)]
internal static extern bool WinHttpGetIEProxyConfigForCurrentUser(
ref WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(WINHTTP, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern SafeInternetHandle WinHttpOpen(string userAgent, AccessType accessType,
string proxyName, string proxyBypass, int dwFlags);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(WINHTTP, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool WinHttpSetTimeouts(SafeInternetHandle session, int resolveTimeout,
int connectTimeout, int sendTimeout, int receiveTimeout);
[DllImport(WINHTTP, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool WinHttpGetProxyForUrl(SafeInternetHandle session, string url,
[In] ref WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out WINHTTP_PROXY_INFO proxyInfo);
[DllImport(WINHTTP, CharSet = CharSet.Unicode, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern bool WinHttpCloseHandle(IntPtr httpSession);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
{
public bool AutoDetect;
public IntPtr AutoConfigUrl;
public IntPtr Proxy;
public IntPtr ProxyBypass;
}
[Flags]
internal enum AutoProxyFlags
{
AutoDetect = 0x00000001, // WINHTTP_AUTOPROXY_AUTO_DETECT
AutoProxyConfigUrl = 0x00000002, // WINHTTP_AUTOPROXY_CONFIG_URL
RunInProcess = 0x00010000, // WINHTTP_AUTOPROXY_RUN_INPROCESS
RunOutProcessOnly = 0x00020000 // WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY
}
internal enum AccessType
{
DefaultProxy = 0,
NoProxy = 1,
NamedProxy = 3
}
[Flags]
internal enum AutoDetectType
{
None = 0x0,
Dhcp = 0x1, // WINHTTP_AUTO_DETECT_TYPE_DHCP
DnsA = 0x2, // WINHTTP_AUTO_DETECT_TYPE_DNS_A
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WINHTTP_AUTOPROXY_OPTIONS
{
public AutoProxyFlags Flags;
public AutoDetectType AutoDetectFlags;
[MarshalAs(UnmanagedType.LPWStr)]
public string AutoConfigUrl;
private IntPtr lpvReserved;
private int dwReserved;
public bool AutoLogonIfChallenged;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct WINHTTP_PROXY_INFO
{
public AccessType AccessType;
public IntPtr Proxy;
public IntPtr ProxyBypass;
}
internal enum ErrorCodes
{
Success = 0,
OutOfHandles = 12001, // ERROR_WINHTTP_OUT_OF_HANDLES
Timeout = 12002, // ERROR_WINHTTP_TIMEOUT
InternalError = 12004, // ERROR_WINHTTP_INTERNAL_ERROR
InvalidUrl = 12005, // ERROR_WINHTTP_INVALID_URL
UnrecognizedScheme = 12006, // ERROR_WINHTTP_UNRECOGNIZED_SCHEME
NameNotResolved = 12007, // ERROR_WINHTTP_NAME_NOT_RESOLVED
InvalidOption = 12009, // ERROR_WINHTTP_INVALID_OPTION
OptionNotSettable = 12011, // ERROR_WINHTTP_OPTION_NOT_SETTABLE
Shutdown = 12012, // ERROR_WINHTTP_SHUTDOWN
LoginFailure = 12015, // ERROR_WINHTTP_LOGIN_FAILURE
OperationCancelled = 12017, // ERROR_WINHTTP_OPERATION_CANCELLED
IncorrectHandleType = 12018, // ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
IncorrectHandleState = 12019, // ERROR_WINHTTP_INCORRECT_HANDLE_STATE
CannotConnect = 12029, // ERROR_WINHTTP_CANNOT_CONNECT
ConnectionError = 12030, // ERROR_WINHTTP_CONNECTION_ERROR
ResendRequest = 12032, // ERROR_WINHTTP_RESEND_REQUEST
AuthCertNeeded = 12044, // ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED
CannotCallBeforeOpen = 12100, // ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN
CannotCallBeforeSend = 12101, // ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND
CannotCallAfterSend = 12102, // ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND
CannotCallAfterOpen = 12103, // ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN
HeaderNotFound = 12150, // ERROR_WINHTTP_HEADER_NOT_FOUND
InvalidServerResponse = 12152, // ERROR_WINHTTP_INVALID_SERVER_RESPONSE
InvalidHeader = 12153, // ERROR_WINHTTP_INVALID_HEADER
InvalidQueryRequest = 12154, // ERROR_WINHTTP_INVALID_QUERY_REQUEST
HeaderAlreadyExists = 12155, // ERROR_WINHTTP_HEADER_ALREADY_EXISTS
RedirectFailed = 12156, // ERROR_WINHTTP_REDIRECT_FAILED
AutoProxyServiceError = 12178, // ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR
BadAutoProxyScript = 12166, // ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT
UnableToDownloadScript = 12167, // ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT
NotInitialized = 12172, // ERROR_WINHTTP_NOT_INITIALIZED
SecureFailure = 12175, // ERROR_WINHTTP_SECURE_FAILURE
SecureCertDateInvalid = 12037, // ERROR_WINHTTP_SECURE_CERT_DATE_INVALID
SecureCertCNInvalid = 12038, // ERROR_WINHTTP_SECURE_CERT_CN_INVALID
SecureInvalidCA = 12045, // ERROR_WINHTTP_SECURE_INVALID_CA
SecureCertRevFailed = 12057, // ERROR_WINHTTP_SECURE_CERT_REV_FAILED
SecureChannelError = 12157, // ERROR_WINHTTP_SECURE_CHANNEL_ERROR
SecureInvalidCert = 12169, // ERROR_WINHTTP_SECURE_INVALID_CERT
SecureCertRevoked = 12170, // ERROR_WINHTTP_SECURE_CERT_REVOKED
SecureCertWrongUsage = 12179, // ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE
AudodetectionFailed = 12180, // ERROR_WINHTTP_AUTODETECTION_FAILED
HeaderCountExceeded = 12181, // ERROR_WINHTTP_HEADER_COUNT_EXCEEDED
HeaderSizeOverflow = 12182, // ERROR_WINHTTP_HEADER_SIZE_OVERFLOW
ChunkedEncodingHeaderSizeOverflow = 12183, // ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW
ResponseDrainOverflow = 12184, // ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW
ClientCertNoPrivateKey = 12185, // ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY
ClientCertNoAccessPrivateKey = 12186, // ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY
}
}
//
// Caching (must use WinInet to cache).
//
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
internal static class UnsafeWinInetCache {
public const int MAX_PATH = 260;
[DllImport(WININET, CharSet = CharSet.Unicode, ExactSpelling=true, SetLastError = true)]
internal static extern bool CreateUrlCacheEntryW(
[In] string urlName,
[In] int expectedFileSize,
[In] string fileExtension,
[Out] System.Text.StringBuilder fileName,
[In] int dwReserved
);
[DllImport(WININET, CharSet = CharSet.Unicode, ExactSpelling=true, SetLastError = true)]
unsafe internal static extern bool CommitUrlCacheEntryW(
[In] string urlName,
[In] string localFileName,
[In] _WinInetCache.FILETIME expireTime,
[In] _WinInetCache.FILETIME lastModifiedTime,
[In] _WinInetCache.EntryType EntryType,
[In] byte* headerInfo,
[In] int headerSizeTChars,
[In] string fileExtension,
[In] string originalUrl
);
[DllImport(WININET, CharSet = CharSet.Unicode, ExactSpelling=true, SetLastError = true)]
unsafe internal static extern bool GetUrlCacheEntryInfoW(
[In] string urlName,
[In] byte* entryPtr, //was [Out]
[In, Out] ref int bufferSz
);
[DllImport(WININET, CharSet = CharSet.Unicode, ExactSpelling=true, SetLastError = true)]
unsafe internal static extern bool SetUrlCacheEntryInfoW(
[In] string lpszUrlName,
[In] byte* EntryPtr,
[In] _WinInetCache.Entry_FC fieldControl
);
[DllImport(WININET, CharSet = CharSet.Unicode, ExactSpelling=true, SetLastError = true)]
internal static extern bool DeleteUrlCacheEntryW( [In] string urlName);
[DllImport(WININET, CharSet = CharSet.Unicode, ExactSpelling=true, SetLastError = true)]
internal static extern bool UnlockUrlCacheEntryFileW(
[In] string urlName,
[In] int dwReserved //must be 0
);
/*********
NOT USED SO FAR
unsafe private extern static SafeUnlockUrlCacheEntryStream RetrieveUrlCacheEntryStream(
[In] string urlName,
[In] byte* entryPtr, //was [Out]
[In, Out] ref int entryBufSize,
[In] bool randomRead,
[In] int dwReserved
);
unsafe internal static extern bool ReadUrlCacheEntryStream(
[In] SafeUnlockUrlCacheEntryStream urlCacheStream,
[In] int offset,
[In] byte* bufferPtr,
[In, Out] ref int bufferSz,
[In] int dwReserved //must be 0
);
internal static extern bool UnlockUrlCacheEntryStream(
[In] IntPtr urlCacheStream,
[In] int dwReserved //mustbe 0
);
unsafe internal static extern bool GetUrlCacheEntryInfoEx(
[In] string url,
[In] byte* entryPtr, //was [Out]
[In, Out] ref int entryBufSize,
[In] IntPtr lpszReserved, //was[Out] must pass null
[In] IntPtr lpdwReserved, //was[In, Out] must pass null
[In] IntPtr lpReserved, //must pass null
[In] int dwFlags //reserved must be 0
);
internal static extern IntPtr FindFirstUrlCacheGroup(
[In] _WinInetCache.GroupFlag flags,
[In] _WinInetCache.GroupSrchType searchFilter,
[In] IntPtr searchConditionPtr, //must be null
[In] int searchConditionSz, //must be 0
[Out] out WinInet.GroupId groupId,
[In] IntPtr lpReserved //was [In,Out] must be IntPtr.Zero
);
internal static extern bool FindNextUrlCacheGroup(
[In] IntPtr hFind,
[Out] out _WinInetCache.GroupId groupId,
[In] IntPtr lpReserved //was [In,Out] must be IntPtr.Zero
);
internal static extern bool GetUrlCacheGroupAttribute(
[In] _WinInetCache.GroupId groupId,
[In] int flags, //must 0
[In] _WinInetCache.GroupAttr attr,
[Out] out _WinInetCache.GroupInfo groupInfo,
[In, Out] ref int groupInfoSize,
[In] IntPtr lpReserved //was [In,Out] must be IntPtr.Zero
);
internal static extern bool SetUrlCacheGroupAttribute(
[In] _WinInetCache.GroupId groupId,
[In] int flags, //must be 0
[In] _WinInetCache.GroupAttr attr,
[In] _WinInetCache.GroupInfo groupInfo,
[In] IntPtr lpReserved //was [In,Out] must be IntPtr.Zero
);
internal static extern WinInet.GroupId CreateUrlCacheGroup(
[In] _WinInetCache.GroupFlag flags,
[In] IntPtr lpReserved //must be IntPtr.Zero
);
internal static extern bool DeleteUrlCacheGroup(
[In] _WinInetCache.GroupId groupId,
[In] _WinInetCache.GroupFlag flags,
[In] IntPtr lpReserved //must be IntPtr.Zero
);
internal static extern bool SetUrlCacheEntryGroup(
[In] string urlName,
[In] _WinInetCache.GroupSetFlag flags,
[In] _WinInetCache.GroupId groupId,
[In] IntPtr groupAttributes, // must pass NULL
[In] int groupAttrCount, // must pass 0
[In] IntPtr lpReserved // must pass NULL
);
unsafe internal static extern IntPtr FindFirstUrlCacheEntryEx(
[In] byte* searchPattern, //must be null
[In] int dwFlags, //must be 0
[In] CacheEntry.EntryType srchFilter,
[In] WinInet.GroupId groupId,
[In] byte* entryPtr, //was [out]
[In, Out] ref int entryBufSize,
[Out] void* lpReserved, // must pass NULL
[In] void* lpReserved2, //was [In,Out] must be IntPtr.Zero
[In] void* lpReserved3 // must pass NULL
);
unsafe internal static extern bool FindNextUrlCacheEntryEx(
[In] IntPtr enumHandle,
[In] byte* entryPtr, //was [Out]
[In, Out]ref int entryBufSize,
[In] void* lpReserved, // [Out] must pass NULL
[In] void* lpReserved2, // [In] [Out] must pass NULL
[In] void* lpReserved3 // must pass NULL
);
unsafe internal static extern IntPtr FindFirstUrlCacheEntry(
[In] string searchPattern,
[In] byte* entryPtr, //was [Out]
[In, Out]ref int entryBufSize
);
unsafe internal static extern bool FindNextUrlCacheEntry(
[In] IntPtr enumHandle,
[In] byte* entryPtr, //was [Out]
[In, Out]ref int entryBufSize
);
internal static extern bool FindCloseUrlCache( [In] IntPtr enumHandle);
/**********/
}
[SuppressUnmanagedCodeSecurityAttribute]
internal static class SspiHelper
{
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal unsafe static extern SecurityStatus SspiFreeAuthIdentity(
[In] IntPtr authData);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
internal unsafe static extern SecurityStatus SspiEncodeStringsAsAuthIdentity(
[In] string userName,
[In] string domainName,
[In] string password,
[Out] out SafeSspiAuthDataHandle authData);
}
#endif // !FEATURE_PAL
#if !FEATURE_PAL
[System.Security.SuppressUnmanagedCodeSecurityAttribute()]
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(CriticalHandle requestQueueHandle, ulong requestId, uint flags, void* pEntityBuffer, uint entityBufferLength, out uint bytesReturned, NativeOverlapped* pOverlapped);
[DllImport(HTTPAPI, EntryPoint = "HttpReceiveRequestEntityBody", ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern uint HttpReceiveRequestEntityBody2(CriticalHandle requestQueueHandle, ulong requestId, uint flags, void* pEntityBuffer, uint entityBufferLength, out uint bytesReturned, [In] SafeHandle pOverlapped);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling=true, CallingConvention=CallingConvention.StdCall, SetLastError=true)]
internal static extern uint HttpReceiveClientCertificate(CriticalHandle requestQueueHandle, ulong connectionId, uint flags, HTTP_SSL_CLIENT_CERT_INFO* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling=true, CallingConvention=CallingConvention.StdCall, SetLastError=true)]
internal static extern uint HttpReceiveClientCertificate(CriticalHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling=true, CallingConvention=CallingConvention.StdCall, SetLastError=true)]
internal static extern uint HttpReceiveHttpRequest(CriticalHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, NativeOverlapped* pOverlapped);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling=true, CallingConvention=CallingConvention.StdCall, SetLastError=true)]
internal static extern uint HttpSendHttpResponse(CriticalHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE* pHttpResponse, void* pCachePolicy, uint* pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling=true, CallingConvention=CallingConvention.StdCall, SetLastError=true)]
internal static extern uint HttpSendResponseEntityBody(CriticalHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, HTTP_DATA_CHUNK* pEntityChunks, uint* pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern uint HttpCancelHttpRequest(CriticalHandle requestQueueHandle, ulong requestId, IntPtr pOverlapped);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, EntryPoint = "HttpSendResponseEntityBody", ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern uint HttpSendResponseEntityBody2(CriticalHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, IntPtr pEntityChunks, out uint pBytesSent, SafeLocalFree pRequestBuffer, uint requestBufferLength, SafeHandle pOverlapped, IntPtr pLogData);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling=true, CallingConvention=CallingConvention.StdCall, SetLastError=true)]
internal static extern uint HttpWaitForDisconnect(CriticalHandle requestQueueHandle, ulong connectionId, NativeOverlapped* pOverlapped);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern uint HttpCreateServerSession(HTTPAPI_VERSION version, ulong* serverSessionId, uint reserved);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern uint HttpCreateUrlGroup(ulong serverSessionId, ulong* urlGroupId, uint reserved);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[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);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern uint HttpSetUrlGroupProperty(ulong urlGroupId, HTTP_SERVER_PROPERTY serverProperty, IntPtr pPropertyInfo, uint propertyInfoLength);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[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);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern uint HttpCloseUrlGroup(ulong urlGroupId);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(TOKENBINDING, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, EntryPoint="TokenBindingVerifyMessage")]
public static extern int TokenBindingVerifyMessage(
[In] byte* tokenBindingMessage,
[In] uint tokenBindingMessageSize,
[In] TOKENBINDING_KEY_PARAMETERS_TYPE keyType,
[In] byte* tlsUnique,
[In] uint tlsUniqueSize,
[Out] out HeapAllocHandle resultList);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(TOKENBINDING, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, EntryPoint="TokenBindingVerifyMessage")]
public static extern int TokenBindingVerifyMessage_V1(
[In] byte* tokenBindingMessage,
[In] uint tokenBindingMessageSize,
[In] IntPtr keyType,
[In] byte* tlsUnique,
[In] uint tlsUniqueSize,
[Out] out HeapAllocHandle resultList);
internal sealed class HeapAllocHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private static readonly IntPtr ProcessHeap = GetProcessHeap();
// Called by P/Invoke when returning SafeHandles.
private HeapAllocHandle()
: base(ownsHandle: true)
{
}
// Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you.
protected override bool ReleaseHandle()
{
return HeapFree(ProcessHeap, 0, handle);
}
}
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,
}
internal enum HTTP_REQUEST_INFO_TYPE {
HttpRequestInfoTypeAuth,
HttpRequestInfoTypeChannelBind,
HttpRequestInfoTypeSslProtocol,
HttpRequestInfoTypeSslTokenBindingDraft,
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.Sequential, Size=32)]
internal struct HTTP_DATA_CHUNK {
internal HTTP_DATA_CHUNK_TYPE DataChunkType;
internal uint p0;
internal byte* pBuffer;
internal uint BufferLength;
}
[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;
}
[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 void* 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;
internal ushort ResponseInfoCount;
internal HTTP_RESPONSE_INFO* pResponseInfo;
}
[StructLayout(LayoutKind.Sequential)]
internal struct HTTP_REQUEST_INFO {
internal HTTP_REQUEST_INFO_TYPE InfoType;
internal uint InfoLength;
internal void* 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 RequestV1;
internal ushort RequestInfoCount;
internal HTTP_REQUEST_INFO* pRequestInfo;
}
[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;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct HTTP_REQUEST_TOKEN_BINDING_INFO
{
public byte* TokenBinding;
public uint TokenBindingSize;
public byte* TlsUnique;
public uint TlsUniqueSize;
public TOKENBINDING_KEY_PARAMETERS_TYPE KeyType;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct HTTP_REQUEST_TOKEN_BINDING_INFO_V1
{
public byte* TokenBinding;
public uint TokenBindingSize;
public byte* TlsUnique;
public uint TlsUniqueSize;
public IntPtr KeyType;
}
internal enum TOKENBINDING_HASH_ALGORITHM_V1 : byte
{
TOKENBINDING_HASH_ALGORITHM_SHA256 = 4,
}
internal enum TOKENBINDING_SIGNATURE_ALGORITHM_V1 : byte
{
TOKENBINDING_SIGNATURE_ALGORITHM_RSA = 1,
TOKENBINDING_SIGNATURE_ALGORITHM_ECDSAP256 = 3,
}
internal enum TOKENBINDING_TYPE : byte
{
TOKENBINDING_TYPE_PROVIDED = 0,
TOKENBINDING_TYPE_REFERRED = 1,
}
internal enum TOKENBINDING_EXTENSION_FORMAT
{
TOKENBINDING_EXTENSION_FORMAT_UNDEFINED = 0,
}
internal enum TOKENBINDING_KEY_PARAMETERS_TYPE : byte
{
TOKENBINDING_KEY_PARAMETERS_TYPE_RSA_PKCS_SHA256 = 0,
TOKENBINDING_KEY_PARAMETERS_TYPE_RSA_PSS_SHA256 = 1,
TOKENBINDING_KEY_PARAMETERS_TYPE_ECDSA_SHA256 = 2,
}
[StructLayout(LayoutKind.Sequential)]
internal struct TOKENBINDING_IDENTIFIER
{
public TOKENBINDING_KEY_PARAMETERS_TYPE keyType;
}
[StructLayout(LayoutKind.Sequential)]
internal struct TOKENBINDING_IDENTIFIER_V1
{
public TOKENBINDING_TYPE bindingType;
public TOKENBINDING_HASH_ALGORITHM_V1 hashAlgorithm;
public TOKENBINDING_SIGNATURE_ALGORITHM_V1 signatureAlgorithm;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct TOKENBINDING_RESULT_DATA
{
public TOKENBINDING_TYPE bindingType;
public uint identifierSize;
public TOKENBINDING_IDENTIFIER* identifierData;
public TOKENBINDING_EXTENSION_FORMAT extensionFormat;
public uint extensionSize;
public IntPtr extensionData;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct TOKENBINDING_RESULT_DATA_V1
{
public uint identifierSize;
public TOKENBINDING_IDENTIFIER_V1* identifierData;
public TOKENBINDING_EXTENSION_FORMAT extensionFormat;
public uint extensionSize;
public IntPtr extensionData;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct TOKENBINDING_RESULT_LIST
{
public uint resultCount;
public TOKENBINDING_RESULT_DATA* resultData;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct TOKENBINDING_RESULT_LIST_V1
{
public uint resultCount;
public TOKENBINDING_RESULT_DATA_V1* resultData;
}
// 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,
}
const int HttpHeaderRequestMaximum = (int)HttpRequestHeader.UserAgent + 1;
const int HttpHeaderResponseMaximum = (int)HttpResponseHeader.WwwAuthenticate + 1;
internal static class HTTP_REQUEST_HEADER_ID {
internal static string ToString(int position) {
return m_Strings[position];
}
private static string[] m_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 Hashtable m_Hashtable;
static HTTP_RESPONSE_HEADER_ID() {
m_Hashtable = new Hashtable((int)Enum.HttpHeaderResponseMaximum);
for (int i = 0; i < (int)Enum.HttpHeaderResponseMaximum; i++) {
m_Hashtable.Add(m_Strings[i], i);
}
}
internal static int IndexOfKnownHeader(string HeaderName) {
object index = m_Hashtable[HeaderName];
return index==null ? -1 : (int)index;
}
internal static string ToString(int position) {
return m_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 string[] m_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 HTTPAPI_VERSION version;
private static volatile bool extendedProtectionSupported;
//
// 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;
}
}
}
//
// returns 'true' if http.sys supports CBT: either the system is Win7+, or http.sys was patched.
//
internal static bool ExtendedProtectionSupported {
get {
return extendedProtectionSupported;
}
}
static HttpApi() {
InitHttpApi(2, 0);
}
private static void InitHttpApi(ushort majorVersion, ushort minorVersion) {
version.HttpApiMajorVersion = majorVersion;
version.HttpApiMinorVersion = minorVersion;
GlobalLog.Print("HttpApi::.ctor() calling HttpApi.HttpInitialize() for Version " + majorVersion + "." + minorVersion);
// For pre-Win7 OS versions, we need to check whether http.sys contains the CBT patch.
// We do so by passing HTTP_INITIALIZE_CBT flag to HttpInitialize. If the flag is not
// supported, http.sys is not patched. Note that http.sys will return invalid parameter
// also on Win7, even though it shipped with CBT support. Therefore we must not pass
// the flag on Win7 and later.
uint statusCode = ErrorCodes.ERROR_SUCCESS;
extendedProtectionSupported = true;
if (ComNetOS.IsWin7orLater) {
// on Win7 and later, we don't pass the CBT flag. CBT is always supported.
statusCode = HttpApi.HttpInitialize(version, (uint)HTTP_FLAGS.HTTP_INITIALIZE_SERVER, null);
}
else {
statusCode = HttpApi.HttpInitialize(version,
(uint)(HTTP_FLAGS.HTTP_INITIALIZE_SERVER | HTTP_FLAGS.HTTP_INITIALIZE_CBT), null);
// if the status code is INVALID_PARAMETER, http.sys does not support CBT.
if (statusCode == ErrorCodes.ERROR_INVALID_PARAMETER) {
if (Logging.On) Logging.PrintWarning(Logging.HttpListener, SR.GetString(SR.net_listener_cbt_not_supported));
// try again without CBT flag: HttpListener can still be used, but doesn't support EP
extendedProtectionSupported = false;
statusCode = HttpApi.HttpInitialize(version, (uint)HTTP_FLAGS.HTTP_INITIALIZE_SERVER, null);
}
}
supported = statusCode == ErrorCodes.ERROR_SUCCESS;
GlobalLog.Print("HttpApi::.ctor() call to HttpApi.HttpInitialize() returned:" + statusCode + " supported:" + supported);
}
static volatile bool supported;
internal static bool Supported {
get {
return supported;
}
}
// Server API
internal static WebHeaderCollection GetHeaders(byte[] memoryBlob, IntPtr originalAddress)
{
GlobalLog.Enter("HttpApi::GetHeaders()");
// Return value.
WebHeaderCollection headerCollection = new WebHeaderCollection(WebHeaderCollectionType.HttpListenerRequest);
fixed (byte* pMemoryBlob = memoryBlob)
{
HTTP_REQUEST* request = (HTTP_REQUEST*) pMemoryBlob;
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 = new string(pUnknownHeader->pName + fixup, 0, pUnknownHeader->NameLength);
string headerValue;
if (pUnknownHeader->pRawValue != null && pUnknownHeader->RawValueLength > 0) {
headerValue = new string(pUnknownHeader->pRawValue + fixup, 0, pUnknownHeader->RawValueLength);
}
else {
headerValue = string.Empty;
}
headerCollection.AddInternal(headerName, headerValue);
}
pUnknownHeader++;
}
}
// known headers
HTTP_KNOWN_HEADER* pKnownHeader = &request->Headers.KnownHeaders;
for (index = 0; index < HttpHeaderRequestMaximum; index++)
{
// For known headers, when header value is empty, RawValueLength will be 0 and
// pRawValue will point to empty string ("\0")
if (pKnownHeader->pRawValue != null)
{
string headerValue = new string(pKnownHeader->pRawValue + fixup, 0, pKnownHeader->RawValueLength);
headerCollection.AddInternal(HTTP_REQUEST_HEADER_ID.ToString(index), headerValue);
}
pKnownHeader++;
}
}
GlobalLog.Leave("HttpApi::GetHeaders()");
return headerCollection;
}
private static string GetKnownHeader(HTTP_REQUEST* request, long fixup, int headerIndex)
{
GlobalLog.Enter("HttpApi::GetKnownHeader()");
string header = null;
HTTP_KNOWN_HEADER* pKnownHeader = (&request->Headers.KnownHeaders) + headerIndex;
GlobalLog.Print("HttpApi::GetKnownHeader() pKnownHeader:0x" + ((IntPtr) pKnownHeader).ToString("x"));
GlobalLog.Print("HttpApi::GetKnownHeader() pRawValue:0x" + ((IntPtr) pKnownHeader->pRawValue).ToString("x") + " RawValueLength:" + pKnownHeader->RawValueLength.ToString());
// 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 = new string(pKnownHeader->pRawValue + fixup, 0, pKnownHeader->RawValueLength);
}
GlobalLog.Leave("HttpApi::GetKnownHeader() return:" + ValidationHelper.ToString(header));
return header;
}
internal static string GetKnownHeader(HTTP_REQUEST* request, int headerIndex)
{
return GetKnownHeader(request, 0, headerIndex);
}
internal static string GetKnownHeader(byte[] memoryBlob, IntPtr originalAddress, int headerIndex)
{
fixed (byte* pMemoryBlob = memoryBlob)
{
return GetKnownHeader((HTTP_REQUEST*) pMemoryBlob, pMemoryBlob - (byte*) originalAddress, headerIndex);
}
}
private unsafe static string GetVerb(HTTP_REQUEST* request, long fixup)
{
GlobalLog.Enter("HttpApi::GetVerb()");
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 = new string(request->pUnknownVerb + fixup, 0, request->UnknownVerbLength);
}
GlobalLog.Leave("HttpApi::GetVerb() return:" + ValidationHelper.ToString(verb));
return verb;
}
internal unsafe static string GetVerb(HTTP_REQUEST* request)
{
return GetVerb(request, 0);
}
internal unsafe static string GetVerb(byte[] memoryBlob, IntPtr originalAddress)
{
fixed (byte* pMemoryBlob = memoryBlob)
{
return GetVerb((HTTP_REQUEST*) pMemoryBlob, pMemoryBlob - (byte*) originalAddress);
}
}
internal static HTTP_VERB GetKnownVerb(byte[] memoryBlob, IntPtr originalAddress)
{
GlobalLog.Enter("HttpApi::GetKnownVerb()");
// Return value.
HTTP_VERB verb = HTTP_VERB.HttpVerbUnknown;
fixed (byte* pMemoryBlob = memoryBlob)
{
HTTP_REQUEST* request = (HTTP_REQUEST*) pMemoryBlob;
if ((int)request->Verb > (int)HTTP_VERB.HttpVerbUnparsed && (int)request->Verb < (int)HTTP_VERB.HttpVerbMaximum)
{
verb = request->Verb;
}
}
GlobalLog.Leave("HttpApi::GetKnownVerb()");
return verb;
}
internal static uint GetChunks(byte[] memoryBlob, IntPtr originalAddress, ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size)
{
GlobalLog.Enter("HttpApi::GetChunks() memoryBlob:" + ValidationHelper.ToString(memoryBlob));
// Return value.
uint dataRead = 0;
fixed(byte* pMemoryBlob = memoryBlob)
{
HTTP_REQUEST* request = (HTTP_REQUEST*) pMemoryBlob;
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->BufferLength){
dataChunkOffset = 0;
dataChunkIndex ++;
pDataChunk++;
}
else{
byte* pFrom = pDataChunk->pBuffer + dataChunkOffset + fixup;
uint bytesToRead = pDataChunk->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;
}
}
GlobalLog.Leave("HttpApi::GetChunks()");
return dataRead;
}
internal static IPEndPoint GetRemoteEndPoint(byte[] memoryBlob, IntPtr originalAddress)
{
GlobalLog.Enter("HttpApi::GetRemoteEndPoint()");
SocketAddress v4address = new SocketAddress(AddressFamily.InterNetwork, SocketAddress.IPv4AddressSize);
SocketAddress v6address = new SocketAddress(AddressFamily.InterNetworkV6, SocketAddress.IPv6AddressSize);
fixed (byte* pMemoryBlob = memoryBlob)
{
HTTP_REQUEST* request = (HTTP_REQUEST*) pMemoryBlob;
IntPtr address = request->Address.pRemoteAddress != null ? (IntPtr) (pMemoryBlob - (byte*) originalAddress + (byte*) request->Address.pRemoteAddress) : IntPtr.Zero;
CopyOutAddress(address, ref v4address, ref v6address);
}
IPEndPoint endpoint = null;
if (v4address != null)
{
endpoint = IPEndPoint.Any.Create(v4address) as IPEndPoint;
}
else if (v6address != null)
{
endpoint = IPEndPoint.IPv6Any.Create(v6address) as IPEndPoint;
}
GlobalLog.Leave("HttpApi::GetRemoteEndPoint()");
return endpoint;
}
internal static IPEndPoint GetLocalEndPoint(byte[] memoryBlob, IntPtr originalAddress)
{
GlobalLog.Enter("HttpApi::GetLocalEndPoint()");
SocketAddress v4address = new SocketAddress(AddressFamily.InterNetwork, SocketAddress.IPv4AddressSize);
SocketAddress v6address = new SocketAddress(AddressFamily.InterNetworkV6, SocketAddress.IPv6AddressSize);
fixed (byte* pMemoryBlob = memoryBlob)
{
HTTP_REQUEST* request = (HTTP_REQUEST*) pMemoryBlob;
IntPtr address = request->Address.pLocalAddress != null ? (IntPtr) (pMemoryBlob - (byte*) originalAddress + (byte*) request->Address.pLocalAddress) : IntPtr.Zero;
CopyOutAddress(address, ref v4address, ref v6address);
}
IPEndPoint endpoint = null;
if (v4address != null)
{
endpoint = IPEndPoint.Any.Create(v4address) as IPEndPoint;
}
else if (v6address != null)
{
endpoint = IPEndPoint.IPv6Any.Create(v6address) as IPEndPoint;
}
GlobalLog.Leave("HttpApi::GetLocalEndPoint()");
return endpoint;
}
/// <summary>
/// Method to acquire the V2 token binding
/// We tell the difference between a V1 binding and a V2 binding by looking at the HTTP_REQUEST_INFO_TYPE returned from the HTTP request blob
/// If we negotiated the new binding type, the value 'HttpRequestInfoTypeSslTokenBinding' will be returned.
/// </summary>
/// <param name="memoryBlob"></param>
/// <param name="originalAddress"></param>
/// <returns></returns>
internal static HTTP_REQUEST_TOKEN_BINDING_INFO* GetTlsTokenBindingRequestInfo(byte[] memoryBlob, IntPtr originalAddress)
{
fixed (byte* pMemoryBlob = memoryBlob)
{
HTTP_REQUEST_V2* request = (HTTP_REQUEST_V2*)pMemoryBlob;
long fixup = pMemoryBlob - (byte*) originalAddress;
for (int i = 0; i < request->RequestInfoCount; i++)
{
HTTP_REQUEST_INFO* pThisInfo = (HTTP_REQUEST_INFO*)(fixup + (byte*)&request->pRequestInfo[i]);
if (pThisInfo != null && pThisInfo->InfoType == HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslTokenBinding)
{
return (HTTP_REQUEST_TOKEN_BINDING_INFO*)((byte*)(pThisInfo->pInfo) + fixup);
}
}
}
return null;
}
/// <summary>
/// Compat method to acquire the old V1 token binding
/// We tell the difference between a V1 binding and a V2 binding by looking at the HTTP_REQUEST_INFO_TYPE returned from the HTTP request blob
/// If we negotiated the old binding type, the value 'HttpRequestInfoTypeSslTokenBindingDraft' will be returned.
/// </summary>
/// <param name="memoryBlob"></param>
/// <param name="originalAddress"></param>
/// <returns></returns>
internal static HTTP_REQUEST_TOKEN_BINDING_INFO_V1* GetTlsTokenBindingRequestInfo_V1(byte[] memoryBlob, IntPtr originalAddress)
{
fixed (byte* pMemoryBlob = memoryBlob)
{
HTTP_REQUEST_V2* request = (HTTP_REQUEST_V2*)pMemoryBlob;
long fixup = pMemoryBlob - (byte*)originalAddress;
for (int i = 0; i < request->RequestInfoCount; i++)
{
HTTP_REQUEST_INFO* pThisInfo = (HTTP_REQUEST_INFO*)(fixup + (byte*)&request->pRequestInfo[i]);
if (pThisInfo != null && pThisInfo->InfoType == HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslTokenBindingDraft)
{
// Old V1 token binding protocol is being used, so we need to handle this data blob using the old behavior
return (HTTP_REQUEST_TOKEN_BINDING_INFO_V1*)((byte*)(pThisInfo->pInfo) + fixup);
}
}
}
return null;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
private static void CopyOutAddress(IntPtr address, ref SocketAddress v4address, ref SocketAddress v6address)
{
if (address != IntPtr.Zero)
{
ushort addressFamily = *((ushort*) address);
if (addressFamily == (ushort) AddressFamily.InterNetwork)
{
v6address = null;
fixed (byte* pBuffer = v4address.m_Buffer)
{
for (int index = 2; index < SocketAddress.IPv4AddressSize; index++)
{
pBuffer[index] = ((byte*) address)[index];
}
}
return;
}
if (addressFamily == (ushort) AddressFamily.InterNetworkV6)
{
v4address = null;
fixed (byte* pBuffer = v6address.m_Buffer)
{
for (int index = 2; index < SocketAddress.IPv6AddressSize; index++)
{
pBuffer[index] = ((byte*) address)[index];
}
}
return;
}
}
v4address = null;
v6address = null;
}
}
[SuppressUnmanagedCodeSecurity]
internal unsafe static class SecureStringHelper
{
#if DEBUG
// this method is only called as part of an assert
internal static bool AreEqualValues(SecureString secureString1, SecureString secureString2)
{
IntPtr bstr1 = IntPtr.Zero;
IntPtr bstr2 = IntPtr.Zero;
bool result = false;
if (secureString1 == null)
{
if (secureString2 == null)
return true;
else
return false;
}
else if (secureString2 == null)
{
return false;
}
// strings are non-null at this point
if ((object)secureString1 == (object)secureString2)
return true; // same objects
if (secureString1.Length != secureString2.Length)
return false;
// strings are same length. decrypt to unmanaged memory and compare them.
try
{
bstr1 = Marshal.SecureStringToBSTR(secureString1);
bstr2 = Marshal.SecureStringToBSTR(secureString2);
result = true;
for (int i = 0; i < secureString1.Length; i++)
{
if (*((char*)bstr1 + i) != *((char*)bstr2 + i))
{
result = false;
break;
}
}
}
finally
{
if (bstr1 != IntPtr.Zero)
Marshal.ZeroFreeBSTR(bstr1);
if (bstr2 != IntPtr.Zero)
Marshal.ZeroFreeBSTR(bstr2);
}
return result;
}
#endif
internal static string CreateString(SecureString secureString)
{
string plainString;
IntPtr bstr = IntPtr.Zero;
if (secureString == null || secureString.Length == 0)
return String.Empty;
try
{
bstr = Marshal.SecureStringToBSTR(secureString);
plainString = Marshal.PtrToStringBSTR(bstr);
}
finally
{
if (bstr != IntPtr.Zero)
Marshal.ZeroFreeBSTR(bstr);
}
return plainString;
}
internal static SecureString CreateSecureString(string plainString)
{
SecureString secureString;
if (plainString == null || plainString.Length == 0)
return new SecureString();
fixed (char* pch = plainString)
{
secureString = new SecureString(pch, plainString.Length);
}
return secureString;
}
}
#endif // !FEATURE_PAL
#if !FEATURE_PAL
internal const int CLSCTX_SERVER = 0x15;
[DllImport(OLE32, PreserveSig=false)]
public static extern void CoCreateInstance(
[In] ref Guid clsid,
IntPtr pUnkOuter,
int context,
[In] ref Guid iid,
[MarshalAs(UnmanagedType.IUnknown)] out Object o );
#endif // !FEATURE_PAL
// Used to support Windows Store apps.
// This code was provided by Immo Landwerth from the CLR team.
[FriendAccessAllowed]
internal class AppXHelper
{
[SecuritySafeCritical]
internal static Lazy<IntPtr> PrimaryWindowHandle = new Lazy<IntPtr>(() => GetPrimaryWindowHandle());
[SecuritySafeCritical]
[SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults",
MessageId = "System.Net.UnsafeNclNativeMethods+AppXHelper.GetWindowThreadProcessId(System.IntPtr,System.Int32@)",
Justification = "The return value of is the thread ID that created the window, not an error code.")]
private static IntPtr GetPrimaryWindowHandle()
{
IntPtr primaryWindow = IntPtr.Zero;
GuiThreadInfo info = new GuiThreadInfo();
info.cbSize = Marshal.SizeOf(info);
// Find the current active window.
if (GetGUIThreadInfo(0, ref info) != 0 && info.hwndActive != IntPtr.Zero)
{
int processId;
// Find the process for that window.
GetWindowThreadProcessId(info.hwndActive, out processId);
// Make sure the current active window belongs to our process.
if (processId == Process.GetCurrentProcess().Id)
{
primaryWindow = info.hwndActive;
}
}
return primaryWindow;
}
[DllImport(USER32, SetLastError=true, ExactSpelling=true)]
private static extern uint GetGUIThreadInfo(int threadId, ref GuiThreadInfo info);
[DllImport(USER32, ExactSpelling=true)]
private static extern uint GetWindowThreadProcessId(IntPtr hwnd, out int processId);
private struct GuiThreadInfo
{
public int cbSize; // Must be set to Marshal.SizeOf(GuiThreadInfo) before using.
public int flags;
public IntPtr hwndActive;
public IntPtr hwndFocus;
public IntPtr hwndCapture;
public IntPtr hwndMenuOwner;
public IntPtr hwndMoveSize;
public IntPtr hwndCaret;
// RECT
public int left;
public int top;
public int right;
public int bottom;
}
}
/// <remarks>
/// Determines whether Token binding is supported on the machine or not
/// This class is thread safe.
/// The static method EnsureTokenBindingOSHelperInitialized is used to get that information.
/// It calls the load library and caches the result under proper locks to make sure it is thread safe and only one call is made to load library.
/// </remarks>
internal static class TokenBindingOSHelper
{
private static bool s_supportsTokenBinding = false;
private static object s_Lock = new object();
private static volatile bool s_Initialized = false;
// <SecurityKernel Critical="True" Ring="0">
// <CallsSuppressUnmanagedCode Name="UnsafeNclNativeMethods.GetProcAddress(System.Net.SafeLoadLibrary,System.String):System.IntPtr" />
// <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
// <ReferencesCritical Name="Method: SafeLoadLibrary.LoadLibraryEx(System.String):System.Net.SafeLoadLibrary" Ring="1" />
// </SecurityKernel>
[System.Security.SecurityCritical]
private static void EnsureTokenBindingOSHelperInitialized()
{
if (s_Initialized)
{
return;
}
lock (s_Lock)
{
if (s_Initialized)
{
return;
}
try
{
// if tokenbinding.dll is not available, TOKENBINDING is not supported
string dllFileName = Path.Combine(Environment.SystemDirectory, TOKENBINDING);
SafeLoadLibrary s_TokenBindingLibrary = SafeLoadLibrary.LoadLibraryEx(dllFileName);
if (!s_TokenBindingLibrary.IsInvalid)
{
s_supportsTokenBinding = s_TokenBindingLibrary.HasFunction("TokenBindingVerifyMessage");
}
s_Initialized = true;
}
catch (Exception e)
{
if (NclUtilities.IsFatal(e))
{
throw;
}
}
}
}
internal static bool SupportsTokenBinding
{
get
{
EnsureTokenBindingOSHelperInitialized();
return s_supportsTokenBinding;
}
}
}
}
}
|