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