1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS kernel-mode tests
3a9ba7a3fSThomas Faber * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4c2c66affSColin Finck * PURPOSE: Kernel-Mode Test Suite test framework declarations
5a9ba7a3fSThomas Faber * COPYRIGHT: Copyright 2011-2018 Thomas Faber <thomas.faber@reactos.org>
6a9ba7a3fSThomas Faber * Copyright 2013 Nikolay Borisov <nib9@aber.ac.uk>
7a9ba7a3fSThomas Faber * Copyright 2014-2016 Pierre Schweitzer <pierre@reactos.org>
8a9ba7a3fSThomas Faber * Copyright 2017 Ged Murphy <gedmurphy@reactos.org>
9c2c66affSColin Finck */
10c2c66affSColin Finck
11c2c66affSColin Finck /* Inspired by Wine C unit tests, Copyright (C) 2002 Alexandre Julliard
12c2c66affSColin Finck * Inspired by ReactOS kernel-mode regression tests,
13c2c66affSColin Finck * Copyright (C) Aleksey Bragin, Filip Navara
14c2c66affSColin Finck */
15c2c66affSColin Finck
16c2c66affSColin Finck #ifndef _KMTEST_TEST_H_
17c2c66affSColin Finck #define _KMTEST_TEST_H_
18c2c66affSColin Finck
19c2c66affSColin Finck #include <kmt_platform.h>
20c2c66affSColin Finck
21c2c66affSColin Finck typedef VOID KMT_TESTFUNC(VOID);
22c2c66affSColin Finck typedef KMT_TESTFUNC *PKMT_TESTFUNC;
23c2c66affSColin Finck
24c2c66affSColin Finck typedef struct
25c2c66affSColin Finck {
26c2c66affSColin Finck const char *TestName;
27c2c66affSColin Finck KMT_TESTFUNC *TestFunction;
28c2c66affSColin Finck } KMT_TEST, *PKMT_TEST;
29c2c66affSColin Finck
30c2c66affSColin Finck typedef const KMT_TEST CKMT_TEST, *PCKMT_TEST;
31c2c66affSColin Finck
32c2c66affSColin Finck extern const KMT_TEST TestList[];
33c2c66affSColin Finck
34c2c66affSColin Finck typedef struct
35c2c66affSColin Finck {
36c2c66affSColin Finck volatile LONG Successes;
37c2c66affSColin Finck volatile LONG Failures;
38c2c66affSColin Finck volatile LONG Skipped;
39c2c66affSColin Finck volatile LONG LogBufferLength;
40c2c66affSColin Finck LONG LogBufferMaxLength;
41c2c66affSColin Finck CHAR LogBuffer[ANYSIZE_ARRAY];
42c2c66affSColin Finck } KMT_RESULTBUFFER, *PKMT_RESULTBUFFER;
43c2c66affSColin Finck
44c2c66affSColin Finck #ifndef KMT_STANDALONE_DRIVER
45c2c66affSColin Finck
46c2c66affSColin Finck /* usermode call-back mechanism */
47c2c66affSColin Finck
48c2c66affSColin Finck /* list of supported operations */
49c2c66affSColin Finck typedef enum _KMT_CALLBACK_INFORMATION_CLASS
50c2c66affSColin Finck {
51c2c66affSColin Finck QueryVirtualMemory
52c2c66affSColin Finck } KMT_CALLBACK_INFORMATION_CLASS, *PKMT_CALLBACK_INFORMATION_CLASS;
53c2c66affSColin Finck
54c2c66affSColin Finck /* TODO: "response" is a little generic */
55c2c66affSColin Finck typedef union _KMT_RESPONSE
56c2c66affSColin Finck {
57c2c66affSColin Finck MEMORY_BASIC_INFORMATION MemInfo;
58c2c66affSColin Finck } KMT_RESPONSE, *PKMT_RESPONSE;
59c2c66affSColin Finck
60c2c66affSColin Finck /* this struct is sent from driver to usermode */
61c2c66affSColin Finck typedef struct _KMT_CALLBACK_REQUEST_PACKET
62c2c66affSColin Finck {
63c2c66affSColin Finck ULONG RequestId;
64c2c66affSColin Finck KMT_CALLBACK_INFORMATION_CLASS OperationClass;
65c2c66affSColin Finck PVOID Parameters;
66c2c66affSColin Finck } KMT_CALLBACK_REQUEST_PACKET, *PKMT_CALLBACK_REQUEST_PACKET;
67c2c66affSColin Finck
68c2c66affSColin Finck PKMT_RESPONSE KmtUserModeCallback(KMT_CALLBACK_INFORMATION_CLASS Operation, PVOID Parameters);
69c2c66affSColin Finck VOID KmtFreeCallbackResponse(PKMT_RESPONSE Response);
70c2c66affSColin Finck
71c2c66affSColin Finck //macro to simplify using the mechanism
72c2c66affSColin Finck #define Test_NtQueryVirtualMemory(BaseAddress, Size, AllocationType, ProtectionType) \
73c2c66affSColin Finck do { \
74c2c66affSColin Finck PKMT_RESPONSE NtQueryTest = KmtUserModeCallback(QueryVirtualMemory, BaseAddress); \
75c2c66affSColin Finck if (NtQueryTest != NULL) \
76c2c66affSColin Finck { \
77c2c66affSColin Finck ok_eq_hex(NtQueryTest->MemInfo.Protect, ProtectionType); \
78c2c66affSColin Finck ok_eq_hex(NtQueryTest->MemInfo.State, AllocationType); \
79c2c66affSColin Finck ok_eq_size(NtQueryTest->MemInfo.RegionSize, Size); \
80c2c66affSColin Finck KmtFreeCallbackResponse(NtQueryTest); \
81c2c66affSColin Finck } \
82c2c66affSColin Finck } while (0) \
83c2c66affSColin Finck
84c2c66affSColin Finck #endif
85c2c66affSColin Finck
86c2c66affSColin Finck #ifdef KMT_STANDALONE_DRIVER
87c2c66affSColin Finck #define KMT_KERNEL_MODE
88c2c66affSColin Finck
89c2c66affSColin Finck typedef NTSTATUS (KMT_IRP_HANDLER)(
90c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
91c2c66affSColin Finck IN PIRP Irp,
92c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation);
93c2c66affSColin Finck typedef KMT_IRP_HANDLER *PKMT_IRP_HANDLER;
94c2c66affSColin Finck
95c2c66affSColin Finck NTSTATUS KmtRegisterIrpHandler(IN UCHAR MajorFunction, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_IRP_HANDLER IrpHandler);
96c2c66affSColin Finck NTSTATUS KmtUnregisterIrpHandler(IN UCHAR MajorFunction, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_IRP_HANDLER IrpHandler);
97c2c66affSColin Finck
98c2c66affSColin Finck typedef NTSTATUS (KMT_MESSAGE_HANDLER)(
99c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
100c2c66affSColin Finck IN ULONG ControlCode,
101c2c66affSColin Finck IN PVOID Buffer OPTIONAL,
102c2c66affSColin Finck IN SIZE_T InLength,
103c2c66affSColin Finck IN OUT PSIZE_T OutLength);
104c2c66affSColin Finck typedef KMT_MESSAGE_HANDLER *PKMT_MESSAGE_HANDLER;
105c2c66affSColin Finck
106c2c66affSColin Finck NTSTATUS KmtRegisterMessageHandler(IN ULONG ControlCode OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_MESSAGE_HANDLER MessageHandler);
107c2c66affSColin Finck NTSTATUS KmtUnregisterMessageHandler(IN ULONG ControlCode OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_MESSAGE_HANDLER MessageHandler);
108c2c66affSColin Finck
109c2c66affSColin Finck typedef enum
110c2c66affSColin Finck {
111c2c66affSColin Finck TESTENTRY_NO_CREATE_DEVICE = 1,
112c2c66affSColin Finck TESTENTRY_NO_REGISTER_DISPATCH = 2,
113c2c66affSColin Finck TESTENTRY_NO_REGISTER_UNLOAD = 4,
114c2c66affSColin Finck TESTENTRY_NO_EXCLUSIVE_DEVICE = 8,
115c2c66affSColin Finck TESTENTRY_NO_READONLY_DEVICE = 16,
116c2c66affSColin Finck TESTENTRY_BUFFERED_IO_DEVICE = 32,
117c2c66affSColin Finck } KMT_TESTENTRY_FLAGS;
118c2c66affSColin Finck
119c2c66affSColin Finck NTSTATUS TestEntry(IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING RegistryPath, OUT PCWSTR *DeviceName, IN OUT INT *Flags);
120c2c66affSColin Finck VOID TestUnload(IN PDRIVER_OBJECT DriverObject);
121c2c66affSColin Finck #endif /* defined KMT_STANDALONE_DRIVER */
122c2c66affSColin Finck
1239d15fb92SGed Murphy #ifdef KMT_FILTER_DRIVER
1249d15fb92SGed Murphy #ifndef KMT_KERNEL_MODE
1259d15fb92SGed Murphy #define KMT_KERNEL_MODE
1269d15fb92SGed Murphy #endif
1279d15fb92SGed Murphy
1289d15fb92SGed Murphy NTSTATUS KmtFilterRegisterCallbacks(_In_ CONST FLT_OPERATION_REGISTRATION *OperationRegistration);
1299d15fb92SGed Murphy
1309d15fb92SGed Murphy typedef enum
1319d15fb92SGed Murphy {
132dfb77638SGed Murphy TESTENTRY_NO_REGISTER_FILTER = 0x01,
133dfb77638SGed Murphy TESTENTRY_NO_CREATE_COMMS_PORT = 0x02,
134dfb77638SGed Murphy TESTENTRY_NO_START_FILTERING = 0x04,
135dfb77638SGed Murphy TESTENTRY_NO_INSTANCE_SETUP = 0x08,
136dfb77638SGed Murphy TESTENTRY_NO_QUERY_TEARDOWN = 0x10,
137dfb77638SGed Murphy TESTENTRY_NO_ALL = 0xFF
1389d15fb92SGed Murphy } KMT_MINIFILTER_FLAGS;
1399d15fb92SGed Murphy
1409d15fb92SGed Murphy VOID TestFilterUnload(_In_ ULONG Flags);
1419d15fb92SGed Murphy NTSTATUS TestInstanceSetup(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_SETUP_FLAGS Flags, _In_ DEVICE_TYPE VolumeDeviceType, _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType, _In_ PUNICODE_STRING VolumeName, _In_ ULONG RealSectorSize, _In_ ULONG SectorSize);
1429d15fb92SGed Murphy VOID TestQueryTeardown(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags);
1439d15fb92SGed Murphy
1449d15fb92SGed Murphy NTSTATUS KmtFilterRegisterComms(_In_ PFLT_CONNECT_NOTIFY ConnectNotifyCallback, _In_ PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback, _In_opt_ PFLT_MESSAGE_NOTIFY MessageNotifyCallback, _In_ LONG MaxClientConnections);
1459d15fb92SGed Murphy
1469d15fb92SGed Murphy #endif/* defined KMT_FILTER_DRIVER */
1479d15fb92SGed Murphy
1489d15fb92SGed Murphy
149c2c66affSColin Finck #ifdef KMT_KERNEL_MODE
150c2c66affSColin Finck /* Device Extension layout */
151c2c66affSColin Finck typedef struct
152c2c66affSColin Finck {
153c2c66affSColin Finck PKMT_RESULTBUFFER ResultBuffer;
154c2c66affSColin Finck PMDL Mdl;
155c2c66affSColin Finck } KMT_DEVICE_EXTENSION, *PKMT_DEVICE_EXTENSION;
156c2c66affSColin Finck
157c2c66affSColin Finck extern BOOLEAN KmtIsCheckedBuild;
158c2c66affSColin Finck extern BOOLEAN KmtIsMultiProcessorBuild;
159c2c66affSColin Finck extern PCSTR KmtMajorFunctionNames[];
160c2c66affSColin Finck extern PDRIVER_OBJECT KmtDriverObject;
161c2c66affSColin Finck
162c2c66affSColin Finck VOID KmtSetIrql(IN KIRQL NewIrql);
163c2c66affSColin Finck BOOLEAN KmtAreInterruptsEnabled(VOID);
164c2c66affSColin Finck ULONG KmtGetPoolTag(PVOID Memory);
165c2c66affSColin Finck USHORT KmtGetPoolType(PVOID Memory);
166c2c66affSColin Finck PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName);
167c2c66affSColin Finck PKTHREAD KmtStartThread(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext OPTIONAL);
168c2c66affSColin Finck VOID KmtFinishThread(IN PKTHREAD Thread OPTIONAL, IN PKEVENT Event OPTIONAL);
169c2c66affSColin Finck #elif defined KMT_USER_MODE
170c2c66affSColin Finck DWORD KmtRunKernelTest(IN PCSTR TestName);
171c2c66affSColin Finck
1729e12af56STimo Kreuzer DWORD KmtLoadDriver(IN PCWSTR ServiceName, IN BOOLEAN RestartIfRunning);
17304b35eccSThomas Faber VOID KmtUnloadDriverKeepService(VOID);
174c2c66affSColin Finck VOID KmtUnloadDriver(VOID);
1759e12af56STimo Kreuzer DWORD KmtOpenDriver(VOID);
176c2c66affSColin Finck VOID KmtCloseDriver(VOID);
1779e12af56STimo Kreuzer DWORD KmtLoadAndOpenDriver(IN PCWSTR ServiceName, IN BOOLEAN RestartIfRunning);
178c2c66affSColin Finck
179c2c66affSColin Finck DWORD KmtSendToDriver(IN DWORD ControlCode);
180c2c66affSColin Finck DWORD KmtSendStringToDriver(IN DWORD ControlCode, IN PCSTR String);
181c2c66affSColin Finck DWORD KmtSendWStringToDriver(IN DWORD ControlCode, IN PCWSTR String);
182c2c66affSColin Finck DWORD KmtSendUlongToDriver(IN DWORD ControlCode, IN DWORD Value);
183c2c66affSColin Finck DWORD KmtSendBufferToDriver(IN DWORD ControlCode, IN OUT PVOID Buffer OPTIONAL, IN DWORD InLength, IN OUT PDWORD OutLength);
184b10dd06aSGed Murphy
185dfb77638SGed Murphy
186dfb77638SGed Murphy DWORD KmtFltCreateService(_In_z_ PCWSTR ServiceName, _In_z_ PCWSTR DisplayName, _Out_ SC_HANDLE *ServiceHandle);
187dfb77638SGed Murphy DWORD KmtFltDeleteService(_In_opt_z_ PCWSTR ServiceName, _Inout_ SC_HANDLE *ServiceHandle);
188dfb77638SGed Murphy DWORD KmtFltAddAltitude(_In_z_ LPWSTR Altitude);
189dfb77638SGed Murphy DWORD KmtFltLoadDriver(_In_ BOOLEAN EnableDriverLoadPrivlege, _In_ BOOLEAN RestartIfRunning, _In_ BOOLEAN ConnectComms, _Out_ HANDLE *hPort);
190b10dd06aSGed Murphy DWORD KmtFltUnloadDriver(_In_ HANDLE *hPort, _In_ BOOLEAN DisonnectComms);
191dfb77638SGed Murphy DWORD KmtFltConnectComms(_Out_ HANDLE *hPort);
192dfb77638SGed Murphy DWORD KmtFltDisconnectComms(_In_ HANDLE hPort);
193b10dd06aSGed Murphy DWORD KmtFltRunKernelTest(_In_ HANDLE hPort, _In_z_ PCSTR TestName);
194b10dd06aSGed Murphy DWORD KmtFltSendToDriver(_In_ HANDLE hPort, _In_ DWORD Message);
195b10dd06aSGed Murphy DWORD KmtFltSendStringToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ PCSTR String);
196b10dd06aSGed Murphy DWORD KmtFltSendWStringToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ PCWSTR String);
197b10dd06aSGed Murphy DWORD KmtFltSendUlongToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ DWORD Value);
198b10dd06aSGed Murphy DWORD KmtFltSendBufferToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_reads_bytes_(BufferSize) LPVOID Buffer, _In_ DWORD BufferSize, _Out_writes_bytes_to_opt_(dwOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer, _In_ DWORD dwOutBufferSize, _Out_opt_ LPDWORD lpBytesReturned);
199b10dd06aSGed Murphy
200c2c66affSColin Finck #else /* if !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
201c2c66affSColin Finck #error either KMT_KERNEL_MODE or KMT_USER_MODE must be defined
202c2c66affSColin Finck #endif /* !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
203c2c66affSColin Finck
204c2c66affSColin Finck extern PKMT_RESULTBUFFER ResultBuffer;
205c2c66affSColin Finck
206c2c66affSColin Finck #ifdef __GNUC__
207c2c66affSColin Finck /* TODO: GCC doesn't understand %wZ :( */
208c2c66affSColin Finck #define KMT_FORMAT(type, fmt, first) /*__attribute__((__format__(type, fmt, first)))*/
209c2c66affSColin Finck #elif !defined __GNUC__
210c2c66affSColin Finck #define KMT_FORMAT(type, fmt, first)
211c2c66affSColin Finck #endif /* !defined __GNUC__ */
212c2c66affSColin Finck
213c2c66affSColin Finck #define START_TEST(name) VOID Test_##name(VOID)
214c2c66affSColin Finck
215c2c66affSColin Finck #ifndef KMT_STRINGIZE
216c2c66affSColin Finck #define KMT_STRINGIZE(x) #x
217c2c66affSColin Finck #endif /* !defined KMT_STRINGIZE */
218c2c66affSColin Finck #define ok(test, ...) ok_(test, __FILE__, __LINE__, __VA_ARGS__)
219c2c66affSColin Finck #define trace(...) trace_( __FILE__, __LINE__, __VA_ARGS__)
220c2c66affSColin Finck #define skip(test, ...) skip_(test, __FILE__, __LINE__, __VA_ARGS__)
221c2c66affSColin Finck
222c2c66affSColin Finck #define ok_(test, file, line, ...) KmtOk(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
223c2c66affSColin Finck #define trace_(file, line, ...) KmtTrace( file ":" KMT_STRINGIZE(line), __VA_ARGS__)
224c2c66affSColin Finck #define skip_(test, file, line, ...) KmtSkip(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
225c2c66affSColin Finck
226c2c66affSColin Finck BOOLEAN KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
227c2c66affSColin Finck BOOLEAN KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
228c2c66affSColin Finck VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 2, 0);
229c2c66affSColin Finck VOID KmtTrace(PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 2, 3);
230c2c66affSColin Finck BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
231c2c66affSColin Finck BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
232c2c66affSColin Finck PVOID KmtAllocateGuarded(SIZE_T SizeRequested);
233c2c66affSColin Finck VOID KmtFreeGuarded(PVOID Pointer);
234c2c66affSColin Finck
235c2c66affSColin Finck #ifdef KMT_KERNEL_MODE
236c2c66affSColin Finck #define ok_irql(irql) ok(KeGetCurrentIrql() == irql, "IRQL is %d, expected %d\n", KeGetCurrentIrql(), irql)
237c2c66affSColin Finck #endif /* defined KMT_KERNEL_MODE */
238c2c66affSColin Finck #define ok_eq_print(value, expected, spec) ok((value) == (expected), #value " = " spec ", expected " spec "\n", value, expected)
239c2c66affSColin Finck #define ok_eq_pointer(value, expected) ok_eq_print(value, expected, "%p")
240c2c66affSColin Finck #define ok_eq_int(value, expected) ok_eq_print(value, expected, "%d")
241c2c66affSColin Finck #define ok_eq_uint(value, expected) ok_eq_print(value, expected, "%u")
242c2c66affSColin Finck #define ok_eq_long(value, expected) ok_eq_print(value, expected, "%ld")
243c2c66affSColin Finck #define ok_eq_ulong(value, expected) ok_eq_print(value, expected, "%lu")
244c2c66affSColin Finck #define ok_eq_longlong(value, expected) ok_eq_print(value, expected, "%I64d")
245c2c66affSColin Finck #define ok_eq_ulonglong(value, expected) ok_eq_print(value, expected, "%I64u")
246c2c66affSColin Finck #define ok_eq_char(value, expected) ok_eq_print(value, expected, "%c")
247c2c66affSColin Finck #define ok_eq_wchar(value, expected) ok_eq_print(value, expected, "%C")
248c2c66affSColin Finck #ifndef _WIN64
249c2c66affSColin Finck #define ok_eq_size(value, expected) ok_eq_print(value, (SIZE_T)(expected), "%lu")
250c2c66affSColin Finck #define ok_eq_longptr(value, expected) ok_eq_print(value, (LONG_PTR)(expected), "%ld")
251c2c66affSColin Finck #define ok_eq_ulongptr(value, expected) ok_eq_print(value, (ULONG_PTR)(expected), "%lu")
252c2c66affSColin Finck #elif defined _WIN64
253c2c66affSColin Finck #define ok_eq_size(value, expected) ok_eq_print(value, (SIZE_T)(expected), "%I64u")
254c2c66affSColin Finck #define ok_eq_longptr(value, expected) ok_eq_print(value, (LONG_PTR)(expected), "%I64d")
255c2c66affSColin Finck #define ok_eq_ulongptr(value, expected) ok_eq_print(value, (ULONG_PTR)(expected), "%I64u")
256c2c66affSColin Finck #endif /* defined _WIN64 */
257c2c66affSColin Finck #define ok_eq_hex(value, expected) ok_eq_print(value, expected, "0x%08lx")
258c2c66affSColin Finck #define ok_bool_true(value, desc) ok((value) == TRUE, desc " FALSE, expected TRUE\n")
259c2c66affSColin Finck #define ok_bool_false(value, desc) ok((value) == FALSE, desc " TRUE, expected FALSE\n")
260c2c66affSColin Finck #define ok_eq_bool(value, expected) ok((value) == (expected), #value " = %s, expected %s\n", \
261c2c66affSColin Finck (value) ? "TRUE" : "FALSE", \
262c2c66affSColin Finck (expected) ? "TRUE" : "FALSE")
263c2c66affSColin Finck #define ok_eq_str(value, expected) ok(!strcmp(value, expected), #value " = \"%s\", expected \"%s\"\n", value, expected)
264c2c66affSColin Finck #define ok_eq_wstr(value, expected) ok(!wcscmp(value, expected), #value " = \"%ls\", expected \"%ls\"\n", value, expected)
265c2c66affSColin Finck #define ok_eq_tag(value, expected) ok_eq_print(value, expected, "0x%08lx")
266c2c66affSColin Finck
267*520cf229STimo Kreuzer #define ok_eq_hex64(value, expected) ok_eq_print(value, expected, "%I64x")
268*520cf229STimo Kreuzer #define ok_eq_xmm(value, expected) ok((value).Low == (expected).Low, #value " = %I64x'%08I64x, expected %I64x'%08I64x\n", (value).Low, (value).High, (expected).Low, (expected).High)
269*520cf229STimo Kreuzer
270c2c66affSColin Finck #define KMT_MAKE_CODE(ControlCode) CTL_CODE(FILE_DEVICE_UNKNOWN, \
271c2c66affSColin Finck 0xC00 + (ControlCode), \
272c2c66affSColin Finck METHOD_BUFFERED, \
273c2c66affSColin Finck FILE_ANY_ACCESS)
274c2c66affSColin Finck
275c2c66affSColin Finck #define MICROSECOND 10
276c2c66affSColin Finck #define MILLISECOND (1000 * MICROSECOND)
277c2c66affSColin Finck #define SECOND (1000 * MILLISECOND)
278c2c66affSColin Finck
279c2c66affSColin Finck /* See apitests/include/apitest.h */
280c2c66affSColin Finck #define KmtInvalidPointer ((PVOID)0x5555555555555555ULL)
281c2c66affSColin Finck
282c2c66affSColin Finck #define KmtStartSeh() \
283c2c66affSColin Finck { \
284c2c66affSColin Finck NTSTATUS ExceptionStatus = STATUS_SUCCESS; \
285c2c66affSColin Finck _SEH2_TRY \
286c2c66affSColin Finck {
287c2c66affSColin Finck
288c2c66affSColin Finck #define KmtEndSeh(ExpectedStatus) \
289c2c66affSColin Finck } \
290c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
291c2c66affSColin Finck { \
292c2c66affSColin Finck ExceptionStatus = _SEH2_GetExceptionCode(); \
293c2c66affSColin Finck } \
294c2c66affSColin Finck _SEH2_END; \
295c2c66affSColin Finck ok_eq_hex(ExceptionStatus, (ExpectedStatus)); \
296c2c66affSColin Finck }
297c2c66affSColin Finck
298c2c66affSColin Finck #define KmtGetSystemOrEmbeddedRoutineAddress(RoutineName) \
299c2c66affSColin Finck p##RoutineName = KmtGetSystemRoutineAddress(L ## #RoutineName); \
300c2c66affSColin Finck if (!p##RoutineName) \
301c2c66affSColin Finck { \
302c2c66affSColin Finck p##RoutineName = RoutineName; \
303c2c66affSColin Finck trace("Using embedded routine for " #RoutineName "\n"); \
304c2c66affSColin Finck } \
305c2c66affSColin Finck else \
306c2c66affSColin Finck trace("Using system routine for " #RoutineName "\n");
307c2c66affSColin Finck
308c2c66affSColin Finck #if defined KMT_DEFINE_TEST_FUNCTIONS
309c2c66affSColin Finck
310c2c66affSColin Finck #if defined KMT_KERNEL_MODE
311c2c66affSColin Finck #include "kmt_test_kernel.h"
312c2c66affSColin Finck #elif defined KMT_USER_MODE
313c2c66affSColin Finck #include "kmt_test_user.h"
314c2c66affSColin Finck #endif /* defined KMT_USER_MODE */
315c2c66affSColin Finck
316c2c66affSColin Finck PKMT_RESULTBUFFER ResultBuffer = NULL;
317c2c66affSColin Finck
KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer,PCSTR String,SIZE_T Length)318c2c66affSColin Finck static VOID KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer, PCSTR String, SIZE_T Length)
319c2c66affSColin Finck {
320c2c66affSColin Finck LONG OldLength;
321c2c66affSColin Finck LONG NewLength;
322c2c66affSColin Finck
323c2c66affSColin Finck if (!Buffer)
324c2c66affSColin Finck return;
325c2c66affSColin Finck
326c2c66affSColin Finck do
327c2c66affSColin Finck {
328c2c66affSColin Finck OldLength = Buffer->LogBufferLength;
329c2c66affSColin Finck NewLength = OldLength + (ULONG)Length;
330c2c66affSColin Finck if (NewLength > Buffer->LogBufferMaxLength)
331c2c66affSColin Finck return;
332c2c66affSColin Finck } while (InterlockedCompareExchange(&Buffer->LogBufferLength, NewLength, OldLength) != OldLength);
333c2c66affSColin Finck
334c2c66affSColin Finck memcpy(&Buffer->LogBuffer[OldLength], String, Length);
335c2c66affSColin Finck }
336c2c66affSColin Finck
337c2c66affSColin Finck KMT_FORMAT(ms_printf, 5, 0)
KmtXVSNPrintF(PSTR Buffer,SIZE_T BufferMaxLength,PCSTR FileAndLine,PCSTR Prepend,PCSTR Format,va_list Arguments)338c2c66affSColin Finck static SIZE_T KmtXVSNPrintF(PSTR Buffer, SIZE_T BufferMaxLength, PCSTR FileAndLine, PCSTR Prepend, PCSTR Format, va_list Arguments)
339c2c66affSColin Finck {
340c2c66affSColin Finck SIZE_T BufferLength = 0;
341c2c66affSColin Finck SIZE_T Length;
342c2c66affSColin Finck
343c2c66affSColin Finck if (FileAndLine)
344c2c66affSColin Finck {
345c2c66affSColin Finck PCSTR Slash;
346c2c66affSColin Finck Slash = strrchr(FileAndLine, '\\');
347c2c66affSColin Finck if (Slash)
348c2c66affSColin Finck FileAndLine = Slash + 1;
349c2c66affSColin Finck Slash = strrchr(FileAndLine, '/');
350c2c66affSColin Finck if (Slash)
351c2c66affSColin Finck FileAndLine = Slash + 1;
352c2c66affSColin Finck
353c2c66affSColin Finck Length = min(BufferMaxLength, strlen(FileAndLine));
354c2c66affSColin Finck memcpy(Buffer, FileAndLine, Length);
355c2c66affSColin Finck Buffer += Length;
356c2c66affSColin Finck BufferLength += Length;
357c2c66affSColin Finck BufferMaxLength -= Length;
358c2c66affSColin Finck }
359c2c66affSColin Finck if (Prepend)
360c2c66affSColin Finck {
361c2c66affSColin Finck Length = min(BufferMaxLength, strlen(Prepend));
362c2c66affSColin Finck memcpy(Buffer, Prepend, Length);
363c2c66affSColin Finck Buffer += Length;
364c2c66affSColin Finck BufferLength += Length;
365c2c66affSColin Finck BufferMaxLength -= Length;
366c2c66affSColin Finck }
367c2c66affSColin Finck if (Format)
368c2c66affSColin Finck {
369c2c66affSColin Finck Length = KmtVSNPrintF(Buffer, BufferMaxLength, Format, Arguments);
370c2c66affSColin Finck /* vsnprintf can return more than maxLength, we don't want to do that */
371c2c66affSColin Finck BufferLength += min(Length, BufferMaxLength);
372c2c66affSColin Finck }
373c2c66affSColin Finck return BufferLength;
374c2c66affSColin Finck }
375c2c66affSColin Finck
376c2c66affSColin Finck KMT_FORMAT(ms_printf, 5, 6)
KmtXSNPrintF(PSTR Buffer,SIZE_T BufferMaxLength,PCSTR FileAndLine,PCSTR Prepend,PCSTR Format,...)377c2c66affSColin Finck static SIZE_T KmtXSNPrintF(PSTR Buffer, SIZE_T BufferMaxLength, PCSTR FileAndLine, PCSTR Prepend, PCSTR Format, ...)
378c2c66affSColin Finck {
379c2c66affSColin Finck SIZE_T BufferLength;
380c2c66affSColin Finck va_list Arguments;
381c2c66affSColin Finck va_start(Arguments, Format);
382c2c66affSColin Finck BufferLength = KmtXVSNPrintF(Buffer, BufferMaxLength, FileAndLine, Prepend, Format, Arguments);
383c2c66affSColin Finck va_end(Arguments);
384c2c66affSColin Finck return BufferLength;
385c2c66affSColin Finck }
386c2c66affSColin Finck
KmtFinishTest(PCSTR TestName)387c2c66affSColin Finck VOID KmtFinishTest(PCSTR TestName)
388c2c66affSColin Finck {
389c2c66affSColin Finck CHAR MessageBuffer[512];
390c2c66affSColin Finck SIZE_T MessageLength;
391c2c66affSColin Finck
392c2c66affSColin Finck if (!ResultBuffer)
393c2c66affSColin Finck return;
394c2c66affSColin Finck
395c2c66affSColin Finck MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, NULL, NULL,
396c2c66affSColin Finck "%s: %ld tests executed (0 marked as todo, %ld failures), %ld skipped.\n",
397c2c66affSColin Finck TestName,
398c2c66affSColin Finck ResultBuffer->Successes + ResultBuffer->Failures,
399c2c66affSColin Finck ResultBuffer->Failures,
400c2c66affSColin Finck ResultBuffer->Skipped);
401c2c66affSColin Finck KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
402c2c66affSColin Finck }
403c2c66affSColin Finck
KmtVOk(INT Condition,PCSTR FileAndLine,PCSTR Format,va_list Arguments)404c2c66affSColin Finck BOOLEAN KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
405c2c66affSColin Finck {
406c2c66affSColin Finck CHAR MessageBuffer[512];
407c2c66affSColin Finck SIZE_T MessageLength;
408c2c66affSColin Finck
409c2c66affSColin Finck if (!ResultBuffer)
410c2c66affSColin Finck return Condition != 0;
411c2c66affSColin Finck
412c2c66affSColin Finck if (Condition)
413c2c66affSColin Finck {
414c2c66affSColin Finck InterlockedIncrement(&ResultBuffer->Successes);
415c2c66affSColin Finck
416c2c66affSColin Finck if (0/*KmtReportSuccess*/)
417c2c66affSColin Finck {
418c2c66affSColin Finck MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Test succeeded\n", NULL);
419c2c66affSColin Finck KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
420c2c66affSColin Finck }
421c2c66affSColin Finck }
422c2c66affSColin Finck else
423c2c66affSColin Finck {
424c2c66affSColin Finck InterlockedIncrement(&ResultBuffer->Failures);
425c2c66affSColin Finck MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Test failed: ", Format, Arguments);
426c2c66affSColin Finck KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
427c2c66affSColin Finck }
428c2c66affSColin Finck
429c2c66affSColin Finck return Condition != 0;
430c2c66affSColin Finck }
431c2c66affSColin Finck
KmtOk(INT Condition,PCSTR FileAndLine,PCSTR Format,...)432c2c66affSColin Finck BOOLEAN KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
433c2c66affSColin Finck {
434c2c66affSColin Finck BOOLEAN Ret;
435c2c66affSColin Finck va_list Arguments;
436c2c66affSColin Finck va_start(Arguments, Format);
437c2c66affSColin Finck Ret = KmtVOk(Condition, FileAndLine, Format, Arguments);
438c2c66affSColin Finck va_end(Arguments);
439c2c66affSColin Finck return Ret;
440c2c66affSColin Finck }
441c2c66affSColin Finck
KmtVTrace(PCSTR FileAndLine,PCSTR Format,va_list Arguments)442c2c66affSColin Finck VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments)
443c2c66affSColin Finck {
444c2c66affSColin Finck CHAR MessageBuffer[512];
445c2c66affSColin Finck SIZE_T MessageLength;
446c2c66affSColin Finck
447c2c66affSColin Finck MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": ", Format, Arguments);
448c2c66affSColin Finck KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
449c2c66affSColin Finck }
450c2c66affSColin Finck
KmtTrace(PCSTR FileAndLine,PCSTR Format,...)451c2c66affSColin Finck VOID KmtTrace(PCSTR FileAndLine, PCSTR Format, ...)
452c2c66affSColin Finck {
453c2c66affSColin Finck va_list Arguments;
454c2c66affSColin Finck va_start(Arguments, Format);
455c2c66affSColin Finck KmtVTrace(FileAndLine, Format, Arguments);
456c2c66affSColin Finck va_end(Arguments);
457c2c66affSColin Finck }
458c2c66affSColin Finck
KmtVSkip(INT Condition,PCSTR FileAndLine,PCSTR Format,va_list Arguments)459c2c66affSColin Finck BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
460c2c66affSColin Finck {
461c2c66affSColin Finck CHAR MessageBuffer[512];
462c2c66affSColin Finck SIZE_T MessageLength;
463c2c66affSColin Finck
464c2c66affSColin Finck if (!ResultBuffer)
465c2c66affSColin Finck return !Condition;
466c2c66affSColin Finck
467c2c66affSColin Finck if (!Condition)
468c2c66affSColin Finck {
469c2c66affSColin Finck InterlockedIncrement(&ResultBuffer->Skipped);
470c2c66affSColin Finck MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Tests skipped: ", Format, Arguments);
471c2c66affSColin Finck KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
472c2c66affSColin Finck }
473c2c66affSColin Finck
474c2c66affSColin Finck return !Condition;
475c2c66affSColin Finck }
476c2c66affSColin Finck
KmtSkip(INT Condition,PCSTR FileAndLine,PCSTR Format,...)477c2c66affSColin Finck BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
478c2c66affSColin Finck {
479c2c66affSColin Finck BOOLEAN Ret;
480c2c66affSColin Finck va_list Arguments;
481c2c66affSColin Finck va_start(Arguments, Format);
482c2c66affSColin Finck Ret = KmtVSkip(Condition, FileAndLine, Format, Arguments);
483c2c66affSColin Finck va_end(Arguments);
484c2c66affSColin Finck return Ret;
485c2c66affSColin Finck }
486c2c66affSColin Finck
KmtAllocateGuarded(SIZE_T SizeRequested)487c2c66affSColin Finck PVOID KmtAllocateGuarded(SIZE_T SizeRequested)
488c2c66affSColin Finck {
489c2c66affSColin Finck NTSTATUS Status;
490c2c66affSColin Finck SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
491c2c66affSColin Finck PVOID VirtualMemory = NULL;
492c2c66affSColin Finck PCHAR StartOfBuffer;
493c2c66affSColin Finck
494c2c66affSColin Finck Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
495c2c66affSColin Finck
496c2c66affSColin Finck if (!NT_SUCCESS(Status))
497c2c66affSColin Finck return NULL;
498c2c66affSColin Finck
499c2c66affSColin Finck Size -= PAGE_SIZE;
500c2c66affSColin Finck Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
501c2c66affSColin Finck if (!NT_SUCCESS(Status))
502c2c66affSColin Finck {
503c2c66affSColin Finck Size = 0;
504c2c66affSColin Finck Status = ZwFreeVirtualMemory(ZwCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
505c2c66affSColin Finck ok_eq_hex(Status, STATUS_SUCCESS);
506c2c66affSColin Finck return NULL;
507c2c66affSColin Finck }
508c2c66affSColin Finck
509c2c66affSColin Finck StartOfBuffer = VirtualMemory;
510c2c66affSColin Finck StartOfBuffer += Size - SizeRequested;
511c2c66affSColin Finck
512c2c66affSColin Finck return StartOfBuffer;
513c2c66affSColin Finck }
514c2c66affSColin Finck
KmtFreeGuarded(PVOID Pointer)515c2c66affSColin Finck VOID KmtFreeGuarded(PVOID Pointer)
516c2c66affSColin Finck {
517c2c66affSColin Finck NTSTATUS Status;
518c2c66affSColin Finck PVOID VirtualMemory = (PVOID)PAGE_ROUND_DOWN((SIZE_T)Pointer);
519c2c66affSColin Finck SIZE_T Size = 0;
520c2c66affSColin Finck
521c2c66affSColin Finck Status = ZwFreeVirtualMemory(ZwCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
522c2c66affSColin Finck ok_eq_hex(Status, STATUS_SUCCESS);
523c2c66affSColin Finck }
524c2c66affSColin Finck
525c2c66affSColin Finck #endif /* defined KMT_DEFINE_TEST_FUNCTIONS */
526c2c66affSColin Finck
527c2c66affSColin Finck #endif /* !defined _KMTEST_TEST_H_ */
528