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.
 
 
 
 
 
 

204 lines
5.5 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
secmem.c
Abstract:
This module implements a user level callback for securing memory for SAN IOs.
Author:
Nar Ganapathy (narg) 8-Feb-2000
Revision History:
--*/
#include "ntrtlp.h"
ULONG_PTR RtlSecureMemorySystemRangeStart;
PRTL_SECURE_MEMORY_CACHE_CALLBACK RtlSecureMemoryCacheCallback = NULL;
NTSTATUS
RtlRegisterSecureMemoryCacheCallback(
IN PRTL_SECURE_MEMORY_CACHE_CALLBACK Callback
)
/*++
Routine Description:
This routine allows a library to register to be called back whenever
memory is freed or its protections are changed. This is useful for
maintaining user level secure memory cache for SAN applications.
Current customer is winsock DP.
Arguments:
CallBack - Supplies a pointer to the callback routine
Return Value:
NTSTATUS code. Returns STATUS_SUCCESS if we could sucessfully register
the callback.
--*/
{
NTSTATUS status;
status = NtQuerySystemInformation(SystemRangeStartInformation,
&RtlSecureMemorySystemRangeStart,
sizeof(RtlSecureMemorySystemRangeStart),
NULL);
if (!NT_SUCCESS(status)) {
return status;
}
if (!RtlSecureMemoryCacheCallback) {
RtlSecureMemoryCacheCallback = Callback;
return STATUS_SUCCESS;
} else {
return STATUS_NO_MORE_ENTRIES;
}
}
BOOLEAN
RtlFlushSecureMemoryCache(
IN PVOID lpAddr,
IN SIZE_T size
)
/*++
Routine Description:
This routine is called from various Win32 and Heap APIs whenever memory is freed
or its protections are changed. We call the callback routine that has been registered.
Its possible that size is 0 which means that this routine has to figure out the region
size. The NtQueryVirtualMemory API is used for this. Unfortunately this API does not
provide us the right boundary of the region. So we loop until the state changes to MEM_FREE.
This will guarantee that a region boundary has been found. This implies that we might unlock
more pages than we have to.
Arguments:
lpAddr - Pointer to the address thats getting freed or its protections changed.
size - Size of the address range. Can be zero.
Return Value:
Returns TRUE if the callback was successful.
--*/
{
ULONG_PTR addr;
SIZE_T regionSize;
ULONG regType;
ULONG regState;
MEMORY_BASIC_INFORMATION memInfo;
NTSTATUS status;
PRTL_SECURE_MEMORY_CACHE_CALLBACK Callback;
Callback = RtlSecureMemoryCacheCallback;
if (Callback) {
if (!size) {
//
// Compute the real size of the region
//
addr = (ULONG_PTR)lpAddr;
status = NtQueryVirtualMemory( NtCurrentProcess(),
(PVOID)addr,
MemoryBasicInformation,
(PMEMORY_BASIC_INFORMATION)&memInfo,
sizeof(memInfo),
NULL
);
if (!NT_SUCCESS(status)) {
return FALSE;
}
if (memInfo.State == MEM_FREE) {
return FALSE;
}
while (1) {
size += memInfo.RegionSize;
regState = memInfo.State;
addr = addr + memInfo.RegionSize;
if (addr > RtlSecureMemorySystemRangeStart) {
break;
}
status = NtQueryVirtualMemory( NtCurrentProcess(),
(PVOID)addr,
MemoryBasicInformation,
(PMEMORY_BASIC_INFORMATION)&memInfo,
sizeof(memInfo),
NULL
);
if (!NT_SUCCESS(status)) {
return FALSE;
}
if (memInfo.State == MEM_FREE) {
break;
}
}
}
status = Callback(lpAddr, size);
return (NT_SUCCESS(status));
}
return FALSE;
}
NTSTATUS
RtlpSecMemFreeVirtualMemory(
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN OUT PSIZE_T RegionSize,
IN ULONG FreeType
)
/*++
Routine Description:
This routine is called from the HEAP APIs to free virtual memory. In addition to calling
NtFreeVirtualMemory it tries to flush the secure memory cache.
Arguments:
The arguments are identical to NtFreeVirtualMemory.
Return Value:
Returns TRUE if the callback was successful.
--*/
{
NTSTATUS status;
status = NtFreeVirtualMemory( ProcessHandle,
BaseAddress,
RegionSize,
FreeType
);
if (status == STATUS_INVALID_PAGE_PROTECTION) {
if ((ProcessHandle == NtCurrentProcess()) && RtlFlushSecureMemoryCache(*BaseAddress, *RegionSize)) {
status = NtFreeVirtualMemory( ProcessHandle,
BaseAddress,
RegionSize,
FreeType
);
return status;
}
}
return status;
}