public static void ExecuteCodeWithGuaranteedCleanup(Action action, Action cleanup) { if (action == null) { throw new ArgumentNullException(nameof(action)); } if (cleanup == null) { throw new ArgumentNullException(nameof(cleanup)); } #if NETFRAMEWORK RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( delegate { action.Invoke(); } , delegate { cleanup.Invoke(); }, null); #else try { action.Invoke(); } finally { cleanup.Invoke(); } #endif }
public unsafe Mutex(bool initiallyOwned, string name, out bool createdNew, MutexSecurity mutexSecurity) { if ((name != null) && (260 < name.Length)) { throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", new object[] { name })); } Win32Native.SECURITY_ATTRIBUTES structure = null; if (mutexSecurity != null) { structure = new Win32Native.SECURITY_ATTRIBUTES { nLength = Marshal.SizeOf(structure) }; byte[] securityDescriptorBinaryForm = mutexSecurity.GetSecurityDescriptorBinaryForm(); byte * pDest = stackalloc byte[(IntPtr)securityDescriptorBinaryForm.Length]; Buffer.memcpy(securityDescriptorBinaryForm, 0, pDest, 0, securityDescriptorBinaryForm.Length); structure.pSecurityDescriptor = pDest; } RuntimeHelpers.CleanupCode backoutCode = new RuntimeHelpers.CleanupCode(this.MutexCleanupCode); MutexCleanupInfo cleanupInfo = new MutexCleanupInfo(null, false); MutexTryCodeHelper helper = new MutexTryCodeHelper(initiallyOwned, cleanupInfo, name, structure, this); RuntimeHelpers.TryCode code = new RuntimeHelpers.TryCode(helper.MutexTryCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(code, backoutCode, cleanupInfo); createdNew = helper.m_newMutex; }
public static byte[] ConvertSecureStringToByteArray(SecureString secString) { byte[] byteArray = new byte[secString.Length]; IntPtr bstr = IntPtr.Zero; RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( delegate { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { bstr = Marshal.SecureStringToBSTR(secString); } Marshal.Copy(bstr, byteArray, 0, secString.Length); }, delegate { if (bstr != IntPtr.Zero) { Marshal.ZeroFreeBSTR(bstr); bstr = IntPtr.Zero; } }, null); return(byteArray); }
internal String GetResourceString(String key) { if (key == null || key.Length == 0) { BCLDebug.Assert(false, "Environment::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); return("[Resource lookup failed - null or empty resource name]"); } // We have a somewhat common potential for infinite // loops with mscorlib's ResourceManager. If "potentially dangerous" // code throws an exception, we will get into an infinite loop // inside the ResourceManager and this "potentially dangerous" code. // Potentially dangerous code includes the IO package, CultureInfo, // parts of the loader, some parts of Reflection, Security (including // custom user-written permissions that may parse an XML file at // class load time), assembly load event handlers, etc. Essentially, // this is not a bounded set of code, and we need to fix the problem. // Fortunately, this is limited to mscorlib's error lookups and is NOT // a general problem for all user code using the ResourceManager. // The solution is to make sure only one thread at a time can call // GetResourceString. Also, since resource lookups can be // reentrant, if the same thread comes into GetResourceString // twice looking for the exact same resource name before // returning, we're going into an infinite loop and we should // return a bogus string. GetResourceStringUserData userData = new GetResourceStringUserData(this, key); RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(GetResourceStringCode); RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(GetResourceStringBackoutCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData); return(userData.m_retVal); }
private void Initialize() { unsafe { // We're about to create an unencrypted version of our sensitive string and store it in memory. // Don't let anyone (GC) make a copy. // To do this, create a new gc handle so we can "pin" the memory. // The gc handle will be pinned, and later we will put info in this string. _gcHandle = default; // insecurePointer will be temporarily used to access the SecureString var insecurePointer = IntPtr.Zero; // This delegate defines the code that will be executed (similar to the code in a Try block) void TryCode(object userData) { // Even though this code executes in the ExecuteCodeWithGuaranteedCleanup() method, processing can be interupted. // We need to make sure nothing happens between when memory is allocated and // when the pointers have been assigned values. Otherwise, we can't cleanup later. // ConstrainedExecutionRegions are better than Try/Finally blocks: not even a ThreadException will interupt this processing. // A CER is not the same as ExecuteCodeWithGuaranteedCleanup: a CER does not have a cleanup. // Create an unencrypted version of the SecureString in unmanaged memory (as a BSTR), and get a pointer to it Action getBstr = () => insecurePointer = Marshal.SecureStringToBSTR(_secureString); getBstr.ExecuteInConstrainedRegion(); // Get the number of bytes in the BSTR (which are contained in the 4 bytes preceeding the pointer) _byteCount = Marshal.ReadInt32(insecurePointer, -4); // Create a new buffer of appropriate length that is filled with 0's Value = InitializeBuffer(_secureString.Length, _byteCount); // It is essential that this buffer not be copied around, even by the CLR garbage collector! // To enforce this, we need to "pin" the variable to its current location in managed memory, so it cannot be changed until we release it. Action pinValue = () => _gcHandle = GCHandle.Alloc(Value, GCHandleType.Pinned); pinValue.ExecuteInConstrainedRegion(); // Copy the data from the unencrypted BSTR to the buffer Buffer.MemoryCopy((void *)insecurePointer, (void *)_gcHandle.AddrOfPinnedObject(), _byteCount, _byteCount); } // This delegate defines the code that will perform cleanup work (similar to the code in a Finally block) void CleanupCode(object userData, bool exceptionThrown) { // insecurePointer was temporarily used to access the SecureString. // Set the BSTR to all 0's and then clean it up. This is important! // This prevents sniffers from seeing the sensitive info as it is cleaned up. if (insecurePointer != IntPtr.Zero) { Marshal.ZeroFreeBSTR(insecurePointer); } } // Better than a Try/Finally: Not even a ThreadException will bypass the cleanup code RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, null); } }
static void Main(string[] args) { Console.Write("Enter Passphrase: "); using (var passphrase = GetPassphraseFromConsole()) { Console.WriteLine("Your password:"******"Exception thrown."); } Marshal.ZeroFreeBSTR(ptr); for (var ii = 0; ii < arPass.Length; ii++) { arPass[ii] = '\0'; } handle.Free(); }, null ); } } }
private unsafe void Update() { Deallocate(); if (SecureText != null) { int length = SecureText.Length; ClearText = new string('\0', length); ByteArray = new byte[length]; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { _gchText = GCHandle.Alloc(ClearText, GCHandleType.Pinned); _gchByte = GCHandle.Alloc(ByteArray, GCHandleType.Pinned); } IntPtr intPtrText = IntPtr.Zero; IntPtr intPtrByte = IntPtr.Zero; RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( delegate { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { intPtrText = Marshal.SecureStringToBSTR(SecureText); intPtrByte = Marshal.SecureStringToGlobalAllocAnsi(SecureText); } char *pStr = (char *)intPtrText; char *pClearText = (char *)_gchText.AddrOfPinnedObject(); for (int index = 0; index < length; index++) { pClearText[index] = pStr[index]; } byte *pByte = (byte *)intPtrByte; byte *pByteArr = (byte *)_gchByte.AddrOfPinnedObject(); for (int index = 0; index < length; index++) { pByteArr[index] = pByte[index]; } }, delegate { if (intPtrText != IntPtr.Zero) { Marshal.ZeroFreeBSTR(intPtrText); } if (intPtrByte != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocAnsi(intPtrByte); } }, null); } }
internal void CreateMutexWithGuaranteedCleanup(bool initiallyOwned, string name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs) { RuntimeHelpers.CleanupCode backoutCode = new RuntimeHelpers.CleanupCode(this.MutexCleanupCode); Mutex.MutexCleanupInfo cleanupInfo = new Mutex.MutexCleanupInfo((SafeWaitHandle)null, false); Mutex.MutexTryCodeHelper mutexTryCodeHelper = new Mutex.MutexTryCodeHelper(initiallyOwned, cleanupInfo, name, secAttrs, this); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(new RuntimeHelpers.TryCode(mutexTryCodeHelper.MutexTryCode), backoutCode, (object)cleanupInfo); createdNew = mutexTryCodeHelper.m_newMutex; }
private void Initialize() { unsafe { // We are about to create an unencrypted version of our sensitive string and store it in memory. // Don't let anyone (GC) make a copy. // To do this, create a new gc handle so we can "pin" the memory. // The gc handle will be pinned and later, we will put info in this string. _gcHandle = new GCHandle(); // insecurePointer will be temporarily used to access the SecureString var insecurePointer = IntPtr.Zero; System.Runtime.CompilerServices.RuntimeHelpers.TryCode code = delegate { // create a new string of appropriate length that is filled with 0's Value = new string((char)0, _secureString.Length); // Even though we are in the ExecuteCodeWithGuaranteedCleanup, processing can be interupted. // We need to make sure nothing happens between when memory is allocated and // when _gcHandle has been assigned the value. Otherwise, we can't cleanup later. // PrepareConstrainedRegions is better than a try/catch. Not even a threadexception will interupt this processing. // A CER is not the same as ExecuteCodeWithGuaranteedCleanup. A CER does not have a cleanup. Action alloc = delegate { _gcHandle = GCHandle.Alloc(Value, GCHandleType.Pinned); }; alloc.ExecuteInConstrainedRegion(); // Even though we are in the ExecuteCodeWithGuaranteedCleanup, processing can be interupted. // We need to make sure nothing happens between when memory is allocated and // when insecurePointer has been assigned the value. Otherwise, we can't cleanup later. // PrepareConstrainedRegions is better than a try/catch. Not even a threadexception will interupt this processing. // A CER is not the same as ExecuteCodeWithGuaranteedCleanup. A CER does not have a cleanup. Action toBSTR = delegate { insecurePointer = Marshal.SecureStringToBSTR(_secureString); }; toBSTR.ExecuteInConstrainedRegion(); // get a pointer to our new "pinned" string var value = (char *)_gcHandle.AddrOfPinnedObject(); // get a pointer to the unencrypted string var charPointer = (char *)insecurePointer; // copy for (int i = 0; i < _secureString.Length; i++) { value[i] = charPointer[i]; } }; System.Runtime.CompilerServices.RuntimeHelpers.CleanupCode cleanup = delegate { // insecurePointer was temporarily used to access the securestring // set the string to all 0's and then clean it up. this is important. // this prevents sniffers from seeing the sensitive info as it is cleaned up. if (insecurePointer != IntPtr.Zero) { Marshal.ZeroFreeBSTR(insecurePointer); } }; // Better than a try/catch. Not even a threadexception will bypass the cleanup code RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(code, cleanup, null); } }
private void UpdateStringValue() { Deallocate(); if (SecureValue != null) { Int32 length = SecureValue.Length; _charArray = new Char[length]; for (Int32 i = 0; i < length; ++i) { _charArray[i] = '\0'; } _GCH = new GCHandle(); // Create a CER (Contrained Execution Region) RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { // Pin our char array, disallowing the garbage collector from // moving it around. _GCH = GCHandle.Alloc(_charArray, GCHandleType.Pinned); } IntPtr stringPtr = IntPtr.Zero; RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( delegate { // Create a CER (Contrained Execution Region) RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { stringPtr = Marshal.SecureStringToBSTR(SecureValue); } // Copy the SecureString content to our pinned string IntPtr charArrayPtr = _GCH.AddrOfPinnedObject(); for (Int32 index = 0; index < length * 2; index++) { Marshal.WriteByte(charArrayPtr, index, Marshal.ReadByte(stringPtr, index)); } }, delegate { if (stringPtr != IntPtr.Zero) { // Free the SecureString BSTR that was generated Marshal.ZeroFreeBSTR(stringPtr); } }, null); } }
public void Enter(Action <int> action) { int oldReentranceCount = currentReentranceCount; RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(delegate { currentReentranceCount = oldReentranceCount + 1; action(currentReentranceCount); }, Cleanup, oldReentranceCount); }
internal static void RunInternal(SecurityContext securityContext, ContextCallback callBack, object state) { if (SecurityContext.cleanupCode == null) { SecurityContext.tryCode = new RuntimeHelpers.TryCode(SecurityContext.runTryCode); SecurityContext.cleanupCode = new RuntimeHelpers.CleanupCode(SecurityContext.runFinallyCode); } SecurityContext.SecurityContextRunData userData = new SecurityContext.SecurityContextRunData(securityContext, callBack, state); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(SecurityContext.tryCode, SecurityContext.cleanupCode, userData); }
void UpdateStringValue() { Deallocate(); unsafe { if (SecureString != null) { int length = SecureString.Length; String = new string('\0', length); _GCH = new GCHandle(); // Create a CER (Contrained Execution Region) RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { // Pin our string, disallowing the garbage collector from // moving it around. _GCH = GCHandle.Alloc(String, GCHandleType.Pinned); } IntPtr stringPtr = IntPtr.Zero; RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( delegate { // Create a CER (Contrained Execution Region) RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { stringPtr = Marshal.SecureStringToBSTR(SecureString); } // Copy the SecureString content to our pinned string char *pString = (char *)stringPtr; char *pInsecureString = (char *)_GCH.AddrOfPinnedObject(); for (int index = 0; index < length; index++) { pInsecureString[index] = pString[index]; } }, delegate { if (stringPtr != IntPtr.Zero) { // Free the SecureString BSTR that was generated Marshal.ZeroFreeBSTR(stringPtr); } }, null); } } }
[System.Security.SecurityCritical] // auto-generated internal static void RunInternal(SecurityContext securityContext, ContextCallback callBack, Object state) { if (cleanupCode == null) { tryCode = new RuntimeHelpers.TryCode(runTryCode); cleanupCode = new RuntimeHelpers.CleanupCode(runFinallyCode); } SecurityContextRunData runData = new SecurityContextRunData(securityContext, callBack, state); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, runData); }
public Mutex(bool initiallyOwned, String name, out bool createdNew) { if (null != name && System.IO.Path.MAX_PATH < name.Length) { throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", name)); } Win32Native.SECURITY_ATTRIBUTES secAttrs = null; SafeWaitHandle mutexHandle = null; bool newMutex = false; RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(MutexCleanupCode); MutexCleanupInfo cleanupInfo = new MutexCleanupInfo(mutexHandle, false); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( delegate(object userData) { // try block RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (initiallyOwned) { cleanupInfo.inCriticalRegion = true; Thread.BeginThreadAffinity(); Thread.BeginCriticalRegion(); } } int errorCode = 0; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { errorCode = CreateMutexHandle(initiallyOwned, name, secAttrs, out mutexHandle); } if (mutexHandle.IsInvalid) { mutexHandle.SetHandleAsInvalid(); if (null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode) { throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name)); } __Error.WinIOError(errorCode, name); } newMutex = errorCode != Win32Native.ERROR_ALREADY_EXISTS; SetHandleInternal(mutexHandle); mutexHandle.SetAsMutex(); hasThreadAffinity = true; }, cleanupCode, cleanupInfo); createdNew = newMutex; }
internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, object state) { if (cleanupCode == null) { tryCode = new RuntimeHelpers.TryCode(ExecutionContext.runTryCode); cleanupCode = new RuntimeHelpers.CleanupCode(ExecutionContext.runFinallyCode); } ExecutionContextRunData userData = new ExecutionContextRunData(executionContext, callback, state); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData); }
internal string GetResourceString(string key, CultureInfo culture) { if ((key == null) || (key.Length == 0)) { return("[Resource lookup failed - null or empty resource name]"); } GetResourceStringUserData userData = new GetResourceStringUserData(this, key, culture); RuntimeHelpers.TryCode code = new RuntimeHelpers.TryCode(this.GetResourceStringCode); RuntimeHelpers.CleanupCode backoutCode = new RuntimeHelpers.CleanupCode(this.GetResourceStringBackoutCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(code, backoutCode, userData); return(userData.m_retVal); }
internal void CreateMutexWithGuaranteedCleanup(bool initiallyOwned, String name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs) { RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(MutexCleanupCode); MutexCleanupInfo cleanupInfo = new MutexCleanupInfo(null, false); MutexTryCodeHelper tryCodeHelper = new MutexTryCodeHelper(initiallyOwned, cleanupInfo, name, secAttrs, this); RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(tryCodeHelper.MutexTryCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( tryCode, cleanupCode, cleanupInfo); createdNew = tryCodeHelper.m_newMutex; }
public static void Run(CompressedStack compressedStack, ContextCallback callback, object state) { if (compressedStack == null) { throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamNull"), "compressedStack"); } if (CompressedStack.cleanupCode == null) { CompressedStack.tryCode = new RuntimeHelpers.TryCode(CompressedStack.runTryCode); CompressedStack.cleanupCode = new RuntimeHelpers.CleanupCode(CompressedStack.runFinallyCode); } CompressedStack.CompressedStackRunData compressedStackRunData = new CompressedStack.CompressedStackRunData(compressedStack, callback, state); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(CompressedStack.tryCode, CompressedStack.cleanupCode, (object)compressedStackRunData); }
public void RunAsClient(PipeStreamImpersonationWorker impersonationWorker) { base.CheckWriteOperations(); ExecuteHelper userData = new ExecuteHelper(impersonationWorker, base.InternalHandle); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData); if (userData.m_impersonateErrorCode != 0) { base.WinIOError(userData.m_impersonateErrorCode); } else if (userData.m_revertImpersonateErrorCode != 0) { base.WinIOError(userData.m_revertImpersonateErrorCode); } }
public static void Run(CompressedStack compressedStack, ContextCallback callback, Object state) { if (compressedStack == null) { throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamNull"), "compressedStack"); } Contract.EndContractBlock(); if (cleanupCode == null) { tryCode = new RuntimeHelpers.TryCode(runTryCode); cleanupCode = new RuntimeHelpers.CleanupCode(runFinallyCode); } CompressedStackRunData runData = new CompressedStackRunData(compressedStack, callback, state); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, runData); }
// This method calls a delegate while impersonating the client. Note that we will not have // access to the client's security token until it has written at least once to the pipe // (and has set its impersonationLevel argument appropriately). public void RunAsClient(PipeStreamImpersonationWorker impersonationWorker) { CheckWriteOperations(); ExecuteHelper execHelper = new ExecuteHelper(impersonationWorker, InternalHandle); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, execHelper); // now handle win32 impersonate/revert specific errors by throwing corresponding exceptions if (execHelper._impersonateErrorCode != 0) { throw WinIOError(execHelper._impersonateErrorCode); } else if (execHelper._revertImpersonateErrorCode != 0) { throw WinIOError(execHelper._revertImpersonateErrorCode); } }
/// <summary> /// The main entry point for the application. /// </summary> static int Main(string[] args) { GCD gcd = new GCD(); RuntimeHelpers.TryCode t = new RuntimeHelpers.TryCode(gcd.TryCode0); RuntimeHelpers.CleanupCode c = new RuntimeHelpers.CleanupCode(gcd.CleanupCode0); int val = 21; try { RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(t, c, val); } catch (Exception Ex) { } return(gcd.GetExitCode()); }
internal void CreateMutexWithGuaranteedCleanup(bool initiallyOwned, String name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs) { #if FEATURE_LEGACYNETCF if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) { name = WinCEObjectNameQuirk(name); } #endif RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(MutexCleanupCode); MutexCleanupInfo cleanupInfo = new MutexCleanupInfo(null, false); MutexTryCodeHelper tryCodeHelper = new MutexTryCodeHelper(initiallyOwned, cleanupInfo, name, secAttrs, this); RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(tryCodeHelper.MutexTryCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( tryCode, cleanupCode, cleanupInfo); createdNew = tryCodeHelper.m_newMutex; }
public void Execute() { // // ExecuteCodeWithGuaranteedCleanupメソッドは, PrepareConstrainedRegionsメソッドと // 同様に、コードをCER(制約された実行環境)で実行するメソッドである。 // // PrepareConstrainedRegionsメソッドが呼び出されたメソッドのcatch, finallyブロックを // CERとしてマークするのに対して、ExecuteCodeWithGuaranteedCleanupメソッドは // 明示的に実行コード部分とクリーンアップ部分 (バックアウトコード)を引数で渡す仕様となっている。 // // ExecuteCodeWithGuaranteedCleanupメソッドは // TryCodeデリゲートとCleanupCodeデリゲート、及び、userDataを受け取る. // // public delegate void TryCode(object userData) // public delegate void CleanupCode(object userData, bool exceptionThrown) // // 前回のサンプルと同じ動作を行う. RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(Calc, Cleanup, null); }
private void Initialize() { unsafe { _gcHandle = new GCHandle(); var insecurePointer = IntPtr.Zero; void code(object userData) { Value = new string((char)0, _secureString.Length); Action alloc = delegate { _gcHandle = GCHandle.Alloc(Value, GCHandleType.Pinned); }; alloc.ExecuteInConstrainedRegion(); Action toBSTR = delegate { insecurePointer = SecureStringMarshal.SecureStringToGlobalAllocUnicode(_secureString); }; toBSTR.ExecuteInConstrainedRegion(); var value = (char *)_gcHandle.AddrOfPinnedObject(); var charPointer = (char *)insecurePointer; for (int i = 0; i < _secureString.Length; i++) { value[i] = charPointer[i]; } } RuntimeHelpers.CleanupCode cleanup = delegate { if (insecurePointer != IntPtr.Zero) { Marshal.ZeroFreeGlobalAllocUnicode(insecurePointer); } }; #pragma warning disable SYSLIB0004 // Type or member is obsolete RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(code, cleanup, null); #pragma warning restore SYSLIB0004 // Type or member is obsolete } }
private static void Main() { Console.WriteLine("Danger"); try { Danger(); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine(); Console.WriteLine("Safety"); try { SafeCode(); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine(); // NOTE: Еще один способ гарантированной очистки RuntimeHelpers.TryCode tryCode = data => { Console.WriteLine("Try code"); }; RuntimeHelpers.CleanupCode cleanupCode = (data, thrown) => { Console.WriteLine("Cleanup code"); }; RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, null); }
public static void Run() { GCD gcd = new GCD(); RuntimeHelpers.TryCode t = new RuntimeHelpers.TryCode(gcd.TryCode0); RuntimeHelpers.CleanupCode c = new RuntimeHelpers.CleanupCode(gcd.CleanupCode0); int val = 21; try { RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(t, c, val); } catch (Exception Ex) { } int res = gcd.GetExitCode(); if (res != 100) { throw new Exception($"{nameof(ExecuteCodeWithGuaranteedCleanupTest)} failed. Result: {res}"); } }
public static void Run() { GCD gcd = new GCD(); RuntimeHelpers.TryCode t = new RuntimeHelpers.TryCode(gcd.TryCode0); RuntimeHelpers.CleanupCode c = new RuntimeHelpers.CleanupCode(gcd.CleanupCode0); int val = 21; try { #pragma warning disable SYSLIB0004 // CER is obsolete RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(t, c, val); #pragma warning restore SYSLIB0004 } catch (Exception Ex) { } int res = gcd.GetExitCode(); if (res != 100) { throw new Exception($"{nameof(ExecuteCodeWithGuaranteedCleanupTest)} failed. Result: {res}"); } }
private static void ThreadFunc(Object o) { Boolean taken = true; if ((Boolean)o) { Monitor.Enter(s_myLock /*, ref taken*/); Thread.Sleep(2000); if (taken) { Monitor.Exit(s_myLock); } } else { RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup( userData => { Monitor.Enter(s_myLock /*, ref taken*/); Thread.Sleep(10000); }, (userData, exceptionThrown) => { if (taken) { Monitor.Exit(s_myLock); } }, null); } }