1f620ce77SHermès Bélusca-Maïto /*
2f620ce77SHermès Bélusca-Maïto * PROJECT: ReactOS KDBG Kernel Debugger
3f620ce77SHermès Bélusca-Maïto * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4f620ce77SHermès Bélusca-Maïto * PURPOSE: IO interface for KDBG. Provides local KDBG versions
5f620ce77SHermès Bélusca-Maïto * of KdpPrintString, KdpPromptString and KdpDprintf.
6f620ce77SHermès Bélusca-Maïto * COPYRIGHT: Copyright 2023 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
7f620ce77SHermès Bélusca-Maïto */
8f620ce77SHermès Bélusca-Maïto
9f620ce77SHermès Bélusca-Maïto /* INCLUDES ******************************************************************/
10f620ce77SHermès Bélusca-Maïto
11f620ce77SHermès Bélusca-Maïto #include <ntoskrnl.h>
12f620ce77SHermès Bélusca-Maïto #include "kdb.h"
13f620ce77SHermès Bélusca-Maïto
14f620ce77SHermès Bélusca-Maïto /* FUNCTIONS *****************************************************************/
15f620ce77SHermès Bélusca-Maïto
16*2046a17eSHermès Bélusca-Maïto static KD_CONTEXT KdbgKdContext;
17*2046a17eSHermès Bélusca-Maïto
18*2046a17eSHermès Bélusca-Maïto #undef KdSendPacket
19*2046a17eSHermès Bélusca-Maïto #define pKdSendPacket KdSendPacket
20*2046a17eSHermès Bélusca-Maïto
21*2046a17eSHermès Bélusca-Maïto #undef KdReceivePacket
22*2046a17eSHermès Bélusca-Maïto #define pKdReceivePacket KdReceivePacket
23*2046a17eSHermès Bélusca-Maïto
24f620ce77SHermès Bélusca-Maïto static VOID
KdbPrintStringWorker(_In_ const CSTRING * Output,_In_ ULONG ApiNumber,_Inout_ PDBGKD_DEBUG_IO DebugIo,_Inout_ PSTRING Header,_Inout_ PSTRING Data)25f620ce77SHermès Bélusca-Maïto KdbPrintStringWorker(
26f620ce77SHermès Bélusca-Maïto _In_ const CSTRING* Output,
27f620ce77SHermès Bélusca-Maïto _In_ ULONG ApiNumber,
28f620ce77SHermès Bélusca-Maïto _Inout_ PDBGKD_DEBUG_IO DebugIo,
29f620ce77SHermès Bélusca-Maïto _Inout_ PSTRING Header,
30f620ce77SHermès Bélusca-Maïto _Inout_ PSTRING Data)
31f620ce77SHermès Bélusca-Maïto {
32f620ce77SHermès Bélusca-Maïto USHORT Length;
33f620ce77SHermès Bélusca-Maïto C_ASSERT(PACKET_MAX_SIZE >= sizeof(*DebugIo));
34f620ce77SHermès Bélusca-Maïto
35f620ce77SHermès Bélusca-Maïto ASSERT((ApiNumber == DbgKdPrintStringApi) ||
36f620ce77SHermès Bélusca-Maïto (ApiNumber == DbgKdGetStringApi));
37f620ce77SHermès Bélusca-Maïto
38f620ce77SHermès Bélusca-Maïto /* Make sure we don't exceed the KD Packet size */
39f620ce77SHermès Bélusca-Maïto Length = min(Output->Length, PACKET_MAX_SIZE - sizeof(*DebugIo));
40f620ce77SHermès Bélusca-Maïto
41f620ce77SHermès Bélusca-Maïto /* Build the packet header */
42f620ce77SHermès Bélusca-Maïto DebugIo->ApiNumber = ApiNumber;
43f620ce77SHermès Bélusca-Maïto DebugIo->ProcessorLevel = 0; // (USHORT)KeProcessorLevel;
44f620ce77SHermès Bélusca-Maïto DebugIo->Processor = KeGetCurrentPrcb()->Number;
45f620ce77SHermès Bélusca-Maïto
46f620ce77SHermès Bélusca-Maïto if (ApiNumber == DbgKdPrintStringApi)
47f620ce77SHermès Bélusca-Maïto DebugIo->u.PrintString.LengthOfString = Length;
48f620ce77SHermès Bélusca-Maïto else // if (ApiNumber == DbgKdGetStringApi)
49f620ce77SHermès Bélusca-Maïto DebugIo->u.GetString.LengthOfPromptString = Length;
50f620ce77SHermès Bélusca-Maïto
51f620ce77SHermès Bélusca-Maïto Header->Length = sizeof(*DebugIo);
52f620ce77SHermès Bélusca-Maïto Header->Buffer = (PCHAR)DebugIo;
53f620ce77SHermès Bélusca-Maïto
54f620ce77SHermès Bélusca-Maïto /* Build the data */
55f620ce77SHermès Bélusca-Maïto Data->Length = Length;
56f620ce77SHermès Bélusca-Maïto Data->Buffer = (PCHAR)Output->Buffer;
57f620ce77SHermès Bélusca-Maïto
58f620ce77SHermès Bélusca-Maïto /* Send the packet */
59*2046a17eSHermès Bélusca-Maïto /* IO packet: call KdTerm */
60*2046a17eSHermès Bélusca-Maïto pKdSendPacket(PACKET_TYPE_KD_DEBUG_IO, Header, Data, &KdbgKdContext);
61f620ce77SHermès Bélusca-Maïto }
62f620ce77SHermès Bélusca-Maïto
63f620ce77SHermès Bélusca-Maïto VOID
KdbPrintString(_In_ const CSTRING * Output)64f620ce77SHermès Bélusca-Maïto KdbPrintString(
65f620ce77SHermès Bélusca-Maïto _In_ const CSTRING* Output)
66f620ce77SHermès Bélusca-Maïto {
67f620ce77SHermès Bélusca-Maïto DBGKD_DEBUG_IO DebugIo;
68f620ce77SHermès Bélusca-Maïto STRING Header, Data;
69f620ce77SHermès Bélusca-Maïto
70f620ce77SHermès Bélusca-Maïto KdbPrintStringWorker(Output, DbgKdPrintStringApi,
71f620ce77SHermès Bélusca-Maïto &DebugIo, &Header, &Data);
72f620ce77SHermès Bélusca-Maïto }
73f620ce77SHermès Bélusca-Maïto
74f620ce77SHermès Bélusca-Maïto static BOOLEAN
KdbPromptStringWorker(_In_ const CSTRING * PromptString,_Inout_ PSTRING ResponseString)75f620ce77SHermès Bélusca-Maïto KdbPromptStringWorker(
76f620ce77SHermès Bélusca-Maïto _In_ const CSTRING* PromptString,
77f620ce77SHermès Bélusca-Maïto _Inout_ PSTRING ResponseString)
78f620ce77SHermès Bélusca-Maïto {
79f620ce77SHermès Bélusca-Maïto DBGKD_DEBUG_IO DebugIo;
80f620ce77SHermès Bélusca-Maïto STRING Header, Data;
81f620ce77SHermès Bélusca-Maïto ULONG Length;
82f620ce77SHermès Bélusca-Maïto KDSTATUS Status;
83f620ce77SHermès Bélusca-Maïto
84f620ce77SHermès Bélusca-Maïto /* Print the prompt */
85f620ce77SHermès Bélusca-Maïto // DebugIo.u.GetString.LengthOfPromptString = Length;
86f620ce77SHermès Bélusca-Maïto DebugIo.u.GetString.LengthOfStringRead = ResponseString->MaximumLength;
87f620ce77SHermès Bélusca-Maïto KdbPrintStringWorker(PromptString, DbgKdGetStringApi,
88f620ce77SHermès Bélusca-Maïto &DebugIo, &Header, &Data);
89f620ce77SHermès Bélusca-Maïto
90f620ce77SHermès Bélusca-Maïto /* Set the maximum lengths for the receive */
91f620ce77SHermès Bélusca-Maïto Header.MaximumLength = sizeof(DebugIo);
92f620ce77SHermès Bélusca-Maïto Data.MaximumLength = ResponseString->MaximumLength;
93f620ce77SHermès Bélusca-Maïto /* Build the data */
94f620ce77SHermès Bélusca-Maïto Data.Buffer = ResponseString->Buffer;
95f620ce77SHermès Bélusca-Maïto
96f620ce77SHermès Bélusca-Maïto /* Enter receive loop */
97f620ce77SHermès Bélusca-Maïto do
98f620ce77SHermès Bélusca-Maïto {
99f620ce77SHermès Bélusca-Maïto /* Get our reply */
100*2046a17eSHermès Bélusca-Maïto /* IO packet: call KdTerm */
101*2046a17eSHermès Bélusca-Maïto Status = pKdReceivePacket(PACKET_TYPE_KD_DEBUG_IO,
102f620ce77SHermès Bélusca-Maïto &Header,
103f620ce77SHermès Bélusca-Maïto &Data,
104f620ce77SHermès Bélusca-Maïto &Length,
105*2046a17eSHermès Bélusca-Maïto &KdbgKdContext);
106f620ce77SHermès Bélusca-Maïto
107f620ce77SHermès Bélusca-Maïto /* Return TRUE if we need to resend */
108f620ce77SHermès Bélusca-Maïto if (Status == KdPacketNeedsResend)
109f620ce77SHermès Bélusca-Maïto return TRUE;
110f620ce77SHermès Bélusca-Maïto
111f620ce77SHermès Bélusca-Maïto /* Loop until we succeed */
112f620ce77SHermès Bélusca-Maïto } while (Status != KdPacketReceived);
113f620ce77SHermès Bélusca-Maïto
114f620ce77SHermès Bélusca-Maïto /* Don't copy back a larger response than there is room for */
115f620ce77SHermès Bélusca-Maïto Length = min(Length, ResponseString->MaximumLength);
116f620ce77SHermès Bélusca-Maïto
117f620ce77SHermès Bélusca-Maïto /* We've got the string back; return the length */
118f620ce77SHermès Bélusca-Maïto ResponseString->Length = (USHORT)Length;
119f620ce77SHermès Bélusca-Maïto
120f620ce77SHermès Bélusca-Maïto /* Success; we don't need to resend */
121f620ce77SHermès Bélusca-Maïto return FALSE;
122f620ce77SHermès Bélusca-Maïto }
123f620ce77SHermès Bélusca-Maïto
124f620ce77SHermès Bélusca-Maïto USHORT
KdbPromptString(_In_ const CSTRING * PromptString,_Inout_ PSTRING ResponseString)125f620ce77SHermès Bélusca-Maïto KdbPromptString(
126f620ce77SHermès Bélusca-Maïto _In_ const CSTRING* PromptString,
127f620ce77SHermès Bélusca-Maïto _Inout_ PSTRING ResponseString)
128f620ce77SHermès Bélusca-Maïto {
129f620ce77SHermès Bélusca-Maïto /* Enter prompt loop: send the prompt and receive the response */
130f620ce77SHermès Bélusca-Maïto ResponseString->Length = 0;
131f620ce77SHermès Bélusca-Maïto while (KdbPromptStringWorker(PromptString, ResponseString))
132f620ce77SHermès Bélusca-Maïto {
133f620ce77SHermès Bélusca-Maïto /* Loop while we need to resend */
134f620ce77SHermès Bélusca-Maïto }
135f620ce77SHermès Bélusca-Maïto return ResponseString->Length;
136f620ce77SHermès Bélusca-Maïto }
137f620ce77SHermès Bélusca-Maïto
138f620ce77SHermès Bélusca-Maïto
139f620ce77SHermès Bélusca-Maïto VOID
KdbPutsN(_In_ PCCH String,_In_ USHORT Length)140f620ce77SHermès Bélusca-Maïto KdbPutsN(
141f620ce77SHermès Bélusca-Maïto _In_ PCCH String,
142f620ce77SHermès Bélusca-Maïto _In_ USHORT Length)
143f620ce77SHermès Bélusca-Maïto {
144f620ce77SHermès Bélusca-Maïto CSTRING Output;
145f620ce77SHermès Bélusca-Maïto
146f620ce77SHermès Bélusca-Maïto Output.Buffer = String;
147f620ce77SHermès Bélusca-Maïto Output.Length = Output.MaximumLength = Length;
148f620ce77SHermès Bélusca-Maïto KdbPrintString(&Output);
149f620ce77SHermès Bélusca-Maïto }
150f620ce77SHermès Bélusca-Maïto
151f620ce77SHermès Bélusca-Maïto VOID
KdbPuts(_In_ PCSTR String)152f620ce77SHermès Bélusca-Maïto KdbPuts(
153f620ce77SHermès Bélusca-Maïto _In_ PCSTR String)
154f620ce77SHermès Bélusca-Maïto {
155f620ce77SHermès Bélusca-Maïto KdbPutsN(String, (USHORT)strnlen(String, MAXUSHORT - sizeof(ANSI_NULL)));
156f620ce77SHermès Bélusca-Maïto }
157f620ce77SHermès Bélusca-Maïto
158f620ce77SHermès Bélusca-Maïto VOID
159f620ce77SHermès Bélusca-Maïto __cdecl
KdbPrintf(_In_ PCSTR Format,...)160f620ce77SHermès Bélusca-Maïto KdbPrintf(
161f620ce77SHermès Bélusca-Maïto _In_ PCSTR Format,
162f620ce77SHermès Bélusca-Maïto ...)
163f620ce77SHermès Bélusca-Maïto {
164f620ce77SHermès Bélusca-Maïto va_list ap;
165f620ce77SHermès Bélusca-Maïto SIZE_T Length;
166f620ce77SHermès Bélusca-Maïto CHAR Buffer[1024];
167f620ce77SHermès Bélusca-Maïto
168f620ce77SHermès Bélusca-Maïto /* Format the string */
169f620ce77SHermès Bélusca-Maïto va_start(ap, Format);
170f620ce77SHermès Bélusca-Maïto Length = _vsnprintf(Buffer,
171f620ce77SHermès Bélusca-Maïto sizeof(Buffer),
172f620ce77SHermès Bélusca-Maïto Format,
173f620ce77SHermès Bélusca-Maïto ap);
174f620ce77SHermès Bélusca-Maïto Length = min(Length, MAXUSHORT - sizeof(ANSI_NULL));
175f620ce77SHermès Bélusca-Maïto va_end(ap);
176f620ce77SHermès Bélusca-Maïto
177f620ce77SHermès Bélusca-Maïto /* Send it to the debugger directly */
178f620ce77SHermès Bélusca-Maïto KdbPutsN(Buffer, (USHORT)Length);
179f620ce77SHermès Bélusca-Maïto }
180f620ce77SHermès Bélusca-Maïto
181f620ce77SHermès Bélusca-Maïto SIZE_T
KdbPrompt(_In_ PCSTR Prompt,_Out_ PCHAR Buffer,_In_ SIZE_T Size)182f620ce77SHermès Bélusca-Maïto KdbPrompt(
183f620ce77SHermès Bélusca-Maïto _In_ PCSTR Prompt,
184f620ce77SHermès Bélusca-Maïto _Out_ PCHAR Buffer,
185f620ce77SHermès Bélusca-Maïto _In_ SIZE_T Size)
186f620ce77SHermès Bélusca-Maïto {
187f620ce77SHermès Bélusca-Maïto CSTRING PromptString;
188f620ce77SHermès Bélusca-Maïto STRING ResponseBuffer;
189f620ce77SHermès Bélusca-Maïto
190f620ce77SHermès Bélusca-Maïto PromptString.Buffer = Prompt;
191f620ce77SHermès Bélusca-Maïto PromptString.Length = PromptString.MaximumLength =
192f620ce77SHermès Bélusca-Maïto (USHORT)strnlen(Prompt, MAXUSHORT - sizeof(ANSI_NULL));
193f620ce77SHermès Bélusca-Maïto
194f620ce77SHermès Bélusca-Maïto ResponseBuffer.Buffer = Buffer;
195f620ce77SHermès Bélusca-Maïto ResponseBuffer.Length = 0;
196f620ce77SHermès Bélusca-Maïto ResponseBuffer.MaximumLength = (USHORT)min(Size, MAXUSHORT);
197f620ce77SHermès Bélusca-Maïto
198f620ce77SHermès Bélusca-Maïto return KdbPromptString(&PromptString, &ResponseBuffer);
199f620ce77SHermès Bélusca-Maïto }
200f620ce77SHermès Bélusca-Maïto
201f620ce77SHermès Bélusca-Maïto /* EOF */
202