1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Kernel-Mode Test Suite for KdSystemDebugControl (kernel-mode) 5 * COPYRIGHT: Copyright 2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 #include <ndk/kdfuncs.h> 10 11 #define ok_eq_print_test(testid, value, expected, spec) \ 12 ok((value) == (expected), "In test %lu: " #value " = " spec ", expected " spec "\n", testid, value, expected) 13 14 #define ok_eq_hex_test(testid, value, expected) \ 15 ok_eq_print_test(testid, value, expected, "0x%08lx") 16 17 #define ok_neq_print_test(testid, value, expected, spec) \ 18 ok((value) != (expected), "In test %lu: " #value " = " spec ", expected != " spec "\n", testid, value, expected) 19 20 #define ok_neq_hex_test(testid, value, expected) \ 21 ok_neq_print_test(testid, value, expected, "0x%08lx") 22 23 24 BOOLEAN 25 (NTAPI *pKdRefreshDebuggerNotPresent)(VOID); 26 27 NTSTATUS 28 (NTAPI *pKdSystemDebugControl)( 29 _In_ SYSDBG_COMMAND Command, 30 _In_ PVOID InputBuffer, 31 _In_ ULONG InputBufferLength, 32 _Out_ PVOID OutputBuffer, 33 _In_ ULONG OutputBufferLength, 34 _Inout_ PULONG ReturnLength, 35 _In_ KPROCESSOR_MODE PreviousMode); 36 37 38 static 39 NTSTATUS 40 TestSystemDebugControl( 41 _In_ SYSDBG_COMMAND Command) 42 { 43 return pKdSystemDebugControl(Command, 44 NULL, // _In_ PVOID InputBuffer, 45 0, // _In_ ULONG InputBufferLength, 46 NULL, // _Out_ PVOID OutputBuffer, 47 0, // _In_ ULONG OutputBufferLength, 48 NULL, 49 KernelMode); 50 } 51 52 START_TEST(KdSystemDebugControl) 53 { 54 NTSTATUS Status; 55 ULONG Command; 56 RTL_OSVERSIONINFOEXW verInfo; 57 UNICODE_STRING fnName; 58 BOOLEAN IsNT52SP1OrHigher; 59 BOOLEAN IsVistaOrHigher; 60 BOOLEAN IsDebuggerActive; 61 62 /* Test for OS version: KdSystemDebugControl() 63 * exists only on NT 5.2 SP1 and higher */ 64 verInfo.dwOSVersionInfoSize = sizeof(verInfo); 65 Status = RtlGetVersion((PRTL_OSVERSIONINFOW)&verInfo); 66 if (skip(NT_SUCCESS(Status), "RtlGetVersion() returned 0x%08lx\n", Status)) 67 return; 68 69 // IsWindowsVersionOrGreater(5, 2, 1); 70 IsNT52SP1OrHigher = 71 (verInfo.dwMajorVersion > 5) || 72 (verInfo.dwMajorVersion == 5 && verInfo.dwMinorVersion > 2) || 73 (verInfo.dwMajorVersion == 5 && verInfo.dwMinorVersion == 2 && verInfo.wServicePackMajor >= 1); 74 75 if (skip(IsNT52SP1OrHigher, "KdSystemDebugControl() only exists on NT 5.2 SP1 and higher\n")) 76 return; 77 78 // IsWindowsVersionOrGreater(6, 0, 0); 79 IsVistaOrHigher = (verInfo.dwMajorVersion >= 6); 80 81 82 /* Load the Kd routines at runtime */ 83 84 /* Note: KdRefreshDebuggerNotPresent() is NT 5.2+ */ 85 RtlInitUnicodeString(&fnName, L"KdRefreshDebuggerNotPresent"); 86 pKdRefreshDebuggerNotPresent = MmGetSystemRoutineAddress(&fnName); 87 ok(!!pKdRefreshDebuggerNotPresent, 88 "KdRefreshDebuggerNotPresent() unavailable but OS is NT 5.2 SP1 or higher?\n"); 89 90 RtlInitUnicodeString(&fnName, L"KdSystemDebugControl"); 91 pKdSystemDebugControl = MmGetSystemRoutineAddress(&fnName); 92 if (skip(!!pKdSystemDebugControl, "KdSystemDebugControl() unavailable but OS is NT 5.2 SP1 or higher?\n")) 93 return; 94 95 96 /* Check whether the kernel debugger is present or not */ 97 IsDebuggerActive = (pKdRefreshDebuggerNotPresent 98 ? !pKdRefreshDebuggerNotPresent() 99 : (/*KD_DEBUGGER_ENABLED &&*/ !KD_DEBUGGER_NOT_PRESENT)); 100 101 trace("Debugger is %s\n", IsDebuggerActive ? "active" : "inactive"); 102 103 /* Unsupported commands */ 104 for (Command = 0; Command <= 6; ++Command) 105 { 106 Status = TestSystemDebugControl((SYSDBG_COMMAND)Command); 107 if (!IsVistaOrHigher || IsDebuggerActive) 108 ok_eq_hex_test(Command, Status, STATUS_INVALID_INFO_CLASS); 109 else 110 ok_eq_hex_test(Command, Status, STATUS_DEBUGGER_INACTIVE); 111 } 112 113 /* 114 * Supported commands: 115 * 116 * SysDbgQueryVersion = 7, 117 * SysDbgReadVirtual = 8, 118 * SysDbgWriteVirtual = 9, 119 * SysDbgReadPhysical = 10, 120 * SysDbgWritePhysical = 11, 121 * SysDbgReadControlSpace = 12, 122 * SysDbgWriteControlSpace = 13, 123 * SysDbgReadIoSpace = 14, 124 * SysDbgWriteIoSpace = 15, 125 * SysDbgReadMsr = 16, 126 * SysDbgWriteMsr = 17, 127 * SysDbgReadBusData = 18, 128 * SysDbgWriteBusData = 19, 129 * SysDbgCheckLowMemory = 20 130 */ 131 for (Command = 7; Command <= 20; ++Command) 132 { 133 Status = TestSystemDebugControl((SYSDBG_COMMAND)Command); 134 if (!IsVistaOrHigher || IsDebuggerActive) 135 ok_neq_hex_test(Command, Status, STATUS_INVALID_INFO_CLASS); // Status must be != STATUS_INVALID_INFO_CLASS 136 else 137 ok_eq_hex_test(Command, Status, STATUS_DEBUGGER_INACTIVE); 138 } 139 140 /* Unsupported commands */ 141 for (Command = 21; Command <= 40; ++Command) 142 { 143 Status = TestSystemDebugControl((SYSDBG_COMMAND)Command); 144 if (!IsVistaOrHigher || IsDebuggerActive) 145 ok_eq_hex_test(Command, Status, STATUS_INVALID_INFO_CLASS); 146 else 147 ok_eq_hex_test(Command, Status, STATUS_DEBUGGER_INACTIVE); 148 } 149 } 150 151 /* EOF */ 152