ReactOS 0.4.16-dev-814-g656a5dc
NtSystemDebugControl.c
Go to the documentation of this file.
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 NtSystemDebugControl (user-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/exfuncs.h>
10#include <ndk/kdfuncs.h>
11#include <ndk/setypes.h>
12
13#define ok_eq_print_test(testid, value, expected, spec) \
14 ok((value) == (expected), "In test %lu: " #value " = " spec ", expected " spec "\n", testid, value, expected)
15
16#define ok_eq_hex_test(testid, value, expected) \
17 ok_eq_print_test(testid, value, expected, "0x%08lx")
18
19#define ok_neq_print_test(testid, value, expected, spec) \
20 ok((value) != (expected), "In test %lu: " #value " = " spec ", expected != " spec "\n", testid, value, expected)
21
22#define ok_neq_hex_test(testid, value, expected) \
23 ok_neq_print_test(testid, value, expected, "0x%08lx")
24
27{
31
32 verInfo.dwOSVersionInfoSize = sizeof(verInfo);
34 if (!NT_SUCCESS(Status))
35 {
36 trace("RtlGetVersion() returned 0x%08lx\n", Status);
37 return 0;
38 }
39
40 Version = ((((verInfo.dwMajorVersion & 0xFF) << 8) |
41 (verInfo.dwMinorVersion & 0xFF)) << 16) |
42 (((verInfo.wServicePackMajor & 0xFF) << 8) |
43 (verInfo.wServicePackMinor & 0xFF));
44
45 return Version;
46}
47
48static
52{
54 NULL, // _In_ PVOID InputBuffer,
55 0, // _In_ ULONG InputBufferLength,
56 NULL, // _Out_ PVOID OutputBuffer,
57 0, // _In_ ULONG OutputBufferLength,
58 NULL);
59}
60
62{
66 SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo = {0};
67 BOOLEAN IsNT52SP1OrHigher;
68 BOOLEAN IsVistaOrHigher;
69 BOOLEAN IsDebuggerActive;
70 BOOLEAN PrivilegeSet[2] = {FALSE};
71 BOOLEAN WasDebuggerEnabled;
72
73 /* Test for OS version: KdSystemDebugControl()
74 * exists only on NT 5.2 SP1 and higher */
76 if (skip(Version != 0, "GetNtDdiVersion() returned 0\n"))
77 return;
78
79 // IsWindowsVersionOrGreater(5, 2, 1);
80 IsNT52SP1OrHigher = (Version >= NTDDI_WS03SP1);
81
82 // IsWindowsVersionOrGreater(6, 0, 0);
83 IsVistaOrHigher = (Version >= NTDDI_WIN6);
84
85
86 /* Check whether the kernel debugger is present or not */
88 &DebuggerInfo,
89 sizeof(DebuggerInfo),
90 NULL);
91
92 IsDebuggerActive = NT_SUCCESS(Status) && !DebuggerInfo.KernelDebuggerNotPresent;
93 // DebuggerInfo.KernelDebuggerEnabled; // SharedUserData->KdDebuggerEnabled;
94
95 trace("Debugger is %s\n", IsDebuggerActive ? "active" : "inactive");
96
97 /*
98 * Explicitly disable the debug privilege so that we can test
99 * that NtSystemDebugControl() fails when the privilege is absent.
100 * Note that SysDbgGetTriageDump (29) is used for testing here,
101 * because it doesn't require a debugger to be active in order
102 * to proceed further (privilege check and actual functionality).
103 */
108
109 /* Now, enable the debug privilege for the rest of the tests */
112
113 /* Supported commands */
114 for (Command = 0; Command <= 5; ++Command)
115 {
117 if (!IsVistaOrHigher || IsDebuggerActive)
119 else
121 }
122
123 /* Test SysDbgBreakPoint (6) only when the debugger is inactive
124 * or disabled; otherwise this call would trigger a breakpoint */
125 if (!skip((IsVistaOrHigher && !IsDebuggerActive) || !SharedUserData->KdDebuggerEnabled,
126 "NtSystemDebugControl(SysDbgBreakPoint) skipped because the debugger is active\n"))
127 {
129 if (!SharedUserData->KdDebuggerEnabled /*&& (!IsVistaOrHigher || IsDebuggerActive)*/)
130 {
132 }
133 else
134 {
135 // ASSERT(IsVistaOrHigher && !IsDebuggerActive);
137 }
138 }
139
140 /*
141 * Commands handled by kernel-mode KdSystemDebugControl(),
142 * and unsupported in user-mode:
143 *
144 * SysDbgQueryVersion = 7,
145 * SysDbgReadVirtual = 8,
146 * SysDbgWriteVirtual = 9,
147 * SysDbgReadPhysical = 10,
148 * SysDbgWritePhysical = 11,
149 * SysDbgReadControlSpace = 12,
150 * SysDbgWriteControlSpace = 13,
151 * SysDbgReadIoSpace = 14,
152 * SysDbgWriteIoSpace = 15,
153 * SysDbgReadMsr = 16,
154 * SysDbgWriteMsr = 17,
155 * SysDbgReadBusData = 18,
156 * SysDbgWriteBusData = 19,
157 * SysDbgCheckLowMemory = 20
158 */
159 // TODO: Handle this differently if !IsNT52SP1OrHigher ?
160 DBG_UNREFERENCED_PARAMETER(IsNT52SP1OrHigher);
161 for (Command = 7; Command <= 20; ++Command)
162 {
164 if (!IsVistaOrHigher || IsDebuggerActive)
166 else
168 }
169
170
171 /*
172 * Separately test commands SysDbgEnableKernelDebugger (21)
173 * and SysDbgDisableKernelDebugger (22), as they influence
174 * the internal state of the debugger. The order of testing
175 * matters, depending on whether the debugger was originally
176 * enabled or disabled.
177 */
178
179 /* Save whether the debugger is currently enabled;
180 * the next tests are going to change its state */
181 WasDebuggerEnabled = SharedUserData->KdDebuggerEnabled;
182
183//
184// FIXME: Re-enable ONCE our KDBG and KDCOM dlls support disabling and re-enabling.
185//
186 DBG_UNREFERENCED_LOCAL_VARIABLE(WasDebuggerEnabled);
187#if 0
188 /* Try to disable or enable the debugger, depending on its original state */
189 if (WasDebuggerEnabled)
191 else
194 if (!IsVistaOrHigher || IsDebuggerActive)
195 {
196 /*
197 * KdEnableDebugger() (with lock enabled) wants a KdDisableDebugger()
198 * first (i.e. that the debugger was previously explicitly disabled)
199 * in order to return success; otherwise it'll return STATUS_INVALID_PARAMETER.
200 */
202 {
204 "In test %lu: Status = 0x%08lx, expected 0x%08lx or 0x%08lx\n",
206 }
207 else
208 {
210 }
211 }
212 else
213 {
215 }
216
217 /* Re-enable or disable the debugger, depending on its original state */
218 if (WasDebuggerEnabled)
220 else
223 if (!IsVistaOrHigher || IsDebuggerActive)
225 else
227#endif
228// END FIXME
229
230
231 /* Supported commands */
232 for (Command = 23; Command <= 31; ++Command)
233 {
235 if (!IsVistaOrHigher || IsDebuggerActive)
237 else
239 }
240
241 /* These are Vista+ and depend on the OS version */
242 for (Command = 32; Command <= 36; ++Command)
243 {
245 if (!IsVistaOrHigher || IsDebuggerActive)
246 {
247 if (Version >= NTDDI_WIN6) // IsVistaOrHigher
249 else
251 }
252 else
253 {
255 }
256 }
257
258 Command = 37; // SysDbgGetLiveKernelDump
260 if (!IsVistaOrHigher || IsDebuggerActive)
261 {
262 if (Version >= NTDDI_WINBLUE)
264 else
266 }
267 else
268 {
270 }
271
272 Command = 38; // SysDbgKdPullRemoteFile
274 if (!IsVistaOrHigher || IsDebuggerActive)
275 {
276 if (Version >= NTDDI_WIN10_VB)
278 else
280 }
281 else
282 {
284 }
285
286 /* Unsupported commands */
287 for (Command = 39; Command <= 40; ++Command)
288 {
290 if (!IsVistaOrHigher || IsDebuggerActive)
292 else
294 }
295
296 /* Finally restore the original debug privilege state */
297 RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, PrivilegeSet[0], FALSE, &PrivilegeSet[0]);
298}
299
300/* EOF */
#define ok_eq_hex_test(testid, value, expected)
static NTSTATUS TestSystemDebugControl(_In_ SYSDBG_COMMAND Command)
#define ok_neq_hex_test(testid, value, expected)
ULONG GetNtDdiVersion(VOID)
unsigned char BOOLEAN
#define ok_eq_hex(value, expected)
Definition: apitest.h:58
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
NTSTATUS NTAPI NtSystemDebugControl(_In_ SYSDBG_COMMAND Command, _In_reads_bytes_(InputBufferLength) PVOID InputBuffer, _In_ ULONG InputBufferLength, _Out_writes_bytes_(OutputBufferLength) PVOID OutputBuffer, _In_ ULONG OutputBufferLength, _Out_opt_ PULONG ReturnLength)
Perform various queries to the kernel debugger.
Definition: dbgctrl.c:209
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
Definition: version.c:158
@ SystemKernelDebuggerInformation
Definition: ntddk_ex.h:46
Status
Definition: gdiplustypes.h:25
#define SE_DEBUG_PRIVILEGE
Definition: security.c:674
#define STATUS_DEBUGGER_INACTIVE
Definition: debugger.c:30
@ SysDbgEnableKernelDebugger
Definition: kdtypes.h:83
@ SysDbgBreakPoint
Definition: kdtypes.h:68
@ SysDbgGetTriageDump
Definition: kdtypes.h:91
@ SysDbgDisableKernelDebugger
Definition: kdtypes.h:84
enum _SYSDBG_COMMAND SYSDBG_COMMAND
NTSYSAPI NTSTATUS NTAPI RtlAdjustPrivilege(_In_ ULONG Privilege, _In_ BOOLEAN NewValue, _In_ BOOLEAN ForThread, _Out_ PBOOLEAN OldValue)
#define _In_
Definition: no_sal2.h:158
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:327
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:326
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define SharedUserData
#define NTDDI_WIN6
Definition: sdkddkver.h:97
#define NTDDI_WIN10_VB
Definition: sdkddkver.h:125
#define NTDDI_WS03SP1
Definition: sdkddkver.h:93
#define NTDDI_WINBLUE
Definition: sdkddkver.h:114
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
Definition: shell.h:41
ULONG dwMajorVersion
Definition: rtltypes.h:270
ULONG dwMinorVersion
Definition: rtltypes.h:271
ULONG dwOSVersionInfoSize
Definition: rtltypes.h:269
USHORT wServicePackMinor
Definition: rtltypes.h:276
USHORT wServicePackMajor
Definition: rtltypes.h:275
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE _In_ USHORT _In_ USHORT Version
Definition: wdffdo.h:469