Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Win32 / SafeHandles / NCryptSafeHandles.cs / 1305376 / NCryptSafeHandles.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Diagnostics.Contracts;
namespace Microsoft.Win32.SafeHandles {
///
/// Base class for NCrypt handles which need to support being pseudo-duplicated. This class is not for
/// external use (instead applications should consume the concrete subclasses of this class).
///
///
/// Since NCrypt handles do not have a native DuplicateHandle type call, we need to do manual
/// reference counting in managed code whenever we hand out an extra reference to one of these handles.
/// This class wraps up the logic to correctly duplicate and free these handles to simluate a native
/// duplication.
///
/// Each open handle object can be thought of as being in one of three states:
/// 1. Owner - created via the marshaler, traditional style safe handle. Notably, only one owner
/// handle exists for a given native handle.
/// 2. Duplicate - points at a handle in the Holder state. Releasing a handle in the duplicate state
/// results only in decrementing the reference count of the holder, not in a release
/// of the native handle.
/// 3. Holder - holds onto a native handle and is referenced by handles in the duplicate state.
/// When all duplicate handles are closed, the holder handle releases the native
/// handle. A holder handle will never be finalized, since this results in a ----
/// between the finalizers of the duplicate handles and the holder handle. Instead,
/// it relies upon all of the duplicate handles to be finalized and decriment the
/// ref count to zero. Instances of a holder handle should never be referenced by
/// anything but a duplicate handle.
///
//
//
//
#pragma warning disable 618 // Have not migrated to v4 transparency yet
[System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
public abstract class SafeNCryptHandle : SafeHandleZeroOrMinusOneIsInvalid {
private enum OwnershipState {
///
/// The safe handle owns the native handle outright. This must be value 0, as this is the
/// state the marshaler will place the handle in when marshaling back a SafeHandle
///
Owner = 0,
///
/// The safe handle does not own the native handle, but points to a Holder which does
///
Duplicate,
///
/// The safe handle owns the native handle, but shares it with other Duplicate handles
///
Holder
}
private OwnershipState m_ownershipState;
///
/// If the handle is a Duplicate, this points at the safe handle which actually owns the native handle.
///
private SafeNCryptHandle m_holder;
protected SafeNCryptHandle() : base(true) {
return;
}
///
/// Wrapper for the m_holder field which ensures that we're in a consistent state
///
private SafeNCryptHandle Holder {
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
get {
Contract.Requires((m_ownershipState == OwnershipState.Duplicate && m_holder != null) ||
(m_ownershipState != OwnershipState.Duplicate && m_holder == null));
Contract.Requires(m_holder == null || m_holder.m_ownershipState == OwnershipState.Holder);
return m_holder;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
set {
Contract.Ensures(m_holder.m_ownershipState == OwnershipState.Holder);
Contract.Ensures(m_ownershipState == OwnershipState.Duplicate);
#if DEBUG
Contract.Ensures(IsValidOpenState);
Contract.Assert(value.IsValidOpenState);
#endif
Contract.Assert(m_ownershipState != OwnershipState.Duplicate);
Contract.Assert(value.m_ownershipState == OwnershipState.Holder);
m_holder = value;
m_ownershipState = OwnershipState.Duplicate;
}
}
#if DEBUG
///
/// Ensure the state of the handle is consistent for an open handle
///
private bool IsValidOpenState {
[Pure]
get {
switch (m_ownershipState) {
// Owner handles do not have a holder
case OwnershipState.Owner:
return Holder == null && !IsInvalid && !IsClosed;
// Duplicate handles have valid open holders with the same raw handle value
case OwnershipState.Duplicate:
bool acquiredHolder = false;
RuntimeHelpers.PrepareConstrainedRegions();
try {
IntPtr holderRawHandle = IntPtr.Zero;
if (Holder != null) {
Holder.DangerousAddRef(ref acquiredHolder);
holderRawHandle = Holder.DangerousGetHandle();
}
bool holderValid = Holder != null &&
!Holder.IsInvalid &&
!Holder.IsClosed &&
holderRawHandle != IntPtr.Zero &&
holderRawHandle == handle;
return holderValid && !IsInvalid && !IsClosed;
}
finally {
if (acquiredHolder) {
Holder.DangerousRelease();
}
}
// Holder handles do not have a holder
case OwnershipState.Holder:
return Holder == null && !IsInvalid && !IsClosed;
// Unknown ownership state
default:
return false;
}
}
}
#endif
///
/// Duplicate a handle
///
///
/// #NCryptHandleDuplicationAlgorithm
///
/// Duplicating a handle performs different operations depending upon the state of the handle:
///
/// * Owner - Allocate two new handles, a holder and a duplicate.
/// - Suppress finalization on the holder
/// - Transition into the duplicate state
/// - Use the new holder as the holder for both this handle and the duplicate
/// - Increment the reference count on the holder
///
/// * Duplicate - Allocate a duplicate handle
/// - Increment the reference count of our holder
/// - Assign the duplicate's holder to be our holder
///
/// * Holder - Specifically disallowed. Holders should only ever be referenced by duplicates,
/// so duplication will occur on the duplicate rather than the holder handle.
///
internal T Duplicate() where T : SafeNCryptHandle, new() {
// Spec#: Consider adding a model variable for ownership state?
Contract.Ensures(Contract.Result() != null);
Contract.Ensures(m_ownershipState == OwnershipState.Duplicate);
Contract.Ensures(Contract.Result().m_ownershipState == OwnershipState.Duplicate);
#if DEBUG
// Spec#: Consider a debug-only? model variable for IsValidOpenState?
Contract.Ensures(Contract.Result().IsValidOpenState);
Contract.Ensures(IsValidOpenState);
Contract.Assert(IsValidOpenState);
#endif
Contract.Assert(m_ownershipState != OwnershipState.Holder);
Contract.Assert(typeof(T) == this.GetType());
if (m_ownershipState == OwnershipState.Owner) {
return DuplicateOwnerHandle();
}
else {
// If we're not an owner handle, and we're being duplicated then we must be a duplicate handle.
return DuplicateDuplicatedHandle();
}
}
///
/// Duplicate a safe handle which is already duplicated.
///
/// See code:Microsoft.Win32.SafeHandles.SafeNCryptHandle#NCryptHandleDuplicationAlgorithm for
/// details about the algorithm.
///
private T DuplicateDuplicatedHandle() where T : SafeNCryptHandle, new() {
Contract.Ensures(m_ownershipState == OwnershipState.Duplicate);
Contract.Ensures(Contract.Result() != null &&
Contract.Result().m_ownershipState == OwnershipState.Duplicate);
#if DEBUG
Contract.Ensures(IsValidOpenState);
Contract.Ensures(Contract.Result().IsValidOpenState);
Contract.Assert(IsValidOpenState);
#endif
Contract.Assert(m_ownershipState == OwnershipState.Duplicate);
Contract.Assert(typeof(T) == this.GetType());
bool addedRef = false;
T duplicate = new T();
// We need to do this operation in a CER, since we need to make sure that if the AddRef occurs
// that the duplicated handle will always point back to the Holder, otherwise the Holder will leak
// since it will never have its ref count reduced to zero.
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally {
Holder.DangerousAddRef(ref addedRef);
duplicate.SetHandle(Holder.DangerousGetHandle());
duplicate.Holder = Holder; // Transitions to OwnershipState.Duplicate
}
return duplicate;
}
///
/// Duplicate a safe handle which is currently the exclusive owner of a native handle
///
/// See code:Microsoft.Win32.SafeHandles.SafeNCryptHandle#NCryptHandleDuplicationAlgorithm for
/// details about the algorithm.
///
private T DuplicateOwnerHandle() where T : SafeNCryptHandle, new() {
Contract.Ensures(m_ownershipState == OwnershipState.Duplicate);
Contract.Ensures(Contract.Result() != null &&
Contract.Result().m_ownershipState == OwnershipState.Duplicate);
#if DEBUG
Contract.Ensures(IsValidOpenState);
Contract.Ensures(Contract.Result().IsValidOpenState);
Contract.Assert(IsValidOpenState);
#endif
Contract.Assert(m_ownershipState == OwnershipState.Owner);
Contract.Assert(typeof(T) == this.GetType());
bool addRef = false;
T holder = new T();
T duplicate = new T();
// We need to do this operation in a CER in order to ensure that everybody's state stays consistent
// with the current view of the world. If the state of the various handles gets out of [....], then
// we'll end up leaking since reference counts will not be set up properly.
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally {
// Setup a holder safe handle to ref count the native handle
holder.m_ownershipState = OwnershipState.Holder;
holder.SetHandle(DangerousGetHandle());
GC.SuppressFinalize(holder);
// Transition into the duplicate state, referencing the holder. The initial reference count
// on the holder will refer to the original handle so there is no need to AddRef here.
Holder = holder; // Transitions to OwnershipState.Duplicate
// The duplicate handle will also reference the holder
holder.DangerousAddRef(ref addRef);
duplicate.SetHandle(holder.DangerousGetHandle());
duplicate.Holder = holder; // Transitions to OwnershipState.Duplicate
}
return duplicate;
}
///
/// Release the handle
///
///
/// Similar to duplication, releasing a handle performs different operations based upon the state
/// of the handle.
///
/// * Owner - Simply call the release P/Invoke method
/// * Duplicate - Decrement the reference count of the current holder
/// * Holder - Call the release P/Invoke. Note that ReleaseHandle on a holder implies a reference
/// count of zero.
///
protected override bool ReleaseHandle() {
if (m_ownershipState == OwnershipState.Duplicate) {
Holder.DangerousRelease();
return true;
}
else {
return ReleaseNativeHandle();
}
}
///
/// Perform the actual release P/Invoke
///
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
protected abstract bool ReleaseNativeHandle();
}
///
/// Safe handle representing an NCRYPT_KEY_HANDLE
///
//
//
//
#pragma warning disable 618 // Have not migrated to v4 transparency yet
[System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
public sealed class SafeNCryptKeyHandle : SafeNCryptHandle {
[DllImport("ncrypt.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
private static extern int NCryptFreeObject(IntPtr hObject);
internal SafeNCryptKeyHandle Duplicate() {
return Duplicate();
}
protected override bool ReleaseNativeHandle() {
return NCryptFreeObject(handle) == 0;
}
}
///
/// Safe handle representing an NCRYPT_PROV_HANDLE
///
//
//
//
#pragma warning disable 618 // Have not migrated to v4 transparency yet
[System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
public sealed class SafeNCryptProviderHandle : SafeNCryptHandle {
[DllImport("ncrypt.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
private static extern int NCryptFreeObject(IntPtr hObject);
internal SafeNCryptProviderHandle Duplicate() {
return Duplicate();
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal void SetHandleValue(IntPtr newHandleValue) {
Contract.Requires(newHandleValue != IntPtr.Zero);
Contract.Requires(!IsClosed);
Contract.Ensures(!IsInvalid);
Contract.Assert(handle == IntPtr.Zero);
SetHandle(newHandleValue);
}
protected override bool ReleaseNativeHandle() {
return NCryptFreeObject(handle) == 0;
}
}
///
/// Safe handle representing an NCRYPT_SECRET_HANDLE
///
//
//
//
#pragma warning disable 618 // Have not migrated to v4 transparency yet
[System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
public sealed class SafeNCryptSecretHandle : SafeNCryptHandle {
[DllImport("ncrypt.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
private static extern int NCryptFreeObject(IntPtr hObject);
protected override bool ReleaseNativeHandle() {
return NCryptFreeObject(handle) == 0;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataControlPagerLinkButton.cs
- ExtensionFile.cs
- DBNull.cs
- TimersDescriptionAttribute.cs
- ClientTargetSection.cs
- HttpResponse.cs
- FragmentQueryProcessor.cs
- ResourceAttributes.cs
- NetStream.cs
- BackStopAuthenticationModule.cs
- MediaPlayer.cs
- LambdaExpression.cs
- NotFiniteNumberException.cs
- NamespaceQuery.cs
- DictionaryTraceRecord.cs
- DbParameterCollectionHelper.cs
- CustomAssemblyResolver.cs
- TextRunProperties.cs
- CodeExpressionStatement.cs
- TypeListConverter.cs
- ProgressBarRenderer.cs
- RectAnimation.cs
- X509SecurityTokenProvider.cs
- DataServiceClientException.cs
- TcpHostedTransportConfiguration.cs
- ToolbarAUtomationPeer.cs
- WindowsHyperlink.cs
- ToolboxBitmapAttribute.cs
- AttachedPropertyMethodSelector.cs
- NonParentingControl.cs
- CodeThrowExceptionStatement.cs
- IndicShape.cs
- BaseCAMarshaler.cs
- InvokePattern.cs
- CodeAttributeDeclaration.cs
- SetStateDesigner.cs
- HostedElements.cs
- SID.cs
- autovalidator.cs
- AsnEncodedData.cs
- HMACRIPEMD160.cs
- BuilderPropertyEntry.cs
- Property.cs
- MasterPageBuildProvider.cs
- GregorianCalendarHelper.cs
- MetaTableHelper.cs
- TemplatePartAttribute.cs
- ReadOnlyTernaryTree.cs
- RootProfilePropertySettingsCollection.cs
- PasswordTextContainer.cs
- DockPatternIdentifiers.cs
- xdrvalidator.cs
- AuthenticatedStream.cs
- Keywords.cs
- CodeTypeConstructor.cs
- Exceptions.cs
- DataServiceRequestArgs.cs
- FileDialogCustomPlace.cs
- ParameterCollectionEditor.cs
- DataGridViewCellEventArgs.cs
- HandledEventArgs.cs
- HeaderFilter.cs
- WebMessageFormatHelper.cs
- UserPreferenceChangedEventArgs.cs
- _BaseOverlappedAsyncResult.cs
- UInt64Converter.cs
- PolyLineSegment.cs
- UserPreference.cs
- AssemblyFilter.cs
- IndependentlyAnimatedPropertyMetadata.cs
- RegexWorker.cs
- EncryptedPackageFilter.cs
- RoutedUICommand.cs
- _Events.cs
- SqlBulkCopyColumnMappingCollection.cs
- DelayedRegex.cs
- DefaultAsyncDataDispatcher.cs
- DiscoveryEndpointValidator.cs
- TypeDescriptionProvider.cs
- TableStyle.cs
- ConstantSlot.cs
- DefaultHttpHandler.cs
- IisTraceListener.cs
- WebPartChrome.cs
- SqlDataSourceFilteringEventArgs.cs
- Bidi.cs
- Root.cs
- ClientTargetSection.cs
- WebBrowserNavigatedEventHandler.cs
- validationstate.cs
- BaseCodePageEncoding.cs
- WindowsEditBox.cs
- XmlArrayItemAttributes.cs
- EntityDataSourceWrapper.cs
- ImmutableDispatchRuntime.cs
- TraceData.cs
- InteropBitmapSource.cs
- TableLayoutPanel.cs
- Transaction.cs
- CompilationLock.cs