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.Data.Common; 6 using System.Diagnostics; 7 using System.Runtime.CompilerServices; 8 using System.Runtime.InteropServices; 9 10 namespace System.Data.ProviderBase 11 { 12 // DbBuffer is abstract to require derived class to exist 13 // so that when debugging, we can tell the difference between one DbBuffer and another 14 internal abstract class DbBuffer : SafeHandle 15 { 16 private readonly int _bufferLength; 17 DbBuffer(int initialSize)18 protected DbBuffer(int initialSize) : base(IntPtr.Zero, true) 19 { 20 if (0 < initialSize) 21 { 22 _bufferLength = initialSize; 23 RuntimeHelpers.PrepareConstrainedRegions(); 24 try { } 25 finally 26 { 27 base.handle = SafeNativeMethods.LocalAlloc((IntPtr)initialSize); 28 } 29 if (IntPtr.Zero == base.handle) 30 { 31 throw new OutOfMemoryException(); 32 } 33 } 34 } 35 DbBuffer(IntPtr invalidHandleValue, bool ownsHandle)36 protected DbBuffer(IntPtr invalidHandleValue, bool ownsHandle) : base(invalidHandleValue, ownsHandle) 37 { 38 } 39 40 private int BaseOffset { get { return 0; } } 41 42 public override bool IsInvalid 43 { 44 get 45 { 46 return (IntPtr.Zero == base.handle); 47 } 48 } 49 50 internal int Length 51 { 52 get 53 { 54 return _bufferLength; 55 } 56 } 57 PtrToStringUni(int offset)58 internal string PtrToStringUni(int offset) 59 { 60 offset += BaseOffset; 61 Validate(offset, 2); 62 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 63 64 string value = null; 65 bool mustRelease = false; 66 RuntimeHelpers.PrepareConstrainedRegions(); 67 try 68 { 69 DangerousAddRef(ref mustRelease); 70 71 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 72 value = Marshal.PtrToStringUni(ptr); 73 Validate(offset, (2 * (value.Length + 1))); 74 } 75 finally 76 { 77 if (mustRelease) 78 { 79 DangerousRelease(); 80 } 81 } 82 83 return value; 84 } 85 PtrToStringUni(int offset, int length)86 internal String PtrToStringUni(int offset, int length) 87 { 88 offset += BaseOffset; 89 Validate(offset, 2 * length); 90 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 91 92 string value = null; 93 bool mustRelease = false; 94 RuntimeHelpers.PrepareConstrainedRegions(); 95 try 96 { 97 DangerousAddRef(ref mustRelease); 98 99 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 100 value = Marshal.PtrToStringUni(ptr, length); 101 } 102 finally 103 { 104 if (mustRelease) 105 { 106 DangerousRelease(); 107 } 108 } 109 return value; 110 } 111 ReadByte(int offset)112 internal byte ReadByte(int offset) 113 { 114 offset += BaseOffset; 115 ValidateCheck(offset, 1); 116 Debug.Assert(0 == offset % 4, "invalid alignment"); 117 118 byte value; 119 bool mustRelease = false; 120 RuntimeHelpers.PrepareConstrainedRegions(); 121 try 122 { 123 DangerousAddRef(ref mustRelease); 124 125 IntPtr ptr = DangerousGetHandle(); 126 value = Marshal.ReadByte(ptr, offset); 127 } 128 finally 129 { 130 if (mustRelease) 131 { 132 DangerousRelease(); 133 } 134 } 135 return value; 136 } 137 ReadBytes(int offset, int length)138 internal byte[] ReadBytes(int offset, int length) 139 { 140 byte[] value = new byte[length]; 141 return ReadBytes(offset, value, 0, length); 142 } 143 ReadBytes(int offset, byte[] destination, int startIndex, int length)144 internal byte[] ReadBytes(int offset, byte[] destination, int startIndex, int length) 145 { 146 offset += BaseOffset; 147 Validate(offset, length); 148 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 149 Debug.Assert(null != destination, "null destination"); 150 Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 151 152 bool mustRelease = false; 153 RuntimeHelpers.PrepareConstrainedRegions(); 154 try 155 { 156 DangerousAddRef(ref mustRelease); 157 158 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 159 Marshal.Copy(ptr, destination, startIndex, length); 160 } 161 finally 162 { 163 if (mustRelease) 164 { 165 DangerousRelease(); 166 } 167 } 168 return destination; 169 } 170 ReadChar(int offset)171 internal Char ReadChar(int offset) 172 { 173 short value = ReadInt16(offset); 174 return unchecked((char)value); 175 } 176 ReadChars(int offset, char[] destination, int startIndex, int length)177 internal char[] ReadChars(int offset, char[] destination, int startIndex, int length) 178 { 179 offset += BaseOffset; 180 Validate(offset, 2 * length); 181 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 182 Debug.Assert(null != destination, "null destination"); 183 Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 184 185 bool mustRelease = false; 186 RuntimeHelpers.PrepareConstrainedRegions(); 187 try 188 { 189 DangerousAddRef(ref mustRelease); 190 191 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 192 Marshal.Copy(ptr, destination, startIndex, length); 193 } 194 finally 195 { 196 if (mustRelease) 197 { 198 DangerousRelease(); 199 } 200 } 201 return destination; 202 } 203 ReadDouble(int offset)204 internal Double ReadDouble(int offset) 205 { 206 Int64 value = ReadInt64(offset); 207 return BitConverter.Int64BitsToDouble(value); 208 } 209 ReadInt16(int offset)210 internal Int16 ReadInt16(int offset) 211 { 212 offset += BaseOffset; 213 ValidateCheck(offset, 2); 214 Debug.Assert(0 == offset % 2, "invalid alignment"); 215 216 short value; 217 bool mustRelease = false; 218 RuntimeHelpers.PrepareConstrainedRegions(); 219 try 220 { 221 DangerousAddRef(ref mustRelease); 222 223 IntPtr ptr = DangerousGetHandle(); 224 value = Marshal.ReadInt16(ptr, offset); 225 } 226 finally 227 { 228 if (mustRelease) 229 { 230 DangerousRelease(); 231 } 232 } 233 return value; 234 } 235 ReadInt16Array(int offset, short[] destination, int startIndex, int length)236 internal void ReadInt16Array(int offset, short[] destination, int startIndex, int length) 237 { 238 offset += BaseOffset; 239 Validate(offset, 2 * length); 240 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 241 Debug.Assert(null != destination, "null destination"); 242 Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 243 244 bool mustRelease = false; 245 RuntimeHelpers.PrepareConstrainedRegions(); 246 try 247 { 248 DangerousAddRef(ref mustRelease); 249 250 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 251 Marshal.Copy(ptr, destination, startIndex, length); 252 } 253 finally 254 { 255 if (mustRelease) 256 { 257 DangerousRelease(); 258 } 259 } 260 } 261 ReadInt32(int offset)262 internal Int32 ReadInt32(int offset) 263 { 264 offset += BaseOffset; 265 ValidateCheck(offset, 4); 266 Debug.Assert(0 == offset % 4, "invalid alignment"); 267 268 int value; 269 bool mustRelease = false; 270 RuntimeHelpers.PrepareConstrainedRegions(); 271 try 272 { 273 DangerousAddRef(ref mustRelease); 274 275 IntPtr ptr = DangerousGetHandle(); 276 value = Marshal.ReadInt32(ptr, offset); 277 } 278 finally 279 { 280 if (mustRelease) 281 { 282 DangerousRelease(); 283 } 284 } 285 return value; 286 } 287 ReadInt32Array(int offset, int[] destination, int startIndex, int length)288 internal void ReadInt32Array(int offset, int[] destination, int startIndex, int length) 289 { 290 offset += BaseOffset; 291 Validate(offset, 4 * length); 292 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 293 Debug.Assert(null != destination, "null destination"); 294 Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 295 296 bool mustRelease = false; 297 RuntimeHelpers.PrepareConstrainedRegions(); 298 try 299 { 300 DangerousAddRef(ref mustRelease); 301 302 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 303 Marshal.Copy(ptr, destination, startIndex, length); 304 } 305 finally 306 { 307 if (mustRelease) 308 { 309 DangerousRelease(); 310 } 311 } 312 } 313 ReadInt64(int offset)314 internal Int64 ReadInt64(int offset) 315 { 316 offset += BaseOffset; 317 ValidateCheck(offset, 8); 318 Debug.Assert(0 == offset % IntPtr.Size, "invalid alignment"); 319 320 long value; 321 bool mustRelease = false; 322 RuntimeHelpers.PrepareConstrainedRegions(); 323 try 324 { 325 DangerousAddRef(ref mustRelease); 326 327 IntPtr ptr = DangerousGetHandle(); 328 value = Marshal.ReadInt64(ptr, offset); 329 } 330 finally 331 { 332 if (mustRelease) 333 { 334 DangerousRelease(); 335 } 336 } 337 return value; 338 } 339 ReadIntPtr(int offset)340 internal IntPtr ReadIntPtr(int offset) 341 { 342 offset += BaseOffset; 343 ValidateCheck(offset, IntPtr.Size); 344 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 345 346 IntPtr value; 347 bool mustRelease = false; 348 RuntimeHelpers.PrepareConstrainedRegions(); 349 try 350 { 351 DangerousAddRef(ref mustRelease); 352 353 IntPtr ptr = DangerousGetHandle(); 354 value = Marshal.ReadIntPtr(ptr, offset); 355 } 356 finally 357 { 358 if (mustRelease) 359 { 360 DangerousRelease(); 361 } 362 } 363 return value; 364 } 365 ReadSingle(int offset)366 internal unsafe Single ReadSingle(int offset) 367 { 368 Int32 value = ReadInt32(offset); 369 return *(Single*)&value; 370 } 371 ReleaseHandle()372 protected override bool ReleaseHandle() 373 { 374 // NOTE: The SafeHandle class guarantees this will be called exactly once. 375 IntPtr ptr = base.handle; 376 base.handle = IntPtr.Zero; 377 if (IntPtr.Zero != ptr) 378 { 379 SafeNativeMethods.LocalFree(ptr); 380 } 381 return true; 382 } 383 StructureToPtr(int offset, object structure)384 private void StructureToPtr(int offset, object structure) 385 { 386 Debug.Assert(null != structure, "null structure"); 387 offset += BaseOffset; 388 ValidateCheck(offset, Marshal.SizeOf(structure.GetType())); 389 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 390 391 bool mustRelease = false; 392 RuntimeHelpers.PrepareConstrainedRegions(); 393 try 394 { 395 DangerousAddRef(ref mustRelease); 396 397 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 398 Marshal.StructureToPtr(structure, ptr, false/*fDeleteOld*/); 399 } 400 finally 401 { 402 if (mustRelease) 403 { 404 DangerousRelease(); 405 } 406 } 407 } 408 WriteByte(int offset, byte value)409 internal void WriteByte(int offset, byte value) 410 { 411 offset += BaseOffset; 412 ValidateCheck(offset, 1); 413 Debug.Assert(0 == offset % 4, "invalid alignment"); 414 415 bool mustRelease = false; 416 RuntimeHelpers.PrepareConstrainedRegions(); 417 try 418 { 419 DangerousAddRef(ref mustRelease); 420 421 IntPtr ptr = DangerousGetHandle(); 422 Marshal.WriteByte(ptr, offset, value); 423 } 424 finally 425 { 426 if (mustRelease) 427 { 428 DangerousRelease(); 429 } 430 } 431 } 432 WriteBytes(int offset, byte[] source, int startIndex, int length)433 internal void WriteBytes(int offset, byte[] source, int startIndex, int length) 434 { 435 offset += BaseOffset; 436 Validate(offset, length); 437 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 438 Debug.Assert(null != source, "null source"); 439 Debug.Assert(startIndex + length <= source.Length, "source too small"); 440 441 bool mustRelease = false; 442 RuntimeHelpers.PrepareConstrainedRegions(); 443 try 444 { 445 DangerousAddRef(ref mustRelease); 446 447 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 448 Marshal.Copy(source, startIndex, ptr, length); 449 } 450 finally 451 { 452 if (mustRelease) 453 { 454 DangerousRelease(); 455 } 456 } 457 } 458 WriteCharArray(int offset, char[] source, int startIndex, int length)459 internal void WriteCharArray(int offset, char[] source, int startIndex, int length) 460 { 461 offset += BaseOffset; 462 Validate(offset, 2 * length); 463 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 464 Debug.Assert(null != source, "null source"); 465 Debug.Assert(startIndex + length <= source.Length, "source too small"); 466 467 bool mustRelease = false; 468 RuntimeHelpers.PrepareConstrainedRegions(); 469 try 470 { 471 DangerousAddRef(ref mustRelease); 472 473 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 474 Marshal.Copy(source, startIndex, ptr, length); 475 } 476 finally 477 { 478 if (mustRelease) 479 { 480 DangerousRelease(); 481 } 482 } 483 } 484 WriteDouble(int offset, Double value)485 internal void WriteDouble(int offset, Double value) 486 { 487 WriteInt64(offset, BitConverter.DoubleToInt64Bits(value)); 488 } 489 WriteInt16(int offset, short value)490 internal void WriteInt16(int offset, short value) 491 { 492 offset += BaseOffset; 493 ValidateCheck(offset, 2); 494 Debug.Assert(0 == offset % 2, "invalid alignment"); 495 496 bool mustRelease = false; 497 RuntimeHelpers.PrepareConstrainedRegions(); 498 try 499 { 500 DangerousAddRef(ref mustRelease); 501 502 IntPtr ptr = DangerousGetHandle(); 503 Marshal.WriteInt16(ptr, offset, value); 504 } 505 finally 506 { 507 if (mustRelease) 508 { 509 DangerousRelease(); 510 } 511 } 512 } 513 WriteInt16Array(int offset, short[] source, int startIndex, int length)514 internal void WriteInt16Array(int offset, short[] source, int startIndex, int length) 515 { 516 offset += BaseOffset; 517 Validate(offset, 2 * length); 518 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 519 Debug.Assert(null != source, "null source"); 520 Debug.Assert(startIndex + length <= source.Length, "source too small"); 521 522 bool mustRelease = false; 523 RuntimeHelpers.PrepareConstrainedRegions(); 524 try 525 { 526 DangerousAddRef(ref mustRelease); 527 528 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 529 Marshal.Copy(source, startIndex, ptr, length); 530 } 531 finally 532 { 533 if (mustRelease) 534 { 535 DangerousRelease(); 536 } 537 } 538 } 539 WriteInt32(int offset, int value)540 internal void WriteInt32(int offset, int value) 541 { 542 offset += BaseOffset; 543 ValidateCheck(offset, 4); 544 Debug.Assert(0 == offset % 4, "invalid alignment"); 545 546 bool mustRelease = false; 547 RuntimeHelpers.PrepareConstrainedRegions(); 548 try 549 { 550 DangerousAddRef(ref mustRelease); 551 552 IntPtr ptr = DangerousGetHandle(); 553 Marshal.WriteInt32(ptr, offset, value); 554 } 555 finally 556 { 557 if (mustRelease) 558 { 559 DangerousRelease(); 560 } 561 } 562 } 563 WriteInt32Array(int offset, int[] source, int startIndex, int length)564 internal void WriteInt32Array(int offset, int[] source, int startIndex, int length) 565 { 566 offset += BaseOffset; 567 Validate(offset, 4 * length); 568 Debug.Assert(0 == offset % ADP.PtrSize, "invalid alignment"); 569 Debug.Assert(null != source, "null source"); 570 Debug.Assert(startIndex + length <= source.Length, "source too small"); 571 572 bool mustRelease = false; 573 RuntimeHelpers.PrepareConstrainedRegions(); 574 try 575 { 576 DangerousAddRef(ref mustRelease); 577 578 IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 579 Marshal.Copy(source, startIndex, ptr, length); 580 } 581 finally 582 { 583 if (mustRelease) 584 { 585 DangerousRelease(); 586 } 587 } 588 } 589 WriteInt64(int offset, long value)590 internal void WriteInt64(int offset, long value) 591 { 592 offset += BaseOffset; 593 ValidateCheck(offset, 8); 594 Debug.Assert(0 == offset % IntPtr.Size, "invalid alignment"); 595 596 bool mustRelease = false; 597 RuntimeHelpers.PrepareConstrainedRegions(); 598 try 599 { 600 DangerousAddRef(ref mustRelease); 601 602 IntPtr ptr = DangerousGetHandle(); 603 Marshal.WriteInt64(ptr, offset, value); 604 } 605 finally 606 { 607 if (mustRelease) 608 { 609 DangerousRelease(); 610 } 611 } 612 } 613 WriteIntPtr(int offset, IntPtr value)614 internal void WriteIntPtr(int offset, IntPtr value) 615 { 616 offset += BaseOffset; 617 ValidateCheck(offset, IntPtr.Size); 618 Debug.Assert(0 == offset % IntPtr.Size, "invalid alignment"); 619 620 bool mustRelease = false; 621 RuntimeHelpers.PrepareConstrainedRegions(); 622 try 623 { 624 DangerousAddRef(ref mustRelease); 625 626 IntPtr ptr = DangerousGetHandle(); 627 Marshal.WriteIntPtr(ptr, offset, value); 628 } 629 finally 630 { 631 if (mustRelease) 632 { 633 DangerousRelease(); 634 } 635 } 636 } 637 WriteSingle(int offset, Single value)638 internal unsafe void WriteSingle(int offset, Single value) 639 { 640 WriteInt32(offset, *(Int32*)&value); 641 } 642 ZeroMemory()643 internal void ZeroMemory() 644 { 645 bool mustRelease = false; 646 RuntimeHelpers.PrepareConstrainedRegions(); 647 try 648 { 649 DangerousAddRef(ref mustRelease); 650 651 IntPtr ptr = DangerousGetHandle(); 652 SafeNativeMethods.ZeroMemory(ptr, Length); 653 } 654 finally 655 { 656 if (mustRelease) 657 { 658 DangerousRelease(); 659 } 660 } 661 } 662 ReadGuid(int offset)663 internal Guid ReadGuid(int offset) 664 { 665 // faster than Marshal.PtrToStructure(offset, typeof(Guid)) 666 byte[] buffer = new byte[16]; 667 ReadBytes(offset, buffer, 0, 16); 668 return new Guid(buffer); 669 } WriteGuid(int offset, Guid value)670 internal void WriteGuid(int offset, Guid value) 671 { 672 // faster than Marshal.Copy(value.GetByteArray() 673 StructureToPtr(offset, value); 674 } 675 ReadDate(int offset)676 internal DateTime ReadDate(int offset) 677 { 678 short[] buffer = new short[3]; 679 ReadInt16Array(offset, buffer, 0, 3); 680 return new DateTime( 681 unchecked((ushort)buffer[0]), // Year 682 unchecked((ushort)buffer[1]), // Month 683 unchecked((ushort)buffer[2])); // Day 684 } WriteDate(int offset, DateTime value)685 internal void WriteDate(int offset, DateTime value) 686 { 687 short[] buffer = new short[3] { 688 unchecked((short)value.Year), 689 unchecked((short)value.Month), 690 unchecked((short)value.Day), 691 }; 692 WriteInt16Array(offset, buffer, 0, 3); 693 } 694 ReadTime(int offset)695 internal TimeSpan ReadTime(int offset) 696 { 697 short[] buffer = new short[3]; 698 ReadInt16Array(offset, buffer, 0, 3); 699 return new TimeSpan( 700 unchecked((ushort)buffer[0]), // Hours 701 unchecked((ushort)buffer[1]), // Minutes 702 unchecked((ushort)buffer[2])); // Seconds 703 } WriteTime(int offset, TimeSpan value)704 internal void WriteTime(int offset, TimeSpan value) 705 { 706 short[] buffer = new short[3] { 707 unchecked((short)value.Hours), 708 unchecked((short)value.Minutes), 709 unchecked((short)value.Seconds), 710 }; 711 WriteInt16Array(offset, buffer, 0, 3); 712 } 713 ReadDateTime(int offset)714 internal DateTime ReadDateTime(int offset) 715 { 716 short[] buffer = new short[6]; 717 ReadInt16Array(offset, buffer, 0, 6); 718 int ticks = ReadInt32(offset + 12); 719 DateTime value = new DateTime( 720 unchecked((ushort)buffer[0]), // Year 721 unchecked((ushort)buffer[1]), // Month 722 unchecked((ushort)buffer[2]), // Day 723 unchecked((ushort)buffer[3]), // Hours 724 unchecked((ushort)buffer[4]), // Minutes 725 unchecked((ushort)buffer[5])); // Seconds 726 return value.AddTicks(ticks / 100); 727 } WriteDateTime(int offset, DateTime value)728 internal void WriteDateTime(int offset, DateTime value) 729 { 730 int ticks = (int)(value.Ticks % 10000000L) * 100; 731 short[] buffer = new short[6] { 732 unchecked((short)value.Year), 733 unchecked((short)value.Month), 734 unchecked((short)value.Day), 735 unchecked((short)value.Hour), 736 unchecked((short)value.Minute), 737 unchecked((short)value.Second), 738 }; 739 WriteInt16Array(offset, buffer, 0, 6); 740 WriteInt32(offset + 12, ticks); 741 } 742 ReadNumeric(int offset)743 internal Decimal ReadNumeric(int offset) 744 { 745 byte[] bits = new byte[20]; 746 ReadBytes(offset, bits, 1, 19); 747 748 int[] buffer = new int[4]; 749 buffer[3] = ((int)bits[2]) << 16; // scale 750 if (0 == bits[3]) 751 { 752 buffer[3] |= unchecked((int)0x80000000); //sign 753 } 754 buffer[0] = BitConverter.ToInt32(bits, 4); // low 755 buffer[1] = BitConverter.ToInt32(bits, 8); // mid 756 buffer[2] = BitConverter.ToInt32(bits, 12); // high 757 if (0 != BitConverter.ToInt32(bits, 16)) 758 { 759 throw ADP.NumericToDecimalOverflow(); 760 } 761 return new Decimal(buffer); 762 } 763 WriteNumeric(int offset, Decimal value, byte precision)764 internal void WriteNumeric(int offset, Decimal value, byte precision) 765 { 766 int[] tmp = Decimal.GetBits(value); 767 byte[] buffer = new byte[20]; 768 769 buffer[1] = precision; 770 Buffer.BlockCopy(tmp, 14, buffer, 2, 2); // copy sign and scale 771 buffer[3] = (Byte)((0 == buffer[3]) ? 1 : 0); // flip sign for native 772 Buffer.BlockCopy(tmp, 0, buffer, 4, 12); 773 buffer[16] = 0; 774 buffer[17] = 0; 775 buffer[18] = 0; 776 buffer[19] = 0; 777 WriteBytes(offset, buffer, 1, 19); 778 } 779 780 [ConditionalAttribute("DEBUG")] ValidateCheck(int offset, int count)781 protected void ValidateCheck(int offset, int count) 782 { 783 Validate(offset, count); 784 } 785 Validate(int offset, int count)786 protected void Validate(int offset, int count) 787 { 788 if ((offset < 0) || (count < 0) || (Length < checked(offset + count))) 789 { 790 throw ADP.InternalError(ADP.InternalErrorCode.InvalidBuffer); 791 } 792 } 793 } 794 }