Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
4.5 KiB

  1. /*++
  2. Copyright (c) 1990-1993 Microsoft Corporation
  3. Module Name:
  4. probe.c
  5. Abstract:
  6. This module implements the probe for write function.
  7. Author:
  8. David N. Cutler (davec) 19-Jan-1990
  9. Environment:
  10. Any mode.
  11. Revision History:
  12. --*/
  13. #include "exp.h"
  14. #if defined(_WIN64)
  15. #include <wow64t.h>
  16. #endif
  17. #if defined(ALLOC_PRAGMA)
  18. #pragma alloc_text(PAGE, ProbeForWrite)
  19. #pragma alloc_text(PAGE, ProbeForRead)
  20. #endif
  21. VOID
  22. ProbeForWrite (
  23. IN PVOID Address,
  24. IN SIZE_T Length,
  25. IN ULONG Alignment
  26. )
  27. /*++
  28. Routine Description:
  29. This function probes a structure for write accessibility and ensures
  30. correct alignment of the structure. If the structure is not accessible
  31. or has incorrect alignment, then an exception is raised.
  32. Arguments:
  33. Address - Supplies a pointer to the structure to be probed.
  34. Length - Supplies the length of the structure.
  35. Alignment - Supplies the required alignment of the structure expressed
  36. as the number of bytes in the primitive datatype (e.g., 1 for char,
  37. 2 for short, 4 for long, and 8 for quad).
  38. Return Value:
  39. None.
  40. --*/
  41. {
  42. ULONG_PTR EndAddress;
  43. ULONG_PTR StartAddress;
  44. #if defined(_WIN64)
  45. ULONG_PTR PageSize;
  46. #else
  47. #define PageSize PAGE_SIZE
  48. #endif
  49. //
  50. // If the structure has zero length, then do not probe the structure for
  51. // write accessibility or alignment.
  52. //
  53. if (Length != 0) {
  54. //
  55. // If the structure is not properly aligned, then raise a data
  56. // misalignment exception.
  57. //
  58. ASSERT((Alignment == 1) || (Alignment == 2) ||
  59. (Alignment == 4) || (Alignment == 8) ||
  60. (Alignment == 16));
  61. StartAddress = (ULONG_PTR)Address;
  62. if ((StartAddress & (Alignment - 1)) == 0) {
  63. //
  64. // Compute the ending address of the structure and probe for
  65. // write accessibility.
  66. //
  67. EndAddress = StartAddress + Length - 1;
  68. if ((StartAddress <= EndAddress) &&
  69. (EndAddress < MM_USER_PROBE_ADDRESS)) {
  70. //
  71. // N.B. Only the contents of the buffer may be probed.
  72. // Therefore the starting byte is probed for the
  73. // first page, and then the first byte in the page
  74. // for each succeeding page.
  75. //
  76. #if defined(_WIN64)
  77. //
  78. // If this is a Wow64 process, then the native page is 4K, which
  79. // could be smaller than the native page size/
  80. //
  81. if (PsGetCurrentProcess()->Wow64Process != NULL) {
  82. PageSize = PAGE_SIZE_X86NT;
  83. } else {
  84. PageSize = PAGE_SIZE;
  85. }
  86. #endif
  87. EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize;
  88. do {
  89. *(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;
  90. StartAddress = (StartAddress & ~(PageSize - 1)) + PageSize;
  91. } while (StartAddress != EndAddress);
  92. return;
  93. } else {
  94. ExRaiseAccessViolation();
  95. }
  96. } else {
  97. ExRaiseDatatypeMisalignment();
  98. }
  99. }
  100. return;
  101. }
  102. #undef ProbeForRead
  103. NTKERNELAPI
  104. VOID
  105. NTAPI
  106. ProbeForRead(
  107. IN CONST VOID *Address,
  108. IN SIZE_T Length,
  109. IN ULONG Alignment
  110. )
  111. /*++
  112. Routine Description:
  113. This function probes a structure for read accessibility and ensures
  114. correct alignment of the structure. If the structure is not accessible
  115. or has incorrect alignment, then an exception is raised.
  116. Arguments:
  117. Address - Supplies a pointer to the structure to be probed.
  118. Length - Supplies the length of the structure.
  119. Alignment - Supplies the required alignment of the structure expressed
  120. as the number of bytes in the primitive datatype (e.g., 1 for char,
  121. 2 for short, 4 for long, and 8 for quad).
  122. Return Value:
  123. None.
  124. --*/
  125. {
  126. PAGED_CODE();
  127. ASSERT(((Alignment) == 1) || ((Alignment) == 2) ||
  128. ((Alignment) == 4) || ((Alignment) == 8) ||
  129. ((Alignment) == 16));
  130. if ((Length) != 0) {
  131. if (((ULONG_PTR)(Address) & ((Alignment) - 1)) != 0) {
  132. ExRaiseDatatypeMisalignment();
  133. } else if ((((ULONG_PTR)(Address) + (Length)) < (ULONG_PTR)(Address)) ||
  134. (((ULONG_PTR)(Address) + (Length)) > (ULONG_PTR)MM_USER_PROBE_ADDRESS)) {
  135. ExRaiseAccessViolation();
  136. }
  137. }
  138. }