Leaked source code of windows server 2003
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.

204 lines
5.7 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. secmem.c
  5. Abstract:
  6. This module implements a user level callback for securing memory for SAN IOs.
  7. Author:
  8. Nar Ganapathy (narg) 8-Feb-2000
  9. Revision History:
  10. --*/
  11. #include "ntrtlp.h"
  12. ULONG_PTR RtlSecureMemorySystemRangeStart;
  13. PRTL_SECURE_MEMORY_CACHE_CALLBACK RtlSecureMemoryCacheCallback = NULL;
  14. NTSTATUS
  15. RtlRegisterSecureMemoryCacheCallback(
  16. IN PRTL_SECURE_MEMORY_CACHE_CALLBACK Callback
  17. )
  18. /*++
  19. Routine Description:
  20. This routine allows a library to register to be called back whenever
  21. memory is freed or its protections are changed. This is useful for
  22. maintaining user level secure memory cache for SAN applications.
  23. Current customer is winsock DP.
  24. Arguments:
  25. CallBack - Supplies a pointer to the callback routine
  26. Return Value:
  27. NTSTATUS code. Returns STATUS_SUCCESS if we could sucessfully register
  28. the callback.
  29. --*/
  30. {
  31. NTSTATUS status;
  32. status = NtQuerySystemInformation(SystemRangeStartInformation,
  33. &RtlSecureMemorySystemRangeStart,
  34. sizeof(RtlSecureMemorySystemRangeStart),
  35. NULL);
  36. if (!NT_SUCCESS(status)) {
  37. return status;
  38. }
  39. if (!RtlSecureMemoryCacheCallback) {
  40. RtlSecureMemoryCacheCallback = Callback;
  41. return STATUS_SUCCESS;
  42. } else {
  43. return STATUS_NO_MORE_ENTRIES;
  44. }
  45. }
  46. BOOLEAN
  47. RtlFlushSecureMemoryCache(
  48. IN PVOID lpAddr,
  49. IN SIZE_T size
  50. )
  51. /*++
  52. Routine Description:
  53. This routine is called from various Win32 and Heap APIs whenever memory is freed
  54. or its protections are changed. We call the callback routine that has been registered.
  55. Its possible that size is 0 which means that this routine has to figure out the region
  56. size. The NtQueryVirtualMemory API is used for this. Unfortunately this API does not
  57. provide us the right boundary of the region. So we loop until the state changes to MEM_FREE.
  58. This will guarantee that a region boundary has been found. This implies that we might unlock
  59. more pages than we have to.
  60. Arguments:
  61. lpAddr - Pointer to the address thats getting freed or its protections changed.
  62. size - Size of the address range. Can be zero.
  63. Return Value:
  64. Returns TRUE if the callback was successful.
  65. --*/
  66. {
  67. ULONG_PTR addr;
  68. SIZE_T regionSize;
  69. ULONG regType;
  70. ULONG regState;
  71. MEMORY_BASIC_INFORMATION memInfo;
  72. NTSTATUS status;
  73. PRTL_SECURE_MEMORY_CACHE_CALLBACK Callback;
  74. Callback = RtlSecureMemoryCacheCallback;
  75. if (Callback) {
  76. if (!size) {
  77. //
  78. // Compute the real size of the region
  79. //
  80. addr = (ULONG_PTR)lpAddr;
  81. status = NtQueryVirtualMemory( NtCurrentProcess(),
  82. (PVOID)addr,
  83. MemoryBasicInformation,
  84. (PMEMORY_BASIC_INFORMATION)&memInfo,
  85. sizeof(memInfo),
  86. NULL
  87. );
  88. if (!NT_SUCCESS(status)) {
  89. return FALSE;
  90. }
  91. if (memInfo.State == MEM_FREE) {
  92. return FALSE;
  93. }
  94. while (1) {
  95. size += memInfo.RegionSize;
  96. regState = memInfo.State;
  97. addr = addr + memInfo.RegionSize;
  98. if (addr > RtlSecureMemorySystemRangeStart) {
  99. break;
  100. }
  101. status = NtQueryVirtualMemory( NtCurrentProcess(),
  102. (PVOID)addr,
  103. MemoryBasicInformation,
  104. (PMEMORY_BASIC_INFORMATION)&memInfo,
  105. sizeof(memInfo),
  106. NULL
  107. );
  108. if (!NT_SUCCESS(status)) {
  109. return FALSE;
  110. }
  111. if (memInfo.State == MEM_FREE) {
  112. break;
  113. }
  114. }
  115. }
  116. status = Callback(lpAddr, size);
  117. return (NT_SUCCESS(status));
  118. }
  119. return FALSE;
  120. }
  121. NTSTATUS
  122. RtlpSecMemFreeVirtualMemory(
  123. IN HANDLE ProcessHandle,
  124. IN OUT PVOID *BaseAddress,
  125. IN OUT PSIZE_T RegionSize,
  126. IN ULONG FreeType
  127. )
  128. /*++
  129. Routine Description:
  130. This routine is called from the HEAP APIs to free virtual memory. In addition to calling
  131. NtFreeVirtualMemory it tries to flush the secure memory cache.
  132. Arguments:
  133. The arguments are identical to NtFreeVirtualMemory.
  134. Return Value:
  135. Returns TRUE if the callback was successful.
  136. --*/
  137. {
  138. NTSTATUS status;
  139. status = NtFreeVirtualMemory( ProcessHandle,
  140. BaseAddress,
  141. RegionSize,
  142. FreeType
  143. );
  144. if (status == STATUS_INVALID_PAGE_PROTECTION) {
  145. if ((ProcessHandle == NtCurrentProcess()) && RtlFlushSecureMemoryCache(*BaseAddress, *RegionSize)) {
  146. status = NtFreeVirtualMemory( ProcessHandle,
  147. BaseAddress,
  148. RegionSize,
  149. FreeType
  150. );
  151. return status;
  152. }
  153. }
  154. return status;
  155. }