Home | History | Annotate | Download | only in tests
      1 /* Capstone Disassembly Engine */
      2 /* By Satoshi Tanda <tanda.sat (at) gmail.com>, 2016 */
      3 
      4 #include <ntddk.h>
      5 #include <capstone.h>
      6 
      7 #ifdef __cplusplus
      8 extern "C" {
      9 #endif
     10 
     11 #include "../utils.h"   // for cs_snprintf
     12 
     13 #ifdef __cplusplus
     14 }
     15 #endif
     16 
     17 EXTERN_C DRIVER_INITIALIZE DriverEntry;
     18 
     19 #pragma warning(push)
     20 #pragma warning(disable : 4005)   // 'identifier' : macro redefinition
     21 #pragma warning(disable : 4007)   // 'main': must be '__cdecl'
     22 
     23 // Drivers must protect floating point hardware state. See use of float.
     24 // Use KeSaveFloatingPointState/KeRestoreFloatingPointState around floating
     25 // point operations. Display Drivers should use the corresponding Eng... routines.
     26 #pragma warning(disable : 28110)  // Suppress this, as it is false positive.
     27 
     28 // "Import" existing tests into this file. All code is encaptured into unique
     29 // namespace so that the same name does not conflict. Beware that those code
     30 // is going to be compiled as C++ source file and not C files because this file
     31 // is C++.
     32 
     33 namespace unnamed {
     34 #include "test.c"
     35 }  // namespace unnamed
     36 
     37 namespace detail {
     38 #include "test_detail.c"
     39 }  // namespace detail
     40 
     41 namespace skipdata {
     42 #include "test_skipdata.c"
     43 }  // namespace skipdata
     44 
     45 namespace iter {
     46 #include "test_iter.c"
     47 }  // namespace iter
     48 
     49 namespace arm {
     50 #include "test_arm.c"
     51 }  // namespace arm
     52 
     53 namespace arm64 {
     54 #include "test_arm64.c"
     55 }  // namespace arm64
     56 
     57 namespace mips {
     58 #include "test_mips.c"
     59 }  // namespace mips
     60 
     61 namespace ppc {
     62 #include "test_ppc.c"
     63 }  // namespace ppc
     64 
     65 namespace sparc {
     66 #include "test_sparc.c"
     67 }  // namespace sparc
     68 
     69 namespace systemz {
     70 #include "test_systemz.c"
     71 }  // namespace systemz
     72 
     73 namespace x86 {
     74 #include "test_x86.c"
     75 }  // namespace x86
     76 
     77 namespace xcore {
     78 #include "test_xcore.c"
     79 }  // namespace xcore
     80 
     81 #pragma warning(pop)
     82 
     83 // Exercises all existing regression tests
     84 static void test()
     85 {
     86 	KFLOATING_SAVE float_save;
     87 	NTSTATUS status;
     88 
     89 	// Any of Capstone APIs cannot be called at IRQL higher than DISPATCH_LEVEL
     90 	// since our malloc implementation using ExAllocatePoolWithTag() is able to
     91 	// allocate memory only up to the DISPATCH_LEVEL level.
     92 	NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
     93 
     94 	// On a 32bit driver, KeSaveFloatingPointState() is required before using any
     95 	// Capstone function because Capstone can access to the MMX/x87 registers and
     96 	// 32bit Windows requires drivers to use KeSaveFloatingPointState() before and
     97 	// KeRestoreFloatingPointState() after accessing them. See "Using Floating
     98 	// Point or MMX in a WDM Driver" on MSDN for more details.
     99 	status = KeSaveFloatingPointState(&float_save);
    100 	if (!NT_SUCCESS(status)) {
    101 		printf("ERROR: Failed to save floating point state!\n");
    102 		return;
    103 	}
    104 
    105 	unnamed::test();
    106 	detail::test();
    107 	skipdata::test();
    108 	iter::test();
    109 	arm::test();
    110 	arm64::test();
    111 	mips::test();
    112 	ppc::test();
    113 	sparc::test();
    114 	systemz::test();
    115 	x86::test();
    116 	xcore::test();
    117 
    118 	// Restores the nonvolatile floating-point context.
    119 	KeRestoreFloatingPointState(&float_save);
    120 }
    121 
    122 // Functional test for cs_winkernel_vsnprintf()
    123 static void cs_winkernel_vsnprintf_test()
    124 {
    125 	char buf[10];
    126 	bool ok = true;
    127 	ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "") == 0 && strcmp(buf, "") == 0);
    128 	ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0") == 1 && strcmp(buf, "0") == 0);
    129 	ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "012345678") == 9 && strcmp(buf, "012345678") == 0);
    130 	ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789") == 10 && strcmp(buf, "012345678") == 0);
    131 	ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "01234567890") == 11 && strcmp(buf, "012345678") == 0);
    132 	ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789001234567890") == 22 && strcmp(buf, "012345678") == 0);
    133 	if (!ok) {
    134 		printf("ERROR: cs_winkernel_vsnprintf_test() did not produce expected results!\n");
    135 	}
    136 }
    137 
    138 // Driver entry point
    139 EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
    140 {
    141 	UNREFERENCED_PARAMETER(DriverObject);
    142 	UNREFERENCED_PARAMETER(RegistryPath);
    143 	cs_winkernel_vsnprintf_test();
    144 	test();
    145 	return STATUS_CANCELLED;
    146 }
    147 
    148 // This functions mimics printf() but does not return the same value as printf()
    149 // would do. printf() is required to exercise regression tests.
    150 _Use_decl_annotations_
    151 int __cdecl printf(const char * format, ...)
    152 {
    153 	NTSTATUS status;
    154 	va_list args;
    155 
    156 	va_start(args, format);
    157 	status = vDbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, format, args);
    158 	va_end(args);
    159 	return NT_SUCCESS(status);
    160 }
    161