xref: /reactos/ntoskrnl/kdbg/kdb_print.c (revision 2046a17e)
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