|
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// <OWNER>Microsoft</OWNER>
/*
* This files defines the following types:
* - NativeOverlapped
* - _IOCompletionCallback
* - OverlappedData
* - Overlapped
* - OverlappedDataCache
*/
/*=============================================================================
**
** Class: Overlapped
**
**
** Purpose: Class for converting information to and from the native
** overlapped structure used in asynchronous file i/o
**
**
=============================================================================*/
namespace System.Threading
{
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Runtime.ConstrainedExecution;
using System.Diagnostics.Contracts;
using System.Collections.Concurrent;
#region struct NativeOverlapped
// Valuetype that represents the (unmanaged) Win32 OVERLAPPED structure
// the layout of this structure must be identical to OVERLAPPED.
// The first five matches OVERLAPPED structure.
// The remaining are reserved at the end
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
[System.Runtime.InteropServices.ComVisible(true)]
public struct NativeOverlapped
{
public IntPtr InternalLow;
public IntPtr InternalHigh;
public int OffsetLow;
public int OffsetHigh;
public IntPtr EventHandle;
}
#endregion struct NativeOverlapped
#region class _IOCompletionCallback
unsafe internal class _IOCompletionCallback
{
[System.Security.SecurityCritical] // auto-generated
IOCompletionCallback _ioCompletionCallback;
ExecutionContext _executionContext;
uint _errorCode; // Error code
uint _numBytes; // No. of bytes transferred
[SecurityCritical]
NativeOverlapped* _pOVERLAP;
[System.Security.SecuritySafeCritical] // auto-generated
static _IOCompletionCallback()
{
}
[System.Security.SecurityCritical] // auto-generated
internal _IOCompletionCallback(IOCompletionCallback ioCompletionCallback, ref StackCrawlMark stackMark)
{
_ioCompletionCallback = ioCompletionCallback;
// clone the exection context
_executionContext = ExecutionContext.Capture(
ref stackMark,
ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
}
// Context callback: same sig for SendOrPostCallback and ContextCallback
#if FEATURE_CORECLR
[System.Security.SecurityCritical] // auto-generated
#endif
static internal ContextCallback _ccb = new ContextCallback(IOCompletionCallback_Context);
[System.Security.SecurityCritical]
static internal void IOCompletionCallback_Context(Object state)
{
_IOCompletionCallback helper = (_IOCompletionCallback)state;
Contract.Assert(helper != null,"_IOCompletionCallback cannot be null");
helper._ioCompletionCallback(helper._errorCode, helper._numBytes, helper._pOVERLAP);
}
// call back helper
[System.Security.SecurityCritical] // auto-generated
static unsafe internal void PerformIOCompletionCallback(uint errorCode, // Error code
uint numBytes, // No. of bytes transferred
NativeOverlapped* pOVERLAP // ptr to OVERLAP structure
)
{
Overlapped overlapped;
_IOCompletionCallback helper;
do
{
overlapped = OverlappedData.GetOverlappedFromNative(pOVERLAP).m_overlapped;
helper = overlapped.iocbHelper;
if (helper == null || helper._executionContext == null || helper._executionContext.IsDefaultFTContext(true))
{
// We got here because of UnsafePack (or) Pack with EC flow supressed
IOCompletionCallback callback = overlapped.UserCallback;
callback( errorCode, numBytes, pOVERLAP);
}
else
{
// We got here because of Pack
helper._errorCode = errorCode;
helper._numBytes = numBytes;
helper._pOVERLAP = pOVERLAP;
using (ExecutionContext executionContext = helper._executionContext.CreateCopy())
ExecutionContext.Run(executionContext, _ccb, helper, true);
}
//Quickly check the VM again, to see if a packet has arrived.
OverlappedData.CheckVMForIOPacket(out pOVERLAP, out errorCode, out numBytes);
} while (pOVERLAP != null);
}
}
#endregion class _IOCompletionCallback
#region class OverlappedData
sealed internal class OverlappedData
{
// ! If you make any change to the layout here, you need to make matching change
// ! to OverlappedObject in vm\nativeoverlapped.h
internal IAsyncResult m_asyncResult;
[System.Security.SecurityCritical] // auto-generated
internal IOCompletionCallback m_iocb;
internal _IOCompletionCallback m_iocbHelper;
internal Overlapped m_overlapped;
private Object m_userObject;
private IntPtr m_pinSelf;
private IntPtr m_userObjectInternal;
private int m_AppDomainId;
#pragma warning disable 414 // Field is not used from managed.
#pragma warning disable 169
private byte m_isArray;
private byte m_toBeCleaned;
#pragma warning restore 414
#pragma warning restore 169
internal NativeOverlapped m_nativeOverlapped;
#if FEATURE_CORECLR
// Adding an empty default ctor for annotation purposes
[System.Security.SecuritySafeCritical] // auto-generated
internal OverlappedData(){}
#endif // FEATURE_CORECLR
[System.Security.SecurityCritical]
internal void ReInitialize()
{
m_asyncResult = null;
m_iocb = null;
m_iocbHelper = null;
m_overlapped = null;
m_userObject = null;
Contract.Assert(m_pinSelf.IsNull(), "OverlappedData has not been freed: m_pinSelf");
m_pinSelf = (IntPtr)0;
m_userObjectInternal = (IntPtr)0;
Contract.Assert(m_AppDomainId == 0 || m_AppDomainId == AppDomain.CurrentDomain.Id, "OverlappedData is not in the current domain");
m_AppDomainId = 0;
m_nativeOverlapped.EventHandle = (IntPtr)0;
m_isArray = 0;
m_nativeOverlapped.InternalLow = (IntPtr)0;
m_nativeOverlapped.InternalHigh = (IntPtr)0;
}
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.AppDomain)]
[ResourceConsumption(ResourceScope.AppDomain)]
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
unsafe internal NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData)
{
if (!m_pinSelf.IsNull()) {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_Overlapped_Pack"));
}
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
if (iocb != null)
{
m_iocbHelper = new _IOCompletionCallback(iocb, ref stackMark);
m_iocb = iocb;
}
else
{
m_iocbHelper = null;
m_iocb = null;
}
m_userObject = userData;
if (m_userObject != null)
{
if (m_userObject.GetType() == typeof(Object[]))
{
m_isArray = 1;
}
else
{
m_isArray = 0;
}
}
return AllocateNativeOverlapped();
}
[System.Security.SecurityCritical] // auto-generated_required
[ResourceExposure(ResourceScope.AppDomain)]
[ResourceConsumption(ResourceScope.AppDomain)]
unsafe internal NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData)
{
if (!m_pinSelf.IsNull()) {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_Overlapped_Pack"));
}
m_userObject = userData;
if (m_userObject != null)
{
if (m_userObject.GetType() == typeof(Object[]))
{
m_isArray = 1;
}
else
{
m_isArray = 0;
}
}
m_iocb = iocb;
m_iocbHelper = null;
return AllocateNativeOverlapped();
}
[ComVisible(false)]
internal IntPtr UserHandle
{
get { return m_nativeOverlapped.EventHandle; }
set { m_nativeOverlapped.EventHandle = value; }
}
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.AppDomain)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
unsafe private extern NativeOverlapped* AllocateNativeOverlapped();
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
unsafe internal static extern void FreeNativeOverlapped(NativeOverlapped* nativeOverlappedPtr);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
unsafe internal static extern OverlappedData GetOverlappedFromNative(NativeOverlapped* nativeOverlappedPtr);
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
unsafe internal static extern void CheckVMForIOPacket(out NativeOverlapped* pOVERLAP, out uint errorCode, out uint numBytes);
}
#endregion class OverlappedData
#region class Overlapped
/// <internalonly/>
[System.Runtime.InteropServices.ComVisible(true)]
public class Overlapped
{
private OverlappedData m_overlappedData;
private static PinnableBufferCache s_overlappedDataCache = new PinnableBufferCache("System.Threading.OverlappedData", ()=> new OverlappedData());
#if FEATURE_CORECLR
[System.Security.SecuritySafeCritical] // auto-generated
#endif
public Overlapped()
{
m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate();
m_overlappedData.m_overlapped = this;
}
public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar)
{
m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate();
m_overlappedData.m_overlapped = this;
m_overlappedData.m_nativeOverlapped.OffsetLow = offsetLo;
m_overlappedData.m_nativeOverlapped.OffsetHigh = offsetHi;
m_overlappedData.UserHandle = hEvent;
m_overlappedData.m_asyncResult = ar;
}
[Obsolete("This constructor is not 64-bit compatible. Use the constructor that takes an IntPtr for the event handle. http://go.microsoft.com/fwlink/?linkid=14202")]
public Overlapped(int offsetLo, int offsetHi, int hEvent, IAsyncResult ar) : this(offsetLo, offsetHi, new IntPtr(hEvent), ar)
{
}
public IAsyncResult AsyncResult
{
get { return m_overlappedData.m_asyncResult; }
set { m_overlappedData.m_asyncResult = value; }
}
public int OffsetLow
{
get { return m_overlappedData.m_nativeOverlapped.OffsetLow; }
set { m_overlappedData.m_nativeOverlapped.OffsetLow = value; }
}
public int OffsetHigh
{
get { return m_overlappedData.m_nativeOverlapped.OffsetHigh; }
set { m_overlappedData.m_nativeOverlapped.OffsetHigh = value; }
}
[Obsolete("This property is not 64-bit compatible. Use EventHandleIntPtr instead. http://go.microsoft.com/fwlink/?linkid=14202")]
public int EventHandle
{
get { return m_overlappedData.UserHandle.ToInt32(); }
set { m_overlappedData.UserHandle = new IntPtr(value); }
}
[ComVisible(false)]
public IntPtr EventHandleIntPtr
{
get { return m_overlappedData.UserHandle; }
set { m_overlappedData.UserHandle = value; }
}
internal _IOCompletionCallback iocbHelper
{
get { return m_overlappedData.m_iocbHelper; }
}
internal IOCompletionCallback UserCallback
{
[System.Security.SecurityCritical]
get { return m_overlappedData.m_iocb; }
}
/*====================================================================
* Packs a managed overlapped class into native Overlapped struct.
* Roots the iocb and stores it in the ReservedCOR field of native Overlapped
* Pins the native Overlapped struct and returns the pinned index.
====================================================================*/
[System.Security.SecurityCritical] // auto-generated
[Obsolete("This method is not safe. Use Pack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
[CLSCompliant(false)]
[ResourceExposure(ResourceScope.AppDomain)]
[ResourceConsumption(ResourceScope.AppDomain)]
unsafe public NativeOverlapped* Pack(IOCompletionCallback iocb)
{
return Pack (iocb, null);
}
[System.Security.SecurityCritical] // auto-generated
[CLSCompliant(false),ComVisible(false)]
[ResourceExposure(ResourceScope.AppDomain)]
[ResourceConsumption(ResourceScope.AppDomain)]
unsafe public NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData)
{
return m_overlappedData.Pack(iocb, userData);
}
[System.Security.SecurityCritical] // auto-generated_required
[Obsolete("This method is not safe. Use UnsafePack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
[CLSCompliant(false)]
[ResourceExposure(ResourceScope.AppDomain)]
[ResourceConsumption(ResourceScope.AppDomain)]
unsafe public NativeOverlapped* UnsafePack(IOCompletionCallback iocb)
{
return UnsafePack (iocb, null);
}
[System.Security.SecurityCritical] // auto-generated_required
[CLSCompliant(false), ComVisible(false)]
[ResourceExposure(ResourceScope.AppDomain)]
[ResourceConsumption(ResourceScope.AppDomain)]
unsafe public NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData)
{
return m_overlappedData.UnsafePack(iocb, userData);
}
/*====================================================================
* Unpacks an unmanaged native Overlapped struct.
* Unpins the native Overlapped struct
====================================================================*/
[System.Security.SecurityCritical] // auto-generated
[CLSCompliant(false)]
unsafe public static Overlapped Unpack(NativeOverlapped* nativeOverlappedPtr)
{
if (nativeOverlappedPtr == null)
throw new ArgumentNullException("nativeOverlappedPtr");
Contract.EndContractBlock();
Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped;
return overlapped;
}
[System.Security.SecurityCritical] // auto-generated
[CLSCompliant(false)]
unsafe public static void Free(NativeOverlapped* nativeOverlappedPtr)
{
if (nativeOverlappedPtr == null)
throw new ArgumentNullException("nativeOverlappedPtr");
Contract.EndContractBlock();
Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped;
OverlappedData.FreeNativeOverlapped(nativeOverlappedPtr);
OverlappedData overlappedData = overlapped.m_overlappedData;
overlapped.m_overlappedData = null;
overlappedData.ReInitialize();
s_overlappedDataCache.Free(overlappedData);
}
}
#endregion class Overlapped
} // namespace
|