1 // <OWNER>Microsoft</OWNER> 2 namespace System.Security { 3 using System.Security.Cryptography; 4 using System.Runtime.InteropServices; 5 #if FEATURE_CORRUPTING_EXCEPTIONS 6 using System.Runtime.ExceptionServices; 7 #endif // FEATURE_CORRUPTING_EXCEPTIONS 8 using System.Text; 9 using Microsoft.Win32; 10 using System.Runtime.CompilerServices; 11 using System.Security.Permissions; 12 using System.Runtime.ConstrainedExecution; 13 using System.Runtime.Versioning; 14 using Microsoft.Win32.SafeHandles; 15 using System.Diagnostics.Contracts; 16 17 public sealed class SecureString: IDisposable { 18 [System.Security.SecurityCritical] // auto-generated 19 private SafeBSTRHandle m_buffer; 20 [ContractPublicPropertyName("Length")] 21 private int m_length; 22 private bool m_readOnly; 23 private bool m_encrypted; 24 25 static bool supportedOnCurrentPlatform = EncryptionSupported(); 26 27 const int BlockSize = (int)Win32Native.CRYPTPROTECTMEMORY_BLOCK_SIZE /2; // a char is two bytes 28 const int MaxLength = 65536; 29 const uint ProtectionScope = Win32Native.CRYPTPROTECTMEMORY_SAME_PROCESS; 30 31 [System.Security.SecuritySafeCritical] // auto-generated SecureString()32 static SecureString() 33 { 34 } 35 36 [System.Security.SecurityCritical] // auto-generated EncryptionSupported()37 unsafe static bool EncryptionSupported() { 38 // check if the enrypt/decrypt function is supported on current OS 39 bool supported = true; 40 try { 41 Win32Native.SystemFunction041( 42 SafeBSTRHandle.Allocate(null , (int)Win32Native.CRYPTPROTECTMEMORY_BLOCK_SIZE), 43 Win32Native.CRYPTPROTECTMEMORY_BLOCK_SIZE, 44 Win32Native.CRYPTPROTECTMEMORY_SAME_PROCESS); 45 } 46 catch (EntryPointNotFoundException) { 47 supported = false; 48 } 49 return supported; 50 } 51 52 [System.Security.SecurityCritical] // auto-generated SecureString(SecureString str)53 internal SecureString(SecureString str) { 54 AllocateBuffer(str.BufferLength); 55 SafeBSTRHandle.Copy(str.m_buffer, this.m_buffer); 56 m_length = str.m_length; 57 m_encrypted = str.m_encrypted; 58 } 59 60 61 [System.Security.SecuritySafeCritical] // auto-generated SecureString()62 public SecureString() { 63 CheckSupportedOnCurrentPlatform(); 64 65 // allocate the minimum block size for calling protectMemory 66 AllocateBuffer(BlockSize); 67 m_length = 0; 68 } 69 70 71 [System.Security.SecurityCritical] // auto-generated 72 #if FEATURE_CORRUPTING_EXCEPTIONS 73 [HandleProcessCorruptedStateExceptions] // 74 #endif // FEATURE_CORRUPTING_EXCEPTIONS InitializeSecureString(char* value, int length)75 private unsafe void InitializeSecureString(char* value, int length) 76 { 77 CheckSupportedOnCurrentPlatform(); 78 79 AllocateBuffer(length); 80 m_length = length; 81 82 byte* bufferPtr = null; 83 RuntimeHelpers.PrepareConstrainedRegions(); 84 try 85 { 86 m_buffer.AcquirePointer(ref bufferPtr); 87 Buffer.Memcpy(bufferPtr, (byte*)value, length * 2); 88 } 89 catch (Exception) { 90 ProtectMemory(); 91 throw; 92 } 93 finally 94 { 95 if (bufferPtr != null) 96 m_buffer.ReleasePointer(); 97 } 98 99 ProtectMemory(); 100 } 101 102 [System.Security.SecurityCritical] // auto-generated 103 [CLSCompliant(false)] SecureString(char* value, int length)104 public unsafe SecureString(char* value, int length) { 105 if( value == null) { 106 throw new ArgumentNullException("value"); 107 } 108 109 if( length < 0) { 110 throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 111 } 112 113 if( length > MaxLength) { 114 throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Length")); 115 } 116 Contract.EndContractBlock(); 117 118 // Refactored since HandleProcessCorruptedStateExceptionsAttribute applies to methods only (yet). 119 InitializeSecureString(value, length); 120 } 121 122 public int Length { 123 [System.Security.SecuritySafeCritical] // auto-generated 124 [MethodImplAttribute(MethodImplOptions.Synchronized)] 125 get { 126 EnsureNotDisposed(); 127 return m_length; 128 } 129 } 130 131 [System.Security.SecuritySafeCritical] // auto-generated 132 [MethodImplAttribute(MethodImplOptions.Synchronized)] 133 #if FEATURE_CORRUPTING_EXCEPTIONS 134 [HandleProcessCorruptedStateExceptions] // 135 #endif // FEATURE_CORRUPTING_EXCEPTIONS AppendChar(char c)136 public void AppendChar(char c) { 137 EnsureNotDisposed(); 138 EnsureNotReadOnly(); 139 140 EnsureCapacity(m_length + 1); 141 142 RuntimeHelpers.PrepareConstrainedRegions(); 143 try { 144 UnProtectMemory(); 145 m_buffer.Write<char>((uint)m_length * sizeof(char), c); 146 m_length++; 147 } 148 catch (Exception) { 149 ProtectMemory(); 150 throw; 151 } 152 finally { 153 ProtectMemory(); 154 } 155 } 156 157 // clears the current contents. Only available if writable 158 [System.Security.SecuritySafeCritical] // auto-generated 159 [MethodImplAttribute(MethodImplOptions.Synchronized)] Clear()160 public void Clear() { 161 EnsureNotDisposed(); 162 EnsureNotReadOnly(); 163 164 m_length = 0; 165 m_buffer.ClearBuffer(); 166 m_encrypted = false; 167 } 168 169 // Do a deep-copy of the SecureString 170 [System.Security.SecuritySafeCritical] // auto-generated 171 [MethodImplAttribute(MethodImplOptions.Synchronized)] Copy()172 public SecureString Copy() { 173 EnsureNotDisposed(); 174 return new SecureString(this); 175 } 176 177 [System.Security.SecuritySafeCritical] // auto-generated 178 [MethodImplAttribute(MethodImplOptions.Synchronized)] Dispose()179 public void Dispose() { 180 if(m_buffer != null && !m_buffer.IsInvalid) { 181 m_buffer.Close(); 182 m_buffer = null; 183 } 184 } 185 186 [System.Security.SecuritySafeCritical] // auto-generated 187 [MethodImplAttribute(MethodImplOptions.Synchronized)] 188 #if FEATURE_CORRUPTING_EXCEPTIONS 189 [HandleProcessCorruptedStateExceptions] // 190 #endif // FEATURE_CORRUPTING_EXCEPTIONS InsertAt( int index, char c )191 public void InsertAt( int index, char c ) { 192 if( index < 0 || index > m_length) { 193 throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString")); 194 } 195 Contract.EndContractBlock(); 196 197 EnsureNotDisposed(); 198 EnsureNotReadOnly(); 199 200 EnsureCapacity(m_length + 1); 201 202 unsafe { 203 byte* bufferPtr = null; 204 RuntimeHelpers.PrepareConstrainedRegions(); 205 try { 206 UnProtectMemory(); 207 m_buffer.AcquirePointer(ref bufferPtr); 208 char* pBuffer = (char*)bufferPtr; 209 210 for (int i = m_length; i > index; i--) { 211 pBuffer[i] = pBuffer[i - 1]; 212 } 213 pBuffer[index] = c; 214 ++m_length; 215 } 216 catch (Exception) { 217 ProtectMemory(); 218 throw; 219 } 220 finally { 221 ProtectMemory(); 222 if (bufferPtr != null) 223 m_buffer.ReleasePointer(); 224 } 225 } 226 } 227 228 [System.Security.SecuritySafeCritical] // auto-generated 229 [MethodImplAttribute(MethodImplOptions.Synchronized)] IsReadOnly()230 public bool IsReadOnly() { 231 EnsureNotDisposed(); 232 return m_readOnly; 233 } 234 235 [System.Security.SecuritySafeCritical] // auto-generated 236 [MethodImplAttribute(MethodImplOptions.Synchronized)] MakeReadOnly()237 public void MakeReadOnly() { 238 EnsureNotDisposed(); 239 m_readOnly = true; 240 } 241 242 [System.Security.SecuritySafeCritical] // auto-generated 243 [MethodImplAttribute(MethodImplOptions.Synchronized)] 244 #if FEATURE_CORRUPTING_EXCEPTIONS 245 [HandleProcessCorruptedStateExceptions] // 246 #endif // FEATURE_CORRUPTING_EXCEPTIONS RemoveAt( int index )247 public void RemoveAt( int index ) { 248 EnsureNotDisposed(); 249 EnsureNotReadOnly(); 250 251 if( index < 0 || index >= m_length) { 252 throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString")); 253 } 254 255 unsafe 256 { 257 byte* bufferPtr = null; 258 RuntimeHelpers.PrepareConstrainedRegions(); 259 try 260 { 261 UnProtectMemory(); 262 m_buffer.AcquirePointer(ref bufferPtr); 263 char* pBuffer = (char*)bufferPtr; 264 265 for (int i = index; i < m_length - 1; i++) 266 { 267 pBuffer[i] = pBuffer[i + 1]; 268 } 269 pBuffer[--m_length] = (char)0; 270 } 271 catch (Exception) { 272 ProtectMemory(); 273 throw; 274 } 275 finally 276 { 277 ProtectMemory(); 278 if (bufferPtr != null) 279 m_buffer.ReleasePointer(); 280 } 281 } 282 } 283 284 [System.Security.SecuritySafeCritical] // auto-generated 285 [MethodImplAttribute(MethodImplOptions.Synchronized)] 286 #if FEATURE_CORRUPTING_EXCEPTIONS 287 [HandleProcessCorruptedStateExceptions] // 288 #endif // FEATURE_CORRUPTING_EXCEPTIONS SetAt( int index, char c )289 public void SetAt( int index, char c ) { 290 if( index < 0 || index >= m_length) { 291 throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString")); 292 } 293 Contract.EndContractBlock(); 294 Contract.Assert(index <= Int32.MaxValue / sizeof(char)); 295 296 EnsureNotDisposed(); 297 EnsureNotReadOnly(); 298 299 RuntimeHelpers.PrepareConstrainedRegions(); 300 try { 301 UnProtectMemory(); 302 m_buffer.Write<char>((uint)index * sizeof(char), c); 303 } 304 catch (Exception) { 305 ProtectMemory(); 306 throw; 307 } 308 finally { 309 ProtectMemory(); 310 } 311 } 312 313 private int BufferLength { 314 [System.Security.SecurityCritical] // auto-generated 315 get { 316 Contract.Assert(m_buffer != null, "Buffer is not initialized!"); 317 return m_buffer.Length; 318 } 319 } 320 321 [System.Security.SecurityCritical] // auto-generated 322 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] AllocateBuffer(int size)323 private void AllocateBuffer(int size) { 324 uint alignedSize = GetAlignedSize(size); 325 326 m_buffer = SafeBSTRHandle.Allocate(null, alignedSize); 327 if (m_buffer.IsInvalid) { 328 throw new OutOfMemoryException(); 329 } 330 } 331 CheckSupportedOnCurrentPlatform()332 private void CheckSupportedOnCurrentPlatform() { 333 if( !supportedOnCurrentPlatform) { 334 throw new NotSupportedException(Environment.GetResourceString("Arg_PlatformSecureString")); 335 } 336 Contract.EndContractBlock(); 337 } 338 339 [System.Security.SecurityCritical] // auto-generated EnsureCapacity(int capacity)340 private void EnsureCapacity(int capacity) { 341 if( capacity > MaxLength) { 342 throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_Capacity")); 343 } 344 Contract.EndContractBlock(); 345 346 if( capacity <= m_buffer.Length) { 347 return; 348 } 349 350 SafeBSTRHandle newBuffer = SafeBSTRHandle.Allocate(null, GetAlignedSize(capacity)); 351 352 if (newBuffer.IsInvalid) { 353 throw new OutOfMemoryException(); 354 } 355 356 SafeBSTRHandle.Copy(m_buffer, newBuffer); 357 m_buffer.Close(); 358 m_buffer = newBuffer; 359 } 360 361 [System.Security.SecurityCritical] // auto-generated EnsureNotDisposed()362 private void EnsureNotDisposed() { 363 if( m_buffer == null) { 364 throw new ObjectDisposedException(null); 365 } 366 Contract.EndContractBlock(); 367 } 368 EnsureNotReadOnly()369 private void EnsureNotReadOnly() { 370 if( m_readOnly) { 371 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); 372 } 373 Contract.EndContractBlock(); 374 } 375 376 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] GetAlignedSize( int size)377 private static uint GetAlignedSize( int size) { 378 Contract.Assert(size >= 0, "size must be non-negative"); 379 380 uint alignedSize = ((uint)size / BlockSize) * BlockSize; 381 if( (size % BlockSize != 0) || size == 0) { // if size is 0, set allocated size to blocksize 382 alignedSize += BlockSize; 383 } 384 return alignedSize; 385 } 386 387 [System.Security.SecurityCritical] // auto-generated GetAnsiByteCount()388 private unsafe int GetAnsiByteCount() { 389 const uint CP_ACP = 0; 390 const uint WC_NO_BEST_FIT_CHARS = 0x00000400; 391 392 uint flgs = WC_NO_BEST_FIT_CHARS; 393 uint DefaultCharUsed = (uint)'?'; 394 395 byte* bufferPtr = null; 396 RuntimeHelpers.PrepareConstrainedRegions(); 397 try { 398 m_buffer.AcquirePointer(ref bufferPtr); 399 400 return Win32Native.WideCharToMultiByte( 401 CP_ACP, 402 flgs, 403 (char*) bufferPtr, 404 m_length, 405 null, 406 0, 407 IntPtr.Zero, 408 new IntPtr((void*)&DefaultCharUsed)); 409 } 410 finally { 411 if (bufferPtr != null) 412 m_buffer.ReleasePointer(); 413 } 414 } 415 416 [System.Security.SecurityCritical] // auto-generated GetAnsiBytes( byte * ansiStrPtr, int byteCount)417 private unsafe void GetAnsiBytes( byte * ansiStrPtr, int byteCount) { 418 const uint CP_ACP = 0; 419 const uint WC_NO_BEST_FIT_CHARS = 0x00000400; 420 421 uint flgs = WC_NO_BEST_FIT_CHARS; 422 uint DefaultCharUsed = (uint)'?'; 423 424 byte* bufferPtr = null; 425 RuntimeHelpers.PrepareConstrainedRegions(); 426 try { 427 m_buffer.AcquirePointer(ref bufferPtr); 428 429 Win32Native.WideCharToMultiByte( 430 CP_ACP, 431 flgs, 432 (char*) bufferPtr, 433 m_length, 434 ansiStrPtr, 435 byteCount - 1, 436 IntPtr.Zero, 437 new IntPtr((void*)&DefaultCharUsed)); 438 439 *(ansiStrPtr + byteCount - 1) = (byte)0; 440 } 441 finally { 442 if (bufferPtr != null) 443 m_buffer.ReleasePointer(); 444 } 445 } 446 447 [System.Security.SecurityCritical] // auto-generated 448 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] ProtectMemory()449 private void ProtectMemory() { 450 Contract.Assert(!m_buffer.IsInvalid && m_buffer.Length != 0, "Invalid buffer!"); 451 Contract.Assert(m_buffer.Length % BlockSize == 0, "buffer length must be multiple of blocksize!"); 452 453 if( m_length == 0 || m_encrypted) { 454 return; 455 } 456 457 RuntimeHelpers.PrepareConstrainedRegions(); 458 try { 459 } 460 finally { 461 // RtlEncryptMemory return an NTSTATUS 462 int status = Win32Native.SystemFunction040(m_buffer, (uint)m_buffer.Length * 2, ProtectionScope); 463 if (status < 0) { // non-negative numbers indicate success 464 #if FEATURE_CORECLR 465 throw new CryptographicException(Win32Native.RtlNtStatusToDosError(status)); 466 #else 467 throw new CryptographicException(Win32Native.LsaNtStatusToWinError(status)); 468 #endif 469 } 470 m_encrypted = true; 471 } 472 } 473 474 [System.Security.SecurityCritical] // auto-generated 475 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 476 [MethodImplAttribute(MethodImplOptions.Synchronized)] 477 #if FEATURE_CORRUPTING_EXCEPTIONS 478 [HandleProcessCorruptedStateExceptions] // 479 #endif // FEATURE_CORRUPTING_EXCEPTIONS ToBSTR()480 internal unsafe IntPtr ToBSTR() { 481 EnsureNotDisposed(); 482 int length = m_length; 483 IntPtr ptr = IntPtr.Zero; 484 IntPtr result = IntPtr.Zero; 485 byte* bufferPtr = null; 486 487 RuntimeHelpers.PrepareConstrainedRegions(); 488 try { 489 RuntimeHelpers.PrepareConstrainedRegions(); 490 try { 491 } 492 finally { 493 ptr = Win32Native.SysAllocStringLen(null, length); 494 } 495 496 if (ptr == IntPtr.Zero) { 497 throw new OutOfMemoryException(); 498 } 499 500 UnProtectMemory(); 501 m_buffer.AcquirePointer(ref bufferPtr); 502 Buffer.Memcpy((byte*) ptr.ToPointer(), bufferPtr, length *2); 503 result = ptr; 504 } 505 catch (Exception) { 506 ProtectMemory(); 507 throw; 508 } 509 finally { 510 ProtectMemory(); 511 if( result == IntPtr.Zero) { 512 // If we failed for any reason, free the new buffer 513 if (ptr != IntPtr.Zero) { 514 Win32Native.ZeroMemory(ptr, (UIntPtr)(length * 2)); 515 Win32Native.SysFreeString(ptr); 516 } 517 } 518 if (bufferPtr != null) 519 m_buffer.ReleasePointer(); 520 } 521 return result; 522 } 523 524 [System.Security.SecurityCritical] // auto-generated 525 [MethodImplAttribute(MethodImplOptions.Synchronized)] 526 #if FEATURE_CORRUPTING_EXCEPTIONS 527 [HandleProcessCorruptedStateExceptions] // 528 #endif // FEATURE_CORRUPTING_EXCEPTIONS ToUniStr(bool allocateFromHeap)529 internal unsafe IntPtr ToUniStr(bool allocateFromHeap) { 530 EnsureNotDisposed(); 531 int length = m_length; 532 IntPtr ptr = IntPtr.Zero; 533 IntPtr result = IntPtr.Zero; 534 byte* bufferPtr = null; 535 536 RuntimeHelpers.PrepareConstrainedRegions(); 537 try { 538 RuntimeHelpers.PrepareConstrainedRegions(); 539 try { 540 } 541 finally { 542 if( allocateFromHeap) { 543 ptr = Marshal.AllocHGlobal((length + 1) * 2); 544 } 545 else { 546 ptr = Marshal.AllocCoTaskMem((length + 1) * 2); 547 } 548 } 549 550 if (ptr == IntPtr.Zero) { 551 throw new OutOfMemoryException(); 552 } 553 554 UnProtectMemory(); 555 m_buffer.AcquirePointer(ref bufferPtr); 556 Buffer.Memcpy((byte*) ptr.ToPointer(), bufferPtr, length *2); 557 char * endptr = (char *) ptr.ToPointer(); 558 *(endptr + length) = '\0'; 559 result = ptr; 560 } 561 catch (Exception) { 562 ProtectMemory(); 563 throw; 564 } 565 finally { 566 ProtectMemory(); 567 568 if( result == IntPtr.Zero) { 569 // If we failed for any reason, free the new buffer 570 if (ptr != IntPtr.Zero) { 571 Win32Native.ZeroMemory(ptr, (UIntPtr)(length * 2)); 572 if( allocateFromHeap) { 573 Marshal.FreeHGlobal(ptr); 574 } 575 else { 576 Marshal.FreeCoTaskMem(ptr); 577 } 578 } 579 } 580 581 if (bufferPtr != null) 582 m_buffer.ReleasePointer(); 583 } 584 return result; 585 } 586 587 [System.Security.SecurityCritical] // auto-generated 588 [MethodImplAttribute(MethodImplOptions.Synchronized)] 589 #if FEATURE_CORRUPTING_EXCEPTIONS 590 [HandleProcessCorruptedStateExceptions] // 591 #endif // FEATURE_CORRUPTING_EXCEPTIONS ToAnsiStr(bool allocateFromHeap)592 internal unsafe IntPtr ToAnsiStr(bool allocateFromHeap) { 593 EnsureNotDisposed(); 594 595 IntPtr ptr = IntPtr.Zero; 596 IntPtr result = IntPtr.Zero; 597 int byteCount = 0; 598 RuntimeHelpers.PrepareConstrainedRegions(); 599 try { 600 // GetAnsiByteCount uses the string data, so the calculation must happen after we are decrypted. 601 UnProtectMemory(); 602 603 // allocating an extra char for terminating zero 604 byteCount = GetAnsiByteCount() + 1; 605 606 RuntimeHelpers.PrepareConstrainedRegions(); 607 try { 608 } 609 finally { 610 if( allocateFromHeap) { 611 ptr = Marshal.AllocHGlobal(byteCount); 612 } 613 else { 614 ptr = Marshal.AllocCoTaskMem(byteCount); 615 } 616 } 617 618 if (ptr == IntPtr.Zero) { 619 throw new OutOfMemoryException(); 620 } 621 622 GetAnsiBytes((byte *)ptr.ToPointer(), byteCount); 623 result = ptr; 624 } 625 catch (Exception) { 626 ProtectMemory(); 627 throw; 628 } 629 finally { 630 ProtectMemory(); 631 if( result == IntPtr.Zero) { 632 // If we failed for any reason, free the new buffer 633 if (ptr != IntPtr.Zero) { 634 Win32Native.ZeroMemory(ptr, (UIntPtr)byteCount); 635 if( allocateFromHeap) { 636 Marshal.FreeHGlobal(ptr); 637 } 638 else { 639 Marshal.FreeCoTaskMem(ptr); 640 } 641 } 642 } 643 644 } 645 return result; 646 } 647 648 [System.Security.SecurityCritical] // auto-generated 649 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] UnProtectMemory()650 private void UnProtectMemory() { 651 Contract.Assert(!m_buffer.IsInvalid && m_buffer.Length != 0, "Invalid buffer!"); 652 Contract.Assert(m_buffer.Length % BlockSize == 0, "buffer length must be multiple of blocksize!"); 653 654 if( m_length == 0) { 655 return; 656 } 657 658 RuntimeHelpers.PrepareConstrainedRegions(); 659 try { 660 } 661 finally { 662 if (m_encrypted) { 663 // RtlEncryptMemory return an NTSTATUS 664 int status = Win32Native.SystemFunction041(m_buffer, (uint)m_buffer.Length * 2, ProtectionScope); 665 if (status < 0) 666 { // non-negative numbers indicate success 667 #if FEATURE_CORECLR 668 throw new CryptographicException(Win32Native.RtlNtStatusToDosError(status)); 669 #else 670 throw new CryptographicException(Win32Native.LsaNtStatusToWinError(status)); 671 #endif 672 } 673 m_encrypted = false; 674 } 675 } 676 } 677 } 678 679 [System.Security.SecurityCritical] // auto-generated 680 [SuppressUnmanagedCodeSecurityAttribute()] 681 internal sealed class SafeBSTRHandle : SafeBuffer { SafeBSTRHandle()682 internal SafeBSTRHandle () : base(true) {} 683 Allocate(String src, uint len)684 internal static SafeBSTRHandle Allocate(String src, uint len) 685 { 686 SafeBSTRHandle bstr = SysAllocStringLen(src, len); 687 bstr.Initialize(len * sizeof(char)); 688 return bstr; 689 } 690 691 [ResourceExposure(ResourceScope.None)] 692 [DllImport(Win32Native.OLEAUT32, CharSet = CharSet.Unicode)] 693 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] SysAllocStringLen(String src, uint len)694 private static extern SafeBSTRHandle SysAllocStringLen(String src, uint len); // BSTR 695 696 [System.Security.SecurityCritical] ReleaseHandle()697 override protected bool ReleaseHandle() 698 { 699 Win32Native.ZeroMemory(handle, (UIntPtr) (Win32Native.SysStringLen(handle) * 2)); 700 Win32Native.SysFreeString(handle); 701 return true; 702 } 703 704 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] ClearBuffer()705 internal unsafe void ClearBuffer() { 706 byte* bufferPtr = null; 707 RuntimeHelpers.PrepareConstrainedRegions(); 708 try 709 { 710 AcquirePointer(ref bufferPtr); 711 Win32Native.ZeroMemory((IntPtr)bufferPtr, (UIntPtr) (Win32Native.SysStringLen((IntPtr)bufferPtr) * 2)); 712 } 713 finally 714 { 715 if (bufferPtr != null) 716 ReleasePointer(); 717 } 718 } 719 720 721 internal unsafe int Length { 722 get { 723 return (int) Win32Native.SysStringLen(this); 724 } 725 } 726 Copy(SafeBSTRHandle source, SafeBSTRHandle target)727 internal unsafe static void Copy(SafeBSTRHandle source, SafeBSTRHandle target) { 728 byte* sourcePtr = null, targetPtr = null; 729 RuntimeHelpers.PrepareConstrainedRegions(); 730 try 731 { 732 source.AcquirePointer(ref sourcePtr); 733 target.AcquirePointer(ref targetPtr); 734 735 Contract.Assert(Win32Native.SysStringLen((IntPtr)targetPtr) >= Win32Native.SysStringLen((IntPtr)sourcePtr), "Target buffer is not large enough!"); 736 737 Buffer.Memcpy(targetPtr, sourcePtr, (int) Win32Native.SysStringLen((IntPtr)sourcePtr) * 2); 738 } 739 finally 740 { 741 if (sourcePtr != null) 742 source.ReleasePointer(); 743 if (targetPtr != null) 744 target.ReleasePointer(); 745 } 746 } 747 } 748 } 749 750