public SafeCspHandle Duplicate() { Contract.Requires(!IsInvalid && !IsClosed); // In the window between the call to CryptContextAddRef and when the raw handle value is assigned // into this safe handle, there's a second reference to the original safe handle that the CLR does // not know about, so we need to bump the reference count around this entire operation to ensure // that we don't have the original handle closed underneath us. bool acquired = false; RuntimeHelpers.PrepareConstrainedRegions(); try { DangerousAddRef(ref acquired); IntPtr originalHandle = DangerousGetHandle(); int error = (int)CapiNative.ErrorCode.Success; SafeCspHandle duplicate = new SafeCspHandle(); // A successful call to CryptContextAddRef and an assignment of the handle value to the duplicate // SafeHandle need to happen atomically, so we contain them within a CER. RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (!CryptContextAddRef(this, IntPtr.Zero, 0)) { error = Marshal.GetLastWin32Error(); } else { duplicate.SetHandle(originalHandle); } } // If we could not call CryptContextAddRef succesfully, then throw the error here otherwise // we should be in a valid state at this point. if (error != (int)CapiNative.ErrorCode.Success) { duplicate.Dispose(); throw new CryptographicException(error); } else { Debug.Assert(!duplicate.IsInvalid, "Failed to duplicate handle successfully"); } return(duplicate); } finally { if (acquired) { DangerousRelease(); } } }
public SafeCspHandle Duplicate() { SafeCspHandle handle2; bool success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { base.DangerousAddRef(ref success); IntPtr ptr = base.DangerousGetHandle(); int hr = 0; SafeCspHandle handle = new SafeCspHandle(); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (!CryptContextAddRef(this, IntPtr.Zero, 0)) { hr = Marshal.GetLastWin32Error(); } else { handle.SetHandle(ptr); } } if (hr != 0) { handle.Dispose(); throw new CryptographicException(hr); } handle2 = handle; } finally { if (success) { base.DangerousRelease(); } } return handle2; }