TestCleanEverything();
- ok(ExGetPreviousMode() == UserMode, "Not comming from umode!\n");
+ ok(ExGetPreviousMode() == UserMode, "Not coming from umode!\n");
if (!skip(Buffer && InLength >= sizeof(QUERY_BUFFER) && *OutLength >= sizeof(QUERY_BUFFER), "Cannot read/write from/to buffer!\n"))
{
PQUERY_BUFFER QueryBuffer;
SehStatus = STATUS_SUCCESS;
_SEH2_TRY
{
- CurrentUser = MmMapLockedPagesSpecifyCache(CurrentMdl, UserMode, CacheType, NULL, FALSE, NormalPagePriority);
+ CurrentUser = MmMapLockedPagesSpecifyCache(CurrentMdl, UserMode, CacheType, QueryBuffer->Buffer, FALSE, NormalPagePriority);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SehStatus = _SEH2_GetExceptionCode();
}
_SEH2_END;
- ok_eq_hex(SehStatus, STATUS_SUCCESS);
- ok(CurrentUser != NULL, "MmMapLockedPagesSpecifyCache failed!\n");
+ if (QueryBuffer->Status != -1)
+ {
+ ok_eq_hex(SehStatus, QueryBuffer->Status);
+ if (NT_SUCCESS(QueryBuffer->Status))
+ {
+ ok(CurrentUser != NULL, "MmMapLockedPagesSpecifyCache failed!\n");
+ }
+ else
+ {
+ ok(CurrentUser == NULL, "MmMapLockedPagesSpecifyCache succeeded!\n");
+ }
+ }
+ QueryBuffer->Status = SehStatus;
}
else
{
ok_eq_size(*OutLength, 0);
ok(CurrentMdl != NULL, "MDL is not in use!\n");
- if (!skip(Buffer && InLength >= sizeof(QUERY_BUFFER), "Cannot read from buffer!\n"))
+ if (!skip(Buffer && InLength >= sizeof(READ_BUFFER), "Cannot read from buffer!\n"))
{
PREAD_BUFFER ReadBuffer;
break;
}
+ case IOCTL_CLEAN:
+ {
+ TestCleanEverything();
+ break;
+ }
default:
ok(0, "Got an unknown message! DeviceObject=%p, ControlCode=%lu, Buffer=%p, In=%lu, Out=%lu bytes\n",
DeviceObject, ControlCode, Buffer, InLength, *OutLength);
*/
#include <kmt_test.h>
+#include <ndk/exfuncs.h>
#include "MmMapLockedPagesSpecifyCache.h"
+#define ALIGN_DOWN_BY(size, align) \
+ ((ULONG_PTR)(size) & ~((ULONG_PTR)(align) - 1))
+
#define SET_BUFFER_LENGTH(Var, Length) \
{ \
C_ASSERT(((Length) % sizeof(ULONG)) == 0); \
QueryBuffer.Length = BufferLength; \
QueryBuffer.Buffer = NULL; \
QueryBuffer.Cached = UseCache; \
+ QueryBuffer.Status = STATUS_SUCCESS; \
}
#define FILL_READ_BUFFER(QueryBuffer, ReadBuffer) \
DWORD Length;
USHORT i;
USHORT BufferLength;
+ SYSTEM_BASIC_INFORMATION BasicInfo;
+ NTSTATUS Status;
+ ULONG_PTR HighestAddress;
KmtLoadDriver(L"MmMapLockedPagesSpecifyCache", FALSE);
KmtOpenDriver();
// more than 2 pages
SET_BUFFER_LENGTH(BufferLength, 2 * 4096 + 2048);
- QueryBuffer.Length = BufferLength;
- QueryBuffer.Buffer = NULL;
- QueryBuffer.Cached = FALSE;
+ FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE);
Length = sizeof(QUERY_BUFFER);
ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n");
ok_eq_int(QueryBuffer.Length, BufferLength);
FILL_READ_BUFFER(QueryBuffer, ReadBuffer);
ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n");
- QueryBuffer.Length = BufferLength;
- QueryBuffer.Buffer = NULL;
- QueryBuffer.Cached = TRUE;
+ FILL_QUERY_BUFFER(QueryBuffer, BufferLength, TRUE);
Length = sizeof(QUERY_BUFFER);
ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n");
ok_eq_int(QueryBuffer.Length, BufferLength);
FILL_READ_BUFFER(QueryBuffer, ReadBuffer);
ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+ // ask for a specific address (we know that ReadBuffer.Buffer is free)
+ SET_BUFFER_LENGTH(BufferLength, 4096);
+ FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE);
+ QueryBuffer.Buffer = ReadBuffer.Buffer;
+ Length = sizeof(QUERY_BUFFER);
+ ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+ ok_eq_int(QueryBuffer.Length, BufferLength);
+ ok(QueryBuffer.Buffer == ReadBuffer.Buffer, "Buffer is NULL\n");
+ CHECK_ALLOC(QueryBuffer.Buffer, BufferLength);
+
+ Length = 0;
+ FILL_READ_BUFFER(QueryBuffer, ReadBuffer);
+ ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+
+ // ask for an unaligned address
+ SET_BUFFER_LENGTH(BufferLength, 4096);
+ FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE);
+ QueryBuffer.Buffer = (PVOID)((ULONG_PTR)ReadBuffer.Buffer + 2048);
+ QueryBuffer.Status = STATUS_INVALID_ADDRESS;
+ Length = sizeof(QUERY_BUFFER);
+ ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+ ok_eq_int(QueryBuffer.Length, BufferLength);
+ ok(QueryBuffer.Buffer == NULL, "Buffer is %p\n", QueryBuffer.Buffer);
+
+ Length = 0;
+ ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n");
+
+ // get system info for MmHighestUserAddress
+ Status = NtQuerySystemInformation(SystemBasicInformation,
+ &BasicInfo,
+ sizeof(BasicInfo),
+ NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ trace("MaximumUserModeAddress: %lx\n", BasicInfo.MaximumUserModeAddress);
+ HighestAddress = ALIGN_DOWN_BY(BasicInfo.MaximumUserModeAddress, PAGE_SIZE);
+
+ // near MmHighestUserAddress
+ SET_BUFFER_LENGTH(BufferLength, 4096);
+ FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE);
+ QueryBuffer.Buffer = (PVOID)(HighestAddress - 15 * PAGE_SIZE); // 7ffe0000
+ QueryBuffer.Status = STATUS_INVALID_ADDRESS;
+ trace("QueryBuffer.Buffer %p\n", QueryBuffer.Buffer);
+ Length = sizeof(QUERY_BUFFER);
+ ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+ ok_eq_int(QueryBuffer.Length, BufferLength);
+ ok(QueryBuffer.Buffer == NULL, "Buffer is %p\n", QueryBuffer.Buffer);
+
+ Length = 0;
+ ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n");
+
+ // far enough away from MmHighestUserAddress
+ SET_BUFFER_LENGTH(BufferLength, 4096);
+ FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE);
+ QueryBuffer.Buffer = (PVOID)(HighestAddress - 16 * PAGE_SIZE); // 7ffdf000
+ QueryBuffer.Status = -1;
+ trace("QueryBuffer.Buffer %p\n", QueryBuffer.Buffer);
+ Length = sizeof(QUERY_BUFFER);
+ ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n");
+ ok_eq_int(QueryBuffer.Length, BufferLength);
+ ok(QueryBuffer.Status == STATUS_SUCCESS ||
+ QueryBuffer.Status == STATUS_CONFLICTING_ADDRESSES, "Status = %lx\n", QueryBuffer.Status);
+
+ Length = 0;
+ ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n");
+
KmtCloseDriver();
KmtUnloadDriver();
}