CHAR LogBuffer[ANYSIZE_ARRAY];
} KMT_RESULTBUFFER, *PKMT_RESULTBUFFER;
+#ifndef KMT_STANDALONE_DRIVER
+
+/* usermode call-back mechanism */
+
+/* list of supported operations */
+typedef enum _KMT_CALLBACK_INFORMATION_CLASS
+{
+ QueryVirtualMemory
+} KMT_CALLBACK_INFORMATION_CLASS, *PKMT_CALLBACK_INFORMATION_CLASS;
+
+/* TODO: "response" is a little generic */
+typedef union _KMT_RESPONSE
+{
+ MEMORY_BASIC_INFORMATION MemInfo;
+} KMT_RESPONSE, *PKMT_RESPONSE;
+
+/* this struct is sent from driver to usermode */
+typedef struct _KMT_CALLBACK_REQUEST_PACKET
+{
+ ULONG RequestId;
+ KMT_CALLBACK_INFORMATION_CLASS OperationClass;
+ PVOID Parameters;
+} KMT_CALLBACK_REQUEST_PACKET, *PKMT_CALLBACK_REQUEST_PACKET;
+
+PKMT_RESPONSE KmtUserModeCallback(KMT_CALLBACK_INFORMATION_CLASS Operation, PVOID Parameters);
+VOID KmtFreeCallbackResponse(PKMT_RESPONSE Response);
+
+//macro to simplify using the mechanism
+#define Test_NtQueryVirtualMemory(BaseAddress, Size, AllocationType, ProtectionType) \
+ do { \
+ PKMT_RESPONSE NtQueryTest = KmtUserModeCallback(QueryVirtualMemory, BaseAddress); \
+ if (NtQueryTest != NULL) \
+ { \
+ ok_eq_hex(NtQueryTest->MemInfo.Protect, ProtectionType); \
+ ok_eq_hex(NtQueryTest->MemInfo.State, AllocationType); \
+ ok_eq_size(NtQueryTest->MemInfo.RegionSize, Size); \
+ KmtFreeCallbackResponse(NtQueryTest); \
+ } \
+ } while (0) \
+
+#endif
+
#ifdef KMT_STANDALONE_DRIVER
#define KMT_KERNEL_MODE
TESTENTRY_NO_CREATE_DEVICE = 1,
TESTENTRY_NO_REGISTER_DISPATCH = 2,
TESTENTRY_NO_REGISTER_UNLOAD = 4,
+ TESTENTRY_NO_EXCLUSIVE_DEVICE = 8,
} KMT_TESTENTRY_FLAGS;
NTSTATUS TestEntry(IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING RegistryPath, OUT PCWSTR *DeviceName, IN OUT INT *Flags);
VOID KmtSetIrql(IN KIRQL NewIrql);
BOOLEAN KmtAreInterruptsEnabled(VOID);
+ULONG KmtGetPoolTag(PVOID Memory);
#elif defined KMT_USER_MODE
DWORD KmtRunKernelTest(IN PCSTR TestName);
DWORD KmtSendToDriver(IN DWORD ControlCode);
DWORD KmtSendStringToDriver(IN DWORD ControlCode, IN PCSTR String);
+DWORD KmtSendWStringToDriver(IN DWORD ControlCode, IN PCWSTR String);
DWORD KmtSendBufferToDriver(IN DWORD ControlCode, IN OUT PVOID Buffer OPTIONAL, IN DWORD InLength, IN OUT PDWORD OutLength);
#else /* if !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
#error either KMT_KERNEL_MODE or KMT_USER_MODE must be defined
#define trace_(file, line, ...) KmtTrace( file ":" KMT_STRINGIZE(line), __VA_ARGS__)
#define skip_(test, file, line, ...) KmtSkip(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
-VOID KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
-VOID KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
+BOOLEAN KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
+BOOLEAN KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 2, 0);
VOID KmtTrace(PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 2, 3);
BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
(expected) ? "TRUE" : "FALSE")
#define ok_eq_str(value, expected) ok(!strcmp(value, expected), #value " = \"%s\", expected \"%s\"\n", value, expected)
#define ok_eq_wstr(value, expected) ok(!wcscmp(value, expected), #value " = \"%ls\", expected \"%ls\"\n", value, expected)
+#define ok_eq_tag(value, expected) ok_eq_print(value, expected, "0x%08lx")
#define KMT_MAKE_CODE(ControlCode) CTL_CODE(FILE_DEVICE_UNKNOWN, \
0xC00 + (ControlCode), \
#define MILLISECOND (1000 * MICROSECOND)
#define SECOND (1000 * MILLISECOND)
+#define KmtInvalidPointer ((PVOID)0x5555555555555555ULL)
+
+#define KmtStartSeh() \
+ ExceptionStatus = STATUS_SUCCESS; \
+ _SEH2_TRY \
+ {
+#define KmtEndSeh(ExpectedStatus) \
+ } \
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
+ { \
+ ExceptionStatus = _SEH2_GetExceptionCode(); \
+ } _SEH2_END; \
+ ok_eq_hex(ExceptionStatus, ExpectedStatus)
+
#if defined KMT_DEFINE_TEST_FUNCTIONS
#if defined KMT_KERNEL_MODE
return (__readeflags() & (1 << 9)) != 0;
}
+typedef struct _POOL_HEADER
+{
+ union
+ {
+ struct
+ {
+#ifdef _M_AMD64
+ USHORT PreviousSize:8;
+ USHORT PoolIndex:8;
+ USHORT BlockSize:8;
+ USHORT PoolType:8;
+#else
+ USHORT PreviousSize:9;
+ USHORT PoolIndex:7;
+ USHORT BlockSize:9;
+ USHORT PoolType:7;
+#endif
+ };
+ ULONG Ulong1;
+ };
+#ifdef _M_AMD64
+ ULONG PoolTag;
+#endif
+ union
+ {
+#ifdef _M_AMD64
+ PEPROCESS ProcessBilled;
+#else
+ ULONG PoolTag;
+#endif
+ struct
+ {
+ USHORT AllocatorBackTraceIndex;
+ USHORT PoolTagHash;
+ };
+ };
+} POOL_HEADER, *PPOOL_HEADER;
+
+ULONG KmtGetPoolTag(PVOID Memory)
+{
+ PPOOL_HEADER Header;
+
+ /* it's not so easy for allocations of PAGE_SIZE */
+ if (((ULONG_PTR)Memory & (PAGE_SIZE - 1)) == 0)
+ return 'TooL';
+
+ Header = Memory;
+ Header--;
+
+ return Header->PoolTag;
+}
+
INT __cdecl KmtVSNPrintF(PSTR Buffer, SIZE_T BufferMaxLength, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
#elif defined KMT_USER_MODE
static PKMT_RESULTBUFFER KmtAllocateResultBuffer(SIZE_T ResultBufferSize)
Buffer->Failures = 0;
Buffer->Skipped = 0;
Buffer->LogBufferLength = 0;
- Buffer->LogBufferMaxLength = ResultBufferSize - FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer);
+ Buffer->LogBufferMaxLength = (ULONG)ResultBufferSize - FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer);
return Buffer;
}
do
{
OldLength = Buffer->LogBufferLength;
- NewLength = OldLength + Length;
+ NewLength = OldLength + (ULONG)Length;
if (NewLength > Buffer->LogBufferMaxLength)
return;
} while (InterlockedCompareExchange(&Buffer->LogBufferLength, NewLength, OldLength) != OldLength);
KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
}
-VOID KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
+BOOLEAN KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
{
CHAR MessageBuffer[512];
SIZE_T MessageLength;
if (!ResultBuffer)
- return;
+ return Condition != 0;
if (Condition)
{
MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Test failed: ", Format, Arguments);
KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
}
+
+ return Condition != 0;
}
-VOID KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
+BOOLEAN KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
{
+ BOOLEAN Ret;
va_list Arguments;
va_start(Arguments, Format);
- KmtVOk(Condition, FileAndLine, Format, Arguments);
+ Ret = KmtVOk(Condition, FileAndLine, Format, Arguments);
va_end(Arguments);
+ return Ret;
}
VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments)