[KMTESTS]
[reactos.git] / rostests / kmtests / include / kmt_test.h
index b1ac21e..b00962a 100644 (file)
@@ -38,6 +38,48 @@ typedef struct
     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
 
@@ -66,6 +108,7 @@ typedef enum
     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);
@@ -87,6 +130,7 @@ extern PDRIVER_OBJECT KmtDriverObject;
 
 VOID KmtSetIrql(IN KIRQL NewIrql);
 BOOLEAN KmtAreInterruptsEnabled(VOID);
+ULONG KmtGetPoolTag(PVOID Memory);
 #elif defined KMT_USER_MODE
 DWORD KmtRunKernelTest(IN PCSTR TestName);
 
@@ -97,6 +141,7 @@ VOID KmtCloseDriver(VOID);
 
 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
@@ -124,8 +169,8 @@ extern PKMT_RESULTBUFFER ResultBuffer;
 #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);
@@ -161,6 +206,7 @@ VOID KmtFreeGuarded(PVOID Pointer);
                                                 (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),         \
@@ -171,6 +217,20 @@ VOID KmtFreeGuarded(PVOID Pointer);
 #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
@@ -222,6 +282,58 @@ BOOLEAN KmtAreInterruptsEnabled(VOID)
     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)
@@ -234,7 +346,7 @@ 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;
 }
@@ -260,7 +372,7 @@ static VOID KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer, PCSTR String, SIZE_T Len
     do
     {
         OldLength = Buffer->LogBufferLength;
-        NewLength = OldLength + Length;
+        NewLength = OldLength + (ULONG)Length;
         if (NewLength > Buffer->LogBufferMaxLength)
             return;
     } while (InterlockedCompareExchange(&Buffer->LogBufferLength, NewLength, OldLength) != OldLength);
@@ -335,13 +447,13 @@ VOID KmtFinishTest(PCSTR TestName)
     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)
     {
@@ -359,14 +471,18 @@ VOID KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
         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)