0986ff415cbf17089e30faafedcb3dc71c0208d1
[reactos.git] / reactos / ntoskrnl / rtl / debug.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/rtl/dbgprint.c
5 * PURPOSE: Debug output
6 *
7 * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13 #include <internal/debug.h>
14
15 /* DATA *********************************************************************/
16
17 typedef struct
18 {
19 ULONG ComponentId;
20 ULONG Level;
21 } KD_COMPONENT_DATA;
22 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
23 KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES];
24 ULONG KdComponentTableEntries = 0;
25
26 /* FUNCTIONS ****************************************************************/
27
28 /*
29 * Note: DON'T CHANGE THIS FUNCTION!!!
30 * DON'T CALL HalDisplayString OR SOMETING ELSE!!!
31 * You'll only break the serial/bochs debugging feature!!!
32 */
33
34 /*
35 * @implemented
36 */
37 ULONG STDCALL
38 vDbgPrintExWithPrefix(IN LPCSTR Prefix,
39 IN ULONG ComponentId,
40 IN ULONG Level,
41 IN LPCSTR Format,
42 IN va_list ap)
43 {
44 ANSI_STRING DebugString;
45 CHAR Buffer[513];
46 PCHAR pBuffer;
47 ULONG pBufferSize;
48 #ifdef SERIALIZE_DBGPRINT
49 # define MESSAGETABLE_SIZE 16
50 LONG MyTableIndex;
51 static LONG Lock = 0;
52 static LONG TableWriteIndex = 0, TableReadIndex = 0;
53 static CHAR MessageTable[MESSAGETABLE_SIZE][sizeof(Buffer)] = { { '\0' } };
54 #endif /* SERIALIZE_DBGPRINT */
55
56 /* TODO FIXME - call NtQueryDebugFilterState() instead per Alex */
57 if ( !DbgQueryDebugFilterState ( ComponentId, Level ) )
58 return 0;
59
60 /* init ansi string */
61 DebugString.Buffer = Buffer;
62 DebugString.MaximumLength = sizeof(Buffer);
63
64 pBuffer = Buffer;
65 pBufferSize = sizeof(Buffer);
66 DebugString.Length = 0;
67 if ( Prefix && *Prefix )
68 {
69 DebugString.Length = strlen(Prefix);
70 if ( DebugString.Length >= sizeof(Buffer) )
71 DebugString.Length = sizeof(Buffer) - 1;
72 memmove ( Buffer, Prefix, DebugString.Length );
73 Buffer[DebugString.Length] = '\0';
74 pBuffer = &Buffer[DebugString.Length];
75 pBufferSize -= DebugString.Length;
76 }
77
78 DebugString.Length += _vsnprintf ( pBuffer, pBufferSize, Format, ap );
79 Buffer[sizeof(Buffer)-1] = '\0';
80
81 #ifdef SERIALIZE_DBGPRINT
82 /* check if we are already running */
83 if (InterlockedCompareExchange(&Lock, 1, 0) == 1)
84 {
85 MyTableIndex = InterlockedIncrement(&TableWriteIndex) - 1;
86 InterlockedCompareExchange(&TableWriteIndex, 0, MESSAGETABLE_SIZE);
87 MyTableIndex %= MESSAGETABLE_SIZE;
88
89 if (MessageTable[MyTableIndex][0] != '\0') /* table is full */
90 {
91 DebugString.Buffer = "CRITICAL ERROR: DbgPrint Table is FULL!";
92 DebugString.Length = 39;
93 KdpPrintString(&DebugString);
94 for (;;);
95 }
96 else
97 {
98 memcpy(MessageTable[MyTableIndex], DebugString.Buffer, DebugString.Length);
99 MessageTable[MyTableIndex][DebugString.Length] = '\0';
100 }
101 }
102 else
103 {
104 #endif /* SERIALIZE_DBGPRINT */
105 KdpPrintString (&DebugString);
106 #ifdef SERIALIZE_DBGPRINT
107 MyTableIndex = TableReadIndex;
108 while (MessageTable[MyTableIndex][0] != '\0')
109 {
110 /*DebugString.Buffer = "$$$";
111 DebugString.Length = 3;
112 KdpPrintString(&DebugString);*/
113
114 DebugString.Buffer = MessageTable[MyTableIndex];
115 DebugString.Length = strlen(DebugString.Buffer);
116 DebugString.MaximumLength = DebugString.Length + 1;
117
118 KdpPrintString(&DebugString);
119 MessageTable[MyTableIndex][0] = '\0';
120
121 MyTableIndex = InterlockedIncrement(&TableReadIndex);
122 InterlockedCompareExchange(&TableReadIndex, 0, MESSAGETABLE_SIZE);
123 MyTableIndex %= MESSAGETABLE_SIZE;
124 }
125 InterlockedDecrement(&Lock);
126 }
127 # undef MESSAGETABLE_SIZE
128 #endif /* SERIALIZE_DBGPRINT */
129
130 return (ULONG)DebugString.Length;
131 }
132
133 /*
134 * @implemented
135 */
136 ULONG STDCALL
137 vDbgPrintEx(IN ULONG ComponentId,
138 IN ULONG Level,
139 IN LPCSTR Format,
140 IN va_list ap)
141 {
142 return vDbgPrintExWithPrefix ( NULL, ComponentId, Level, Format, ap );
143 }
144
145 /*
146 * @implemented
147 */
148 ULONG
149 DbgPrint(PCH Format, ...)
150 {
151 va_list ap;
152 ULONG rc;
153
154 va_start (ap, Format);
155 /* TODO FIXME - use DPFLTR_DEFAULT_ID and DPFLTR_INFO_LEVEL
156 *
157 * https://www.osronline.com/article.cfm?article=295
158 *
159 * ( first need to add those items to default registry and write the code
160 * to load those settings so we don't anger ros-devs when DbgPrint() suddenly
161 * stops working )
162 *
163 * ( also when you do this, remove -1 hack from DbgQueryDebugFilterState() )
164 */
165 rc = vDbgPrintExWithPrefix ( NULL, (ULONG)-1, (ULONG)-1, Format, ap );
166 va_end (ap);
167
168 return rc;
169 }
170
171 /*
172 * @implemented
173 */
174 ULONG
175 __cdecl
176 DbgPrintEx(IN ULONG ComponentId,
177 IN ULONG Level,
178 IN PCH Format,
179 ...)
180 {
181 va_list ap;
182 ULONG rc;
183
184 va_start (ap, Format);
185 rc = vDbgPrintExWithPrefix ( NULL, ComponentId, Level, Format, ap );
186 va_end (ap);
187
188 return rc;
189 }
190
191 /*
192 * @unimplemented
193 */
194 ULONG
195 __cdecl
196 DbgPrintReturnControlC(PCH Format,
197 ...)
198 {
199 UNIMPLEMENTED;
200 return 0;
201 }
202
203 /*
204 * @unimplemented
205 */
206 VOID
207 STDCALL
208 DbgPrompt(PCH OutputString,
209 PCH InputString,
210 USHORT InputSize)
211 {
212 ANSI_STRING Output;
213 ANSI_STRING Input;
214
215 Input.Length = 0;
216 Input.MaximumLength = InputSize;
217 Input.Buffer = InputString;
218
219 Output.Length = strlen (OutputString);
220 Output.MaximumLength = Output.Length + 1;
221 Output.Buffer = OutputString;
222
223 /* FIXME: Not implemented yet!
224 KdpPromptString (&Output, &Input); */
225 }
226
227 /*
228 * @implemented
229 */
230 BOOLEAN
231 STDCALL
232 DbgQueryDebugFilterState(IN ULONG ComponentId,
233 IN ULONG Level)
234 {
235 int i;
236
237 /* HACK HACK HACK - see comments in DbgPrint() */
238 if ( ComponentId == -1 )
239 return TRUE;
240
241 /* convert Level to mask if it isn't already one */
242 if ( Level < 32 )
243 Level = 1 << Level;
244
245 for ( i = 0; i < KdComponentTableEntries; i++ )
246 {
247 if ( ComponentId == KdComponentTable[i].ComponentId )
248 {
249 if ( Level & KdComponentTable[i].Level )
250 return TRUE;
251 break;
252 }
253 }
254 return FALSE;
255 }
256
257 /*
258 * @implemented
259 */
260 NTSTATUS
261 STDCALL
262 DbgSetDebugFilterState(IN ULONG ComponentId,
263 IN ULONG Level,
264 IN BOOLEAN State)
265 {
266 int i;
267 for ( i = 0; i < KdComponentTableEntries; i++ )
268 {
269 if ( ComponentId == KdComponentTable[i].ComponentId )
270 break;
271 }
272 if ( i == KdComponentTableEntries )
273 {
274 if ( i == MAX_KD_COMPONENT_TABLE_ENTRIES )
275 return STATUS_INVALID_PARAMETER_1;
276 ++KdComponentTableEntries;
277 KdComponentTable[i].ComponentId = ComponentId;
278 KdComponentTable[i].Level = 0;
279 }
280 if ( State )
281 KdComponentTable[i].Level |= Level;
282 else
283 KdComponentTable[i].Level &= ~Level;
284 return STATUS_SUCCESS;
285 }
286
287 /*
288 * @unimplemented
289 */
290 NTSTATUS
291 STDCALL
292 DbgLoadImageSymbols(IN PUNICODE_STRING Name,
293 IN ULONG Base,
294 IN ULONG Unknown3)
295 {
296 UNIMPLEMENTED;
297 return STATUS_NOT_IMPLEMENTED;
298 }
299 /* EOF */