1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Runtime; 6 using System.Diagnostics; 7 using System.Runtime.InteropServices; 8 9 namespace System.Security 10 { 11 internal sealed class SafeBSTRHandle : SafeBuffer 12 { SafeBSTRHandle()13 internal SafeBSTRHandle() : base(true) { } 14 Allocate(uint lenInChars)15 internal static SafeBSTRHandle Allocate(uint lenInChars) 16 { 17 ulong lenInBytes = (ulong)lenInChars * sizeof(char); 18 SafeBSTRHandle bstr = Interop.OleAut32.SysAllocStringLen(IntPtr.Zero, lenInChars); 19 if (bstr.IsInvalid) // SysAllocStringLen returns a NULL ptr when there's insufficient memory 20 { 21 throw new OutOfMemoryException(); 22 } 23 bstr.Initialize(lenInBytes); 24 return bstr; 25 } 26 ReleaseHandle()27 override protected bool ReleaseHandle() 28 { 29 RuntimeImports.RhZeroMemory(handle, (UIntPtr)(Interop.OleAut32.SysStringLen(handle) * sizeof(char))); 30 Interop.OleAut32.SysFreeString(handle); 31 return true; 32 } 33 ClearBuffer()34 internal unsafe void ClearBuffer() 35 { 36 byte* bufferPtr = null; 37 try 38 { 39 AcquirePointer(ref bufferPtr); 40 RuntimeImports.RhZeroMemory((IntPtr)bufferPtr, (UIntPtr)(Interop.OleAut32.SysStringLen((IntPtr)bufferPtr) * sizeof(char))); 41 } 42 finally 43 { 44 if (bufferPtr != null) 45 { 46 ReleasePointer(); 47 } 48 } 49 } 50 51 internal unsafe uint Length => Interop.OleAut32.SysStringLen(this); 52 Copy(SafeBSTRHandle source, SafeBSTRHandle target, uint bytesToCopy)53 internal unsafe static void Copy(SafeBSTRHandle source, SafeBSTRHandle target, uint bytesToCopy) 54 { 55 if (bytesToCopy == 0) 56 { 57 return; 58 } 59 60 byte* sourcePtr = null, targetPtr = null; 61 try 62 { 63 source.AcquirePointer(ref sourcePtr); 64 target.AcquirePointer(ref targetPtr); 65 66 Debug.Assert(source.ByteLength >= bytesToCopy, "Source buffer is too small."); 67 Buffer.MemoryCopy(sourcePtr, targetPtr, target.ByteLength, bytesToCopy); 68 } 69 finally 70 { 71 if (targetPtr != null) 72 { 73 target.ReleasePointer(); 74 } 75 if (sourcePtr != null) 76 { 77 source.ReleasePointer(); 78 } 79 } 80 } 81 } 82 } 83