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
- EventLogEntry.cs
- SignatureToken.cs
- PersonalizationProvider.cs
- WebPartCatalogCloseVerb.cs
- SqlFormatter.cs
- TextParagraph.cs
- VisualStateChangedEventArgs.cs
- XmlWellformedWriter.cs
- NetworkCredential.cs
- DataGridViewAutoSizeModeEventArgs.cs
- XmlMemberMapping.cs
- ConfigsHelper.cs
- DynamicEndpointElement.cs
- UInt64Storage.cs
- WebBrowserContainer.cs
- HttpModuleCollection.cs
- DLinqTableProvider.cs
- GridViewDeletedEventArgs.cs
- LocalBuilder.cs
- InputScopeConverter.cs
- WmlObjectListAdapter.cs
- ImagingCache.cs
- HasCopySemanticsAttribute.cs
- NavigationHelper.cs
- BindingContext.cs
- control.ime.cs
- ByteAnimationUsingKeyFrames.cs
- TextBoxLine.cs
- StrokeRenderer.cs
- SmiEventStream.cs
- DbConnectionInternal.cs
- ContentDisposition.cs
- ConstructorBuilder.cs
- mediaeventargs.cs
- JavaScriptSerializer.cs
- XmlSchemaSimpleType.cs
- DynamicRenderer.cs
- LayoutUtils.cs
- SafeUserTokenHandle.cs
- BamlVersionHeader.cs
- COM2PropertyDescriptor.cs
- EventPrivateKey.cs
- VBCodeProvider.cs
- EntitySetBase.cs
- ColorDialog.cs
- XmlSchemaAnnotated.cs
- SerialPort.cs
- QueryProcessor.cs
- SamlAuthenticationClaimResource.cs
- ListBox.cs
- Nodes.cs
- ApplicationHost.cs
- PassportPrincipal.cs
- ProcessHostConfigUtils.cs
- WebSysDisplayNameAttribute.cs
- CollectionViewSource.cs
- versioninfo.cs
- WorkflowInstanceAbortedRecord.cs
- HttpRuntimeSection.cs
- InvalidateEvent.cs
- SchemaDeclBase.cs
- KeyInstance.cs
- MetadataItemCollectionFactory.cs
- SessionIDManager.cs
- ServiceDebugBehavior.cs
- EndpointFilterProvider.cs
- SamlAction.cs
- TextEditor.cs
- EncryptedData.cs
- xml.cs
- VerificationAttribute.cs
- clipboard.cs
- AbstractExpressions.cs
- DocumentXPathNavigator.cs
- TypeGeneratedEventArgs.cs
- ExpressionServices.cs
- SectionInput.cs
- JpegBitmapEncoder.cs
- CssClassPropertyAttribute.cs
- InvalidPrinterException.cs
- DBPropSet.cs
- UrlMappingsSection.cs
- DbCommandTree.cs
- CompletedAsyncResult.cs
- ImmComposition.cs
- RadioButtonDesigner.cs
- BitmapSource.cs
- SHA384Managed.cs
- MinMaxParagraphWidth.cs
- SizeConverter.cs
- BaseInfoTable.cs
- OracleParameter.cs
- HttpBrowserCapabilitiesBase.cs
- DelayedRegex.cs
- UnionCodeGroup.cs
- HttpCapabilitiesBase.cs
- DataControlPagerLinkButton.cs
- OdbcCommand.cs
- MenuCommand.cs
- SQLGuidStorage.cs