SafeBSTRHandle.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. using System.Runtime;
  5. using System.Diagnostics;
  6. using System.Runtime.InteropServices;
  7. namespace System.Security
  8. {
  9. internal sealed class SafeBSTRHandle : SafeBuffer
  10. {
  11. internal SafeBSTRHandle() : base(true) { }
  12. internal static SafeBSTRHandle Allocate(uint lenInChars)
  13. {
  14. ulong lenInBytes = (ulong)lenInChars * sizeof(char);
  15. SafeBSTRHandle bstr = Interop.OleAut32.SysAllocStringLen(IntPtr.Zero, lenInChars);
  16. if (bstr.IsInvalid) // SysAllocStringLen returns a NULL ptr when there's insufficient memory
  17. {
  18. throw new OutOfMemoryException();
  19. }
  20. bstr.Initialize(lenInBytes);
  21. return bstr;
  22. }
  23. override protected bool ReleaseHandle()
  24. {
  25. RuntimeImports.RhZeroMemory(handle, (UIntPtr)(Interop.OleAut32.SysStringLen(handle) * sizeof(char)));
  26. Interop.OleAut32.SysFreeString(handle);
  27. return true;
  28. }
  29. internal unsafe void ClearBuffer()
  30. {
  31. byte* bufferPtr = null;
  32. try
  33. {
  34. AcquirePointer(ref bufferPtr);
  35. RuntimeImports.RhZeroMemory((IntPtr)bufferPtr, (UIntPtr)(Interop.OleAut32.SysStringLen((IntPtr)bufferPtr) * sizeof(char)));
  36. }
  37. finally
  38. {
  39. if (bufferPtr != null)
  40. {
  41. ReleasePointer();
  42. }
  43. }
  44. }
  45. internal unsafe uint Length => Interop.OleAut32.SysStringLen(this);
  46. internal static unsafe void Copy(SafeBSTRHandle source, SafeBSTRHandle target, uint bytesToCopy)
  47. {
  48. if (bytesToCopy == 0)
  49. {
  50. return;
  51. }
  52. byte* sourcePtr = null, targetPtr = null;
  53. try
  54. {
  55. source.AcquirePointer(ref sourcePtr);
  56. target.AcquirePointer(ref targetPtr);
  57. Debug.Assert(source.ByteLength >= bytesToCopy, "Source buffer is too small.");
  58. Buffer.MemoryCopy(sourcePtr, targetPtr, target.ByteLength, bytesToCopy);
  59. }
  60. finally
  61. {
  62. if (targetPtr != null)
  63. {
  64. target.ReleasePointer();
  65. }
  66. if (sourcePtr != null)
  67. {
  68. source.ReleasePointer();
  69. }
  70. }
  71. }
  72. }
  73. }