* PROJECT: ReactOS kernel-mode tests
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: Kernel-Mode Test Suite test framework declarations
- * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
+ * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
*/
/* Inspired by Wine C unit tests, Copyright (C) 2002 Alexandre Julliard
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);
+USHORT KmtGetPoolType(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);
#define ok_eq_ulong(value, expected) ok_eq_print(value, expected, "%lu")
#define ok_eq_longlong(value, expected) ok_eq_print(value, expected, "%I64d")
#define ok_eq_ulonglong(value, expected) ok_eq_print(value, expected, "%I64u")
+#define ok_eq_char(value, expected) ok_eq_print(value, expected, "%c")
+#define ok_eq_wchar(value, expected) ok_eq_print(value, expected, "%C")
#ifndef _WIN64
#define ok_eq_size(value, expected) ok_eq_print(value, (SIZE_T)(expected), "%lu")
#define ok_eq_longptr(value, expected) ok_eq_print(value, (LONG_PTR)(expected), "%ld")
(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)
+/* See apitests/include/apitest.h */
+#define KmtInvalidPointer ((PVOID)0x5555555555555555ULL)
+
+#define KmtStartSeh() \
+{ \
+ NTSTATUS 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;
+}
+
+USHORT KmtGetPoolType(PVOID Memory)
+{
+ PPOOL_HEADER Header;
+
+ /* it's not so easy for allocations of PAGE_SIZE */
+ if (((ULONG_PTR)Memory & (PAGE_SIZE - 1)) == 0)
+ return 0;
+
+ Header = Memory;
+ Header--;
+
+ return Header->PoolType;
+}
+
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)
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)