1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdapi.c
5 * PURPOSE: KD64 Public Routines and Internal Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13
14 #ifdef KDBG
15 #include <kdbg/kdb.h>
16 #endif
17
18 #define NDEBUG
19 #include <debug.h>
20
21 VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads);
22
23 /* PRIVATE FUNCTIONS *********************************************************/
24
25 VOID
26 NTAPI
KdpMoveMemory(_In_ PVOID Destination,_In_ PVOID Source,_In_ SIZE_T Length)27 KdpMoveMemory(
28 _In_ PVOID Destination,
29 _In_ PVOID Source,
30 _In_ SIZE_T Length)
31 {
32 PCHAR DestinationBytes, SourceBytes;
33
34 /* Copy the buffers 1 byte at a time */
35 DestinationBytes = Destination;
36 SourceBytes = Source;
37 while (Length--) *DestinationBytes++ = *SourceBytes++;
38 }
39
40 VOID
41 NTAPI
KdpZeroMemory(_In_ PVOID Destination,_In_ SIZE_T Length)42 KdpZeroMemory(
43 _In_ PVOID Destination,
44 _In_ SIZE_T Length)
45 {
46 PCHAR DestinationBytes;
47
48 /* Zero the buffer 1 byte at a time */
49 DestinationBytes = Destination;
50 while (Length--) *DestinationBytes++ = 0;
51 }
52
53 NTSTATUS
54 NTAPI
KdpCopyMemoryChunks(_In_ ULONG64 Address,_In_ PVOID Buffer,_In_ ULONG TotalSize,_In_ ULONG ChunkSize,_In_ ULONG Flags,_Out_opt_ PULONG ActualSize)55 KdpCopyMemoryChunks(
56 _In_ ULONG64 Address,
57 _In_ PVOID Buffer,
58 _In_ ULONG TotalSize,
59 _In_ ULONG ChunkSize,
60 _In_ ULONG Flags,
61 _Out_opt_ PULONG ActualSize)
62 {
63 NTSTATUS Status;
64 ULONG RemainingLength, CopyChunk;
65
66 /* Check if we didn't get a chunk size or if it is too big */
67 if (ChunkSize == 0)
68 {
69 /* Default to 4 byte chunks */
70 ChunkSize = 4;
71 }
72 else if (ChunkSize > MMDBG_COPY_MAX_SIZE)
73 {
74 /* Normalize to maximum size */
75 ChunkSize = MMDBG_COPY_MAX_SIZE;
76 }
77
78 /* Copy the whole range in aligned chunks */
79 RemainingLength = TotalSize;
80 CopyChunk = 1;
81 while (RemainingLength > 0)
82 {
83 /*
84 * Determine the best chunk size for this round.
85 * The ideal size is aligned, isn't larger than the
86 * the remaining length and respects the chunk limit.
87 */
88 while (((CopyChunk * 2) <= RemainingLength) &&
89 (CopyChunk < ChunkSize) &&
90 ((Address & ((CopyChunk * 2) - 1)) == 0))
91 {
92 /* Increase it */
93 CopyChunk *= 2;
94 }
95
96 /*
97 * The chunk size can be larger than the remaining size if this
98 * isn't the first round, so check if we need to shrink it back.
99 */
100 while (CopyChunk > RemainingLength)
101 {
102 /* Shrink it */
103 CopyChunk /= 2;
104 }
105
106 /* Do the copy */
107 Status = MmDbgCopyMemory(Address, Buffer, CopyChunk, Flags);
108 if (!NT_SUCCESS(Status))
109 {
110 /* Copy failed, break out */
111 break;
112 }
113
114 /* Update pointers and length for the next run */
115 Address = Address + CopyChunk;
116 Buffer = (PVOID)((ULONG_PTR)Buffer + CopyChunk);
117 RemainingLength = RemainingLength - CopyChunk;
118 }
119
120 /* We may have modified executable code, flush the instruction cache */
121 KeSweepICache((PVOID)(ULONG_PTR)Address, TotalSize);
122
123 /*
124 * Return the size we managed to copy and return
125 * success if we could copy the whole range.
126 */
127 if (ActualSize) *ActualSize = TotalSize - RemainingLength;
128 return RemainingLength == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
129 }
130
131 VOID
132 NTAPI
KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PCONTEXT Context)133 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,
134 IN PCONTEXT Context)
135 {
136 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;
137 STRING Header;
138 NTSTATUS Status = STATUS_SUCCESS;
139
140 /* Validate the address space */
141 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)
142 {
143 /* Check if this is process memory */
144 if ((PVOID)(ULONG_PTR)Memory->Address < MmHighestUserAddress)
145 {
146 /* It is */
147 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
148 }
149 else
150 {
151 /* Check if it's session space */
152 if (MmIsSessionAddress((PVOID)(ULONG_PTR)Memory->Address))
153 {
154 /* It is */
155 Memory->AddressSpace = DBGKD_QUERY_MEMORY_SESSION;
156 }
157 else
158 {
159 /* Not session space but some other kernel memory */
160 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
161 }
162 }
163
164 /* Set flags */
165 Memory->Flags = DBGKD_QUERY_MEMORY_READ |
166 DBGKD_QUERY_MEMORY_WRITE |
167 DBGKD_QUERY_MEMORY_EXECUTE;
168 }
169 else
170 {
171 /* Invalid */
172 Status = STATUS_INVALID_PARAMETER;
173 }
174
175 /* Return structure */
176 State->ReturnStatus = Status;
177 Memory->Reserved = 0;
178
179 /* Build header */
180 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
181 Header.Buffer = (PCHAR)State;
182
183 /* Send the packet */
184 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
185 &Header,
186 NULL,
187 &KdpContext);
188 }
189
190 VOID
191 NTAPI
KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)192 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,
193 IN PSTRING Data,
194 IN PCONTEXT Context)
195 {
196 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory;
197 STRING Header;
198
199 /* TODO */
200 KdpDprintf("Memory Search support is unimplemented!\n");
201
202 /* Send a failure packet */
203 State->ReturnStatus = STATUS_UNSUCCESSFUL;
204 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
205 Header.Buffer = (PCHAR)State;
206 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
207 &Header,
208 NULL,
209 &KdpContext);
210 }
211
212 VOID
213 NTAPI
KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)214 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,
215 IN PSTRING Data,
216 IN PCONTEXT Context)
217 {
218 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory;
219 STRING Header;
220
221 /* TODO */
222 KdpDprintf("Memory Fill support is unimplemented!\n");
223
224 /* Send a failure packet */
225 State->ReturnStatus = STATUS_UNSUCCESSFUL;
226 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
227 Header.Buffer = (PCHAR)State;
228 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
229 &Header,
230 NULL,
231 &KdpContext);
232 }
233
234 VOID
235 NTAPI
KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)236 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
237 IN PSTRING Data,
238 IN PCONTEXT Context)
239 {
240 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
241 STRING Header;
242
243 /* Build header */
244 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
245 Header.Buffer = (PCHAR)State;
246 ASSERT(Data->Length == 0);
247
248 /* Create the breakpoint */
249 Breakpoint->BreakPointHandle =
250 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress);
251 if (!Breakpoint->BreakPointHandle)
252 {
253 /* We failed */
254 State->ReturnStatus = STATUS_UNSUCCESSFUL;
255 }
256 else
257 {
258 /* Success! */
259 State->ReturnStatus = STATUS_SUCCESS;
260 }
261
262 /* Send the packet */
263 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
264 &Header,
265 NULL,
266 &KdpContext);
267 }
268
269 VOID
270 NTAPI
KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)271 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
272 IN PSTRING Data,
273 IN PCONTEXT Context)
274 {
275 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
276 STRING Header;
277
278 /* Fill out the header */
279 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
280 Header.Buffer = (PCHAR)State;
281 ASSERT(Data->Length == 0);
282
283 /* Get the version block */
284 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
285 {
286 /* We're all good */
287 State->ReturnStatus = STATUS_SUCCESS;
288 }
289 else
290 {
291 /* We failed */
292 State->ReturnStatus = STATUS_UNSUCCESSFUL;
293 }
294
295 /* Send the packet */
296 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
297 &Header,
298 NULL,
299 &KdpContext);
300 }
301
302 NTSTATUS
303 NTAPI
KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)304 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
305 IN PSTRING Data,
306 IN PCONTEXT Context)
307 {
308 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
309 STRING Header;
310
311 /* TODO */
312 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n");
313
314 /* Send a failure packet */
315 State->ReturnStatus = STATUS_UNSUCCESSFUL;
316 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
317 Header.Buffer = (PCHAR)State;
318 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
319 &Header,
320 Data,
321 &KdpContext);
322 return STATUS_UNSUCCESSFUL;
323 }
324
325 VOID
326 NTAPI
KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)327 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
328 IN PSTRING Data,
329 IN PCONTEXT Context)
330 {
331 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
332 STRING Header;
333
334 /* TODO */
335 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n");
336
337 /* Send a failure packet */
338 State->ReturnStatus = STATUS_UNSUCCESSFUL;
339 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
340 Header.Buffer = (PCHAR)State;
341 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
342 &Header,
343 Data,
344 &KdpContext);
345 }
346
347 VOID
348 NTAPI
KdpWriteCustomBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)349 KdpWriteCustomBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
350 IN PSTRING Data,
351 IN PCONTEXT Context)
352 {
353 //PDBGKD_WRITE_CUSTOM_BREAKPOINT = &State->u.WriteCustomBreakpoint;
354 STRING Header;
355
356 /* Not supported */
357 KdpDprintf("Custom Breakpoint Write is unimplemented\n");
358
359 /* Send a failure packet */
360 State->ReturnStatus = STATUS_UNSUCCESSFUL;
361 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
362 Header.Buffer = (PCHAR)State;
363 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
364 &Header,
365 NULL,
366 &KdpContext);
367 }
368
369 VOID
370 NTAPI
DumpTraceData(IN PSTRING TraceData)371 DumpTraceData(IN PSTRING TraceData)
372 {
373 /* Update the buffer */
374 TraceDataBuffer[0] = TraceDataBufferPosition;
375
376 /* Setup the trace data */
377 TraceData->Length = (USHORT)(TraceDataBufferPosition * sizeof(ULONG));
378 TraceData->Buffer = (PCHAR)TraceDataBuffer;
379
380 /* Reset the buffer location */
381 TraceDataBufferPosition = 1;
382 }
383
384 VOID
385 NTAPI
KdpSetCommonState(IN ULONG NewState,IN PCONTEXT Context,IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange)386 KdpSetCommonState(IN ULONG NewState,
387 IN PCONTEXT Context,
388 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange)
389 {
390 ULONG InstructionCount;
391 BOOLEAN HadBreakpoints;
392
393 /* Setup common stuff available for all CPU architectures */
394 WaitStateChange->NewState = NewState;
395 WaitStateChange->ProcessorLevel = KeProcessorLevel;
396 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
397 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
398 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
399 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
400
401 /* Zero out the entire Control Report */
402 KdpZeroMemory(&WaitStateChange->AnyControlReport,
403 sizeof(DBGKD_ANY_CONTROL_REPORT));
404
405 /* Now copy the instruction stream and set the count */
406 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter,
407 &WaitStateChange->ControlReport.InstructionStream[0],
408 DBGKD_MAXSTREAM,
409 0,
410 MMDBG_COPY_UNSAFE,
411 &InstructionCount);
412 WaitStateChange->ControlReport.InstructionCount = (USHORT)InstructionCount;
413
414 /* Clear all the breakpoints in this region */
415 HadBreakpoints =
416 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
417 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
418 WaitStateChange->ControlReport.InstructionCount - 1));
419 if (HadBreakpoints)
420 {
421 /* Copy the instruction stream again, this time without breakpoints */
422 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter,
423 &WaitStateChange->ControlReport.InstructionStream[0],
424 InstructionCount,
425 0,
426 MMDBG_COPY_UNSAFE,
427 NULL);
428 }
429 }
430
431 VOID
432 NTAPI
KdpSysGetVersion(_Out_ PDBGKD_GET_VERSION64 Version)433 KdpSysGetVersion(
434 _Out_ PDBGKD_GET_VERSION64 Version)
435 {
436 /* Copy the version block */
437 KdpMoveMemory(Version,
438 &KdVersionBlock,
439 sizeof(DBGKD_GET_VERSION64));
440 }
441
442 VOID
443 NTAPI
KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)444 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
445 {
446 STRING Header;
447
448 /* Fill out the header */
449 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
450 Header.Buffer = (PCHAR)State;
451
452 /* Get the version block */
453 KdpSysGetVersion(&State->u.GetVersion64);
454
455 /* Fill out the state */
456 State->ApiNumber = DbgKdGetVersionApi;
457 State->ReturnStatus = STATUS_SUCCESS;
458
459 /* Send the packet */
460 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
461 &Header,
462 NULL,
463 &KdpContext);
464 }
465
466 VOID
467 NTAPI
KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)468 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
469 IN PSTRING Data,
470 IN PCONTEXT Context)
471 {
472 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
473 STRING Header;
474 ULONG Length = ReadMemory->TransferCount;
475
476 /* Setup the header */
477 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
478 Header.Buffer = (PCHAR)State;
479 ASSERT(Data->Length == 0);
480
481 /* Validate length */
482 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
483 {
484 /* Overflow, set it to maximum possible */
485 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
486 }
487
488 /* Do the read */
489 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress,
490 Data->Buffer,
491 Length,
492 0,
493 MMDBG_COPY_UNSAFE,
494 &Length);
495
496 /* Return the actual length read */
497 ReadMemory->ActualBytesRead = Length;
498 Data->Length = (USHORT)Length;
499
500 /* Send the packet */
501 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
502 &Header,
503 Data,
504 &KdpContext);
505 }
506
507 VOID
508 NTAPI
KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)509 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
510 IN PSTRING Data,
511 IN PCONTEXT Context)
512 {
513 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
514 STRING Header;
515
516 /* Setup the header */
517 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
518 Header.Buffer = (PCHAR)State;
519
520 /* Do the write */
521 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress,
522 Data->Buffer,
523 Data->Length,
524 0,
525 MMDBG_COPY_UNSAFE |
526 MMDBG_COPY_WRITE,
527 &WriteMemory->ActualBytesWritten);
528
529 /* Send the packet */
530 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
531 &Header,
532 NULL,
533 &KdpContext);
534 }
535
536 VOID
537 NTAPI
KdpReadPhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)538 KdpReadPhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State,
539 IN PSTRING Data,
540 IN PCONTEXT Context)
541 {
542 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
543 STRING Header;
544 ULONG Length = ReadMemory->TransferCount;
545 ULONG Flags, CacheFlags;
546
547 /* Setup the header */
548 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
549 Header.Buffer = (PCHAR)State;
550 ASSERT(Data->Length == 0);
551
552 /* Validate length */
553 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
554 {
555 /* Overflow, set it to maximum possible */
556 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
557 }
558
559 /* Start with the default flags */
560 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_PHYSICAL;
561
562 /* Get the caching flags and check if a type is specified */
563 CacheFlags = ReadMemory->ActualBytesRead;
564 if (CacheFlags == DBGKD_CACHING_CACHED)
565 {
566 /* Cached */
567 Flags |= MMDBG_COPY_CACHED;
568 }
569 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
570 {
571 /* Uncached */
572 Flags |= MMDBG_COPY_UNCACHED;
573 }
574 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED)
575 {
576 /* Write Combined */
577 Flags |= MMDBG_COPY_WRITE_COMBINED;
578 }
579
580 /* Do the read */
581 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress,
582 Data->Buffer,
583 Length,
584 0,
585 Flags,
586 &Length);
587
588 /* Return the actual length read */
589 ReadMemory->ActualBytesRead = Length;
590 Data->Length = (USHORT)Length;
591
592 /* Send the packet */
593 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
594 &Header,
595 Data,
596 &KdpContext);
597 }
598
599 VOID
600 NTAPI
KdpWritePhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)601 KdpWritePhysicalMemory(IN PDBGKD_MANIPULATE_STATE64 State,
602 IN PSTRING Data,
603 IN PCONTEXT Context)
604 {
605 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
606 STRING Header;
607 ULONG Flags, CacheFlags;
608
609 /* Setup the header */
610 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
611 Header.Buffer = (PCHAR)State;
612
613 /* Start with the default flags */
614 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE | MMDBG_COPY_PHYSICAL;
615
616 /* Get the caching flags and check if a type is specified */
617 CacheFlags = WriteMemory->ActualBytesWritten;
618 if (CacheFlags == DBGKD_CACHING_CACHED)
619 {
620 /* Cached */
621 Flags |= MMDBG_COPY_CACHED;
622 }
623 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
624 {
625 /* Uncached */
626 Flags |= MMDBG_COPY_UNCACHED;
627 }
628 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED)
629 {
630 /* Write Combined */
631 Flags |= MMDBG_COPY_WRITE_COMBINED;
632 }
633
634 /* Do the write */
635 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress,
636 Data->Buffer,
637 Data->Length,
638 0,
639 Flags,
640 &WriteMemory->ActualBytesWritten);
641
642 /* Send the packet */
643 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
644 &Header,
645 NULL,
646 &KdpContext);
647 }
648
649 VOID
650 NTAPI
KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)651 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
652 IN PSTRING Data,
653 IN PCONTEXT Context)
654 {
655 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
656 STRING Header;
657 ULONG Length;
658
659 /* Setup the header */
660 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
661 Header.Buffer = (PCHAR)State;
662 ASSERT(Data->Length == 0);
663
664 /* Check the length requested */
665 Length = ReadMemory->TransferCount;
666 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
667 {
668 /* Use maximum allowed */
669 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
670 }
671
672 /* Call the internal routine */
673 State->ReturnStatus = KdpSysReadControlSpace(State->Processor,
674 ReadMemory->TargetBaseAddress,
675 Data->Buffer,
676 Length,
677 &Length);
678
679 /* Return the actual length read */
680 ReadMemory->ActualBytesRead = Length;
681 Data->Length = (USHORT)Length;
682
683 /* Send the reply */
684 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
685 &Header,
686 Data,
687 &KdpContext);
688 }
689
690 VOID
691 NTAPI
KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)692 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
693 IN PSTRING Data,
694 IN PCONTEXT Context)
695 {
696 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
697 STRING Header;
698
699 /* Setup the header */
700 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
701 Header.Buffer = (PCHAR)State;
702
703 /* Call the internal routine */
704 State->ReturnStatus = KdpSysWriteControlSpace(State->Processor,
705 WriteMemory->TargetBaseAddress,
706 Data->Buffer,
707 Data->Length,
708 &WriteMemory->ActualBytesWritten);
709
710 /* Send the reply */
711 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
712 &Header,
713 Data,
714 &KdpContext);
715 }
716
717 VOID
718 NTAPI
KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)719 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
720 IN PSTRING Data,
721 IN PCONTEXT Context)
722 {
723 STRING Header;
724 PCONTEXT TargetContext;
725
726 /* Setup the header */
727 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
728 Header.Buffer = (PCHAR)State;
729 ASSERT(Data->Length == 0);
730
731 /* Make sure that this is a valid request */
732 if (State->Processor < KeNumberProcessors)
733 {
734 /* Check if the request is for this CPU */
735 if (State->Processor == KeGetCurrentPrcb()->Number)
736 {
737 /* We're just copying our own context */
738 TargetContext = Context;
739 }
740 else
741 {
742 /* Get the context from the PRCB array */
743 TargetContext = &KiProcessorBlock[State->Processor]->
744 ProcessorState.ContextFrame;
745 }
746
747 /* Copy it over to the debugger */
748 KdpMoveMemory(Data->Buffer,
749 TargetContext,
750 sizeof(CONTEXT));
751 Data->Length = sizeof(CONTEXT);
752
753 /* Let the debugger set the context now */
754 KdpContextSent = TRUE;
755
756 /* Finish up */
757 State->ReturnStatus = STATUS_SUCCESS;
758 }
759 else
760 {
761 /* Invalid request */
762 State->ReturnStatus = STATUS_UNSUCCESSFUL;
763 }
764
765 /* Send the reply */
766 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
767 &Header,
768 Data,
769 &KdpContext);
770 }
771
772 VOID
773 NTAPI
KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)774 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
775 IN PSTRING Data,
776 IN PCONTEXT Context)
777 {
778 STRING Header;
779 PCONTEXT TargetContext;
780
781 /* Setup the header */
782 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
783 Header.Buffer = (PCHAR)State;
784 ASSERT(Data->Length == sizeof(CONTEXT));
785
786 /* Make sure that this is a valid request */
787 if ((State->Processor < KeNumberProcessors) &&
788 (KdpContextSent))
789 {
790 /* Check if the request is for this CPU */
791 if (State->Processor == KeGetCurrentPrcb()->Number)
792 {
793 /* We're just copying our own context */
794 TargetContext = Context;
795 }
796 else
797 {
798 /* Get the context from the PRCB array */
799 TargetContext = &KiProcessorBlock[State->Processor]->
800 ProcessorState.ContextFrame;
801 }
802
803 /* Copy the new context to it */
804 KdpMoveMemory(TargetContext,
805 Data->Buffer,
806 sizeof(CONTEXT));
807
808 /* Finish up */
809 State->ReturnStatus = STATUS_SUCCESS;
810 }
811 else
812 {
813 /* Invalid request */
814 State->ReturnStatus = STATUS_UNSUCCESSFUL;
815 }
816
817 /* Send the reply */
818 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
819 &Header,
820 NULL,
821 &KdpContext);
822 }
823
824 VOID
825 NTAPI
KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)826 KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
827 IN PSTRING Data,
828 IN PCONTEXT Context)
829 {
830 STRING Header;
831 PDBGKD_CONTEXT_EX ContextEx;
832 PCONTEXT TargetContext;
833 ASSERT(Data->Length == 0);
834
835 /* Get our struct */
836 ContextEx = &State->u.ContextEx;
837
838 /* Set up the header */
839 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
840 Header.Buffer = (PCHAR)State;
841
842 /* Make sure that this is a valid request */
843 if ((State->Processor < KeNumberProcessors) &&
844 (ContextEx->Offset + ContextEx->ByteCount) <= sizeof(CONTEXT))
845 {
846 /* Check if the request is for this CPU */
847 if (State->Processor == KeGetCurrentPrcb()->Number)
848 {
849 /* We're just copying our own context */
850 TargetContext = Context;
851 }
852 else
853 {
854 /* Get the context from the PRCB array */
855 TargetContext = &KiProcessorBlock[State->Processor]->
856 ProcessorState.ContextFrame;
857 }
858
859 /* Copy what is requested */
860 KdpMoveMemory(Data->Buffer,
861 (PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
862 ContextEx->ByteCount);
863
864 /* KD copies all */
865 Data->Length = ContextEx->BytesCopied = ContextEx->ByteCount;
866
867 /* Let the debugger set the context now */
868 KdpContextSent = TRUE;
869
870 /* Finish up */
871 State->ReturnStatus = STATUS_SUCCESS;
872 }
873 else
874 {
875 /* Invalid request */
876 ContextEx->BytesCopied = 0;
877 State->ReturnStatus = STATUS_UNSUCCESSFUL;
878 }
879
880 /* Send the reply */
881 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
882 &Header,
883 Data,
884 &KdpContext);
885 }
886
887 VOID
888 NTAPI
KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)889 KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
890 IN PSTRING Data,
891 IN PCONTEXT Context)
892 {
893 STRING Header;
894 PDBGKD_CONTEXT_EX ContextEx;
895 PCONTEXT TargetContext;
896
897 /* Get our struct */
898 ContextEx = &State->u.ContextEx;
899 ASSERT(Data->Length == ContextEx->ByteCount);
900
901 /* Set up the header */
902 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
903 Header.Buffer = (PCHAR)State;
904
905 /* Make sure that this is a valid request */
906 if ((State->Processor < KeNumberProcessors) &&
907 ((ContextEx->Offset + ContextEx->ByteCount) <= sizeof(CONTEXT)) &&
908 (KdpContextSent))
909 {
910 /* Check if the request is for this CPU */
911 if (State->Processor == KeGetCurrentPrcb()->Number)
912 {
913 /* We're just copying our own context */
914 TargetContext = Context;
915 }
916 else
917 {
918 /* Get the context from the PRCB array */
919 TargetContext = &KiProcessorBlock[State->Processor]->
920 ProcessorState.ContextFrame;
921 }
922
923 /* Copy what is requested */
924 KdpMoveMemory((PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
925 Data->Buffer,
926 ContextEx->ByteCount);
927
928 /* KD copies all */
929 ContextEx->BytesCopied = ContextEx->ByteCount;
930
931 /* Finish up */
932 State->ReturnStatus = STATUS_SUCCESS;
933 }
934 else
935 {
936 /* Invalid request */
937 ContextEx->BytesCopied = 0;
938 State->ReturnStatus = STATUS_UNSUCCESSFUL;
939 }
940
941 /* Send the reply */
942 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
943 &Header,
944 NULL,
945 &KdpContext);
946 }
947
948 VOID
949 NTAPI
KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)950 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)
951 {
952 /* Crash with the special code */
953 KeBugCheck(MANUALLY_INITIATED_CRASH);
954 }
955
956 VOID
957 NTAPI
KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)958 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
959 IN PSTRING Data,
960 IN PCONTEXT Context)
961 {
962 STRING Header;
963 PDBGKD_READ_WRITE_MSR ReadMsr = &State->u.ReadWriteMsr;
964 ULARGE_INTEGER MsrValue;
965
966 /* Setup the header */
967 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
968 Header.Buffer = (PCHAR)State;
969 ASSERT(Data->Length == 0);
970
971 /* Call the internal routine */
972 State->ReturnStatus = KdpSysReadMsr(ReadMsr->Msr, &MsrValue.QuadPart);
973
974 /* Return the data */
975 ReadMsr->DataValueLow = MsrValue.LowPart;
976 ReadMsr->DataValueHigh = MsrValue.HighPart;
977
978 /* Send the reply */
979 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
980 &Header,
981 NULL,
982 &KdpContext);
983 }
984
985 VOID
986 NTAPI
KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)987 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
988 IN PSTRING Data,
989 IN PCONTEXT Context)
990 {
991 STRING Header;
992 PDBGKD_READ_WRITE_MSR WriteMsr = &State->u.ReadWriteMsr;
993 ULARGE_INTEGER MsrValue;
994
995 /* Setup the header */
996 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
997 Header.Buffer = (PCHAR)State;
998 ASSERT(Data->Length == 0);
999
1000 /* Call the internal routine */
1001 MsrValue.LowPart = WriteMsr->DataValueLow;
1002 MsrValue.HighPart = WriteMsr->DataValueHigh;
1003 State->ReturnStatus = KdpSysWriteMsr(WriteMsr->Msr, &MsrValue.QuadPart);
1004
1005 /* Send the reply */
1006 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1007 &Header,
1008 NULL,
1009 &KdpContext);
1010 }
1011
1012 VOID
1013 NTAPI
KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1014 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
1015 IN PSTRING Data,
1016 IN PCONTEXT Context)
1017 {
1018 STRING Header;
1019 PDBGKD_GET_SET_BUS_DATA GetBusData = &State->u.GetSetBusData;
1020 ULONG Length;
1021
1022 /* Setup the header */
1023 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1024 Header.Buffer = (PCHAR)State;
1025 ASSERT(Data->Length == 0);
1026
1027 /* Check the length requested */
1028 Length = GetBusData->Length;
1029 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
1030 {
1031 /* Use maximum allowed */
1032 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
1033 }
1034
1035 /* Call the internal routine */
1036 State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType,
1037 GetBusData->BusNumber,
1038 GetBusData->SlotNumber,
1039 GetBusData->Offset,
1040 Data->Buffer,
1041 Length,
1042 &Length);
1043
1044 /* Return the actual length read */
1045 GetBusData->Length = Length;
1046 Data->Length = (USHORT)Length;
1047
1048 /* Send the reply */
1049 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1050 &Header,
1051 Data,
1052 &KdpContext);
1053 }
1054
1055 VOID
1056 NTAPI
KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1057 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
1058 IN PSTRING Data,
1059 IN PCONTEXT Context)
1060 {
1061 STRING Header;
1062 PDBGKD_GET_SET_BUS_DATA SetBusData = &State->u.GetSetBusData;
1063
1064 /* Setup the header */
1065 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1066 Header.Buffer = (PCHAR)State;
1067
1068 /* Call the internal routine */
1069 State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType,
1070 SetBusData->BusNumber,
1071 SetBusData->SlotNumber,
1072 SetBusData->Offset,
1073 Data->Buffer,
1074 SetBusData->Length,
1075 &SetBusData->Length);
1076
1077 /* Send the reply */
1078 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1079 &Header,
1080 NULL,
1081 &KdpContext);
1082 }
1083
1084 VOID
1085 NTAPI
KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1086 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
1087 IN PSTRING Data,
1088 IN PCONTEXT Context)
1089 {
1090 STRING Header;
1091 PDBGKD_READ_WRITE_IO64 ReadIo = &State->u.ReadWriteIo;
1092
1093 /* Setup the header */
1094 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1095 Header.Buffer = (PCHAR)State;
1096 ASSERT(Data->Length == 0);
1097
1098 /*
1099 * Clear the value so 1 or 2 byte reads
1100 * don't leave the higher bits unmodified
1101 */
1102 ReadIo->DataValue = 0;
1103
1104 /* Call the internal routine */
1105 State->ReturnStatus = KdpSysReadIoSpace(Isa,
1106 0,
1107 1,
1108 ReadIo->IoAddress,
1109 &ReadIo->DataValue,
1110 ReadIo->DataSize,
1111 &ReadIo->DataSize);
1112
1113 /* Send the reply */
1114 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1115 &Header,
1116 NULL,
1117 &KdpContext);
1118 }
1119
1120 VOID
1121 NTAPI
KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1122 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
1123 IN PSTRING Data,
1124 IN PCONTEXT Context)
1125 {
1126 STRING Header;
1127 PDBGKD_READ_WRITE_IO64 WriteIo = &State->u.ReadWriteIo;
1128
1129 /* Setup the header */
1130 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1131 Header.Buffer = (PCHAR)State;
1132 ASSERT(Data->Length == 0);
1133
1134 /* Call the internal routine */
1135 State->ReturnStatus = KdpSysWriteIoSpace(Isa,
1136 0,
1137 1,
1138 WriteIo->IoAddress,
1139 &WriteIo->DataValue,
1140 WriteIo->DataSize,
1141 &WriteIo->DataSize);
1142
1143 /* Send the reply */
1144 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1145 &Header,
1146 NULL,
1147 &KdpContext);
1148 }
1149
1150 VOID
1151 NTAPI
KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1152 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
1153 IN PSTRING Data,
1154 IN PCONTEXT Context)
1155 {
1156 STRING Header;
1157 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended = &State->u.
1158 ReadWriteIoExtended;
1159
1160 /* Setup the header */
1161 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1162 Header.Buffer = (PCHAR)State;
1163 ASSERT(Data->Length == 0);
1164
1165 /*
1166 * Clear the value so 1 or 2 byte reads
1167 * don't leave the higher bits unmodified
1168 */
1169 ReadIoExtended->DataValue = 0;
1170
1171 /* Call the internal routine */
1172 State->ReturnStatus = KdpSysReadIoSpace(ReadIoExtended->InterfaceType,
1173 ReadIoExtended->BusNumber,
1174 ReadIoExtended->AddressSpace,
1175 ReadIoExtended->IoAddress,
1176 &ReadIoExtended->DataValue,
1177 ReadIoExtended->DataSize,
1178 &ReadIoExtended->DataSize);
1179
1180 /* Send the reply */
1181 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1182 &Header,
1183 NULL,
1184 &KdpContext);
1185 }
1186
1187 VOID
1188 NTAPI
KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,IN PSTRING Data,IN PCONTEXT Context)1189 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
1190 IN PSTRING Data,
1191 IN PCONTEXT Context)
1192 {
1193 STRING Header;
1194 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended = &State->u.
1195 ReadWriteIoExtended;
1196
1197 /* Setup the header */
1198 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1199 Header.Buffer = (PCHAR)State;
1200 ASSERT(Data->Length == 0);
1201
1202 /* Call the internal routine */
1203 State->ReturnStatus = KdpSysWriteIoSpace(WriteIoExtended->InterfaceType,
1204 WriteIoExtended->BusNumber,
1205 WriteIoExtended->AddressSpace,
1206 WriteIoExtended->IoAddress,
1207 &WriteIoExtended->DataValue,
1208 WriteIoExtended->DataSize,
1209 &WriteIoExtended->DataSize);
1210
1211 /* Send the reply */
1212 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1213 &Header,
1214 NULL,
1215 &KdpContext);
1216 }
1217
1218 VOID
1219 NTAPI
KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State)1220 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State)
1221 {
1222 STRING Header;
1223
1224 /* Setup the header */
1225 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1226 Header.Buffer = (PCHAR)State;
1227
1228 /* Call the internal routine */
1229 State->ReturnStatus = KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE);
1230
1231 /* Send the reply */
1232 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1233 &Header,
1234 NULL,
1235 &KdpContext);
1236 }
1237
1238 VOID
1239 NTAPI
KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State)1240 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State)
1241 {
1242 STRING Header;
1243
1244 /* Set failure */
1245 State->ReturnStatus = STATUS_UNSUCCESSFUL;
1246
1247 /* Setup the packet */
1248 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1249 Header.Buffer = (PCHAR)State;
1250
1251 /* Send it */
1252 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1253 &Header,
1254 NULL,
1255 &KdpContext);
1256 }
1257
1258 static
1259 KCONTINUE_STATUS
KdpSwitchProcessor(_In_ USHORT ProcessorIndex)1260 KdpSwitchProcessor(
1261 _In_ USHORT ProcessorIndex)
1262 {
1263 /* Make sure that the processor index is valid */
1264 if (ProcessorIndex >= KeNumberProcessors)
1265 {
1266 KdpDprintf("%u is not a valid processor number\n", ProcessorIndex);
1267 return ContinueProcessorReselected;
1268 }
1269
1270 /* If the new processor is the current one, there is nothing to do */
1271 if (ProcessorIndex == KeGetCurrentProcessorNumber())
1272 {
1273 return ContinueProcessorReselected;
1274 }
1275
1276 /* Call the architecture specific Ke routine */
1277 return KxSwitchKdProcessor(ProcessorIndex);
1278 }
1279
1280 KCONTINUE_STATUS
1281 NTAPI
KdpSendWaitContinue(IN ULONG PacketType,IN PSTRING SendHeader,IN PSTRING SendData OPTIONAL,IN OUT PCONTEXT Context)1282 KdpSendWaitContinue(IN ULONG PacketType,
1283 IN PSTRING SendHeader,
1284 IN PSTRING SendData OPTIONAL,
1285 IN OUT PCONTEXT Context)
1286 {
1287 STRING Data, Header;
1288 DBGKD_MANIPULATE_STATE64 ManipulateState;
1289 ULONG Length;
1290 KDSTATUS RecvCode;
1291
1292 /* Setup the Manipulate State structure */
1293 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
1294 Header.Buffer = (PCHAR)&ManipulateState;
1295 Data.MaximumLength = sizeof(KdpMessageBuffer);
1296 Data.Buffer = KdpMessageBuffer;
1297
1298 /*
1299 * Reset the context state to ensure the debugger has received
1300 * the current context before it sets it.
1301 */
1302 KdpContextSent = FALSE;
1303
1304 SendPacket:
1305 /* Send the Packet */
1306 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
1307
1308 /* If the debugger isn't present anymore, just return success */
1309 if (KdDebuggerNotPresent) return ContinueSuccess;
1310
1311 /* Main processing Loop */
1312 for (;;)
1313 {
1314 /* Receive Loop */
1315 do
1316 {
1317 /* Wait to get a reply to our packet */
1318 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1319 &Header,
1320 &Data,
1321 &Length,
1322 &KdpContext);
1323
1324 /* If we got a resend request, do it */
1325 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
1326 } while (RecvCode == KdPacketTimedOut);
1327
1328 /* Now check what API we got */
1329 switch (ManipulateState.ApiNumber)
1330 {
1331 case DbgKdReadVirtualMemoryApi:
1332
1333 /* Read virtual memory */
1334 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
1335 break;
1336
1337 case DbgKdWriteVirtualMemoryApi:
1338
1339 /* Write virtual memory */
1340 KdpWriteVirtualMemory(&ManipulateState, &Data, Context);
1341 break;
1342
1343 case DbgKdGetContextApi:
1344
1345 /* Get the current context */
1346 KdpGetContext(&ManipulateState, &Data, Context);
1347 break;
1348
1349 case DbgKdSetContextApi:
1350
1351 /* Set a new context */
1352 KdpSetContext(&ManipulateState, &Data, Context);
1353 break;
1354
1355 case DbgKdWriteBreakPointApi:
1356
1357 /* Write the breakpoint */
1358 KdpWriteBreakpoint(&ManipulateState, &Data, Context);
1359 break;
1360
1361 case DbgKdRestoreBreakPointApi:
1362
1363 /* Restore the breakpoint */
1364 KdpRestoreBreakpoint(&ManipulateState, &Data, Context);
1365 break;
1366
1367 case DbgKdContinueApi:
1368
1369 /* Simply continue */
1370 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);
1371
1372 case DbgKdReadControlSpaceApi:
1373
1374 /* Read control space */
1375 KdpReadControlSpace(&ManipulateState, &Data, Context);
1376 break;
1377
1378 case DbgKdWriteControlSpaceApi:
1379
1380 /* Write control space */
1381 KdpWriteControlSpace(&ManipulateState, &Data, Context);
1382 break;
1383
1384 case DbgKdReadIoSpaceApi:
1385
1386 /* Read I/O Space */
1387 KdpReadIoSpace(&ManipulateState, &Data, Context);
1388 break;
1389
1390 case DbgKdWriteIoSpaceApi:
1391
1392 /* Write I/O Space */
1393 KdpWriteIoSpace(&ManipulateState, &Data, Context);
1394 break;
1395
1396 case DbgKdRebootApi:
1397
1398 /* Reboot the system */
1399 HalReturnToFirmware(HalRebootRoutine);
1400 break;
1401
1402 case DbgKdContinueApi2:
1403
1404 /* Check if caller reports success */
1405 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))
1406 {
1407 /* Update the state */
1408 KdpGetStateChange(&ManipulateState, Context);
1409 return ContinueSuccess;
1410 }
1411 else
1412 {
1413 /* Return an error */
1414 return ContinueError;
1415 }
1416
1417 case DbgKdReadPhysicalMemoryApi:
1418
1419 /* Read physical memory */
1420 KdpReadPhysicalMemory(&ManipulateState, &Data, Context);
1421 break;
1422
1423 case DbgKdWritePhysicalMemoryApi:
1424
1425 /* Write physical memory */
1426 KdpWritePhysicalMemory(&ManipulateState, &Data, Context);
1427 break;
1428
1429 case DbgKdQuerySpecialCallsApi:
1430 case DbgKdSetSpecialCallApi:
1431 case DbgKdClearSpecialCallsApi:
1432
1433 /* TODO */
1434 KdpDprintf("Special Call support is unimplemented!\n");
1435 KdpNotSupported(&ManipulateState);
1436 break;
1437
1438 case DbgKdSetInternalBreakPointApi:
1439 case DbgKdGetInternalBreakPointApi:
1440
1441 /* TODO */
1442 KdpDprintf("Internal Breakpoint support is unimplemented!\n");
1443 KdpNotSupported(&ManipulateState);
1444 break;
1445
1446 case DbgKdReadIoSpaceExtendedApi:
1447
1448 /* Read I/O Space */
1449 KdpReadIoSpaceExtended(&ManipulateState, &Data, Context);
1450 break;
1451
1452 case DbgKdWriteIoSpaceExtendedApi:
1453
1454 /* Write I/O Space */
1455 KdpWriteIoSpaceExtended(&ManipulateState, &Data, Context);
1456 break;
1457
1458 case DbgKdGetVersionApi:
1459
1460 /* Get version data */
1461 KdpGetVersion(&ManipulateState);
1462 break;
1463
1464 case DbgKdWriteBreakPointExApi:
1465
1466 /* Write the breakpoint and check if it failed */
1467 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState,
1468 &Data,
1469 Context)))
1470 {
1471 /* Return an error */
1472 return ContinueError;
1473 }
1474 break;
1475
1476 case DbgKdRestoreBreakPointExApi:
1477
1478 /* Restore the breakpoint */
1479 KdpRestoreBreakPointEx(&ManipulateState, &Data, Context);
1480 break;
1481
1482 case DbgKdCauseBugCheckApi:
1483
1484 /* Crash the system */
1485 KdpCauseBugCheck(&ManipulateState);
1486 break;
1487
1488 case DbgKdSwitchProcessor:
1489
1490 /* Switch the processor and return */
1491 return KdpSwitchProcessor(ManipulateState.Processor);
1492
1493 case DbgKdPageInApi:
1494
1495 /* This API, introduced in NT4, has been obsoleted in NT5. It is
1496 * replaced by ExpDebuggerPageIn support in ExpDebuggerWorker(). */
1497 KdpDprintf("DbgKdPageInApi is obsolete!\n");
1498 KdpNotSupported(&ManipulateState);
1499 break;
1500
1501 case DbgKdReadMachineSpecificRegister:
1502
1503 /* Read from the specified MSR */
1504 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context);
1505 break;
1506
1507 case DbgKdWriteMachineSpecificRegister:
1508
1509 /* Write to the specified MSR */
1510 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context);
1511 break;
1512
1513 case DbgKdSearchMemoryApi:
1514
1515 /* Search memory */
1516 KdpSearchMemory(&ManipulateState, &Data, Context);
1517 break;
1518
1519 case DbgKdGetBusDataApi:
1520
1521 /* Read from the bus */
1522 KdpGetBusData(&ManipulateState, &Data, Context);
1523 break;
1524
1525 case DbgKdSetBusDataApi:
1526
1527 /* Write to the bus */
1528 KdpSetBusData(&ManipulateState, &Data, Context);
1529 break;
1530
1531 case DbgKdCheckLowMemoryApi:
1532
1533 /* Check for memory corruption in the lower 4 GB */
1534 KdpCheckLowMemory(&ManipulateState);
1535 break;
1536
1537 case DbgKdClearAllInternalBreakpointsApi:
1538
1539 /* Just clear the counter */
1540 KdpNumInternalBreakpoints = 0;
1541 break;
1542
1543 case DbgKdFillMemoryApi:
1544
1545 /* Fill memory */
1546 KdpFillMemory(&ManipulateState, &Data, Context);
1547 break;
1548
1549 case DbgKdQueryMemoryApi:
1550
1551 /* Query memory */
1552 KdpQueryMemory(&ManipulateState, Context);
1553 break;
1554
1555 case DbgKdSwitchPartition:
1556
1557 /* TODO */
1558 KdpDprintf("Partition Switch support is unimplemented!\n");
1559 KdpNotSupported(&ManipulateState);
1560 break;
1561
1562 case DbgKdWriteCustomBreakpointApi:
1563
1564 /* Write the customized breakpoint */
1565 KdpWriteCustomBreakpoint(&ManipulateState, &Data, Context);
1566 break;
1567
1568 case DbgKdGetContextExApi:
1569
1570 /* Extended Context Get */
1571 KdpGetContextEx(&ManipulateState, &Data, Context);
1572 break;
1573
1574 case DbgKdSetContextExApi:
1575
1576 /* Extended Context Set */
1577 KdpSetContextEx(&ManipulateState, &Data, Context);
1578 break;
1579
1580 /* Unsupported Messages */
1581 default:
1582
1583 /* Send warning */
1584 KdpDprintf("Received Unrecognized API 0x%lx\n", ManipulateState.ApiNumber);
1585
1586 /* Setup an empty message, with failure */
1587 Data.Length = 0;
1588 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
1589
1590 /* Send it */
1591 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1592 &Header,
1593 &Data,
1594 &KdpContext);
1595 break;
1596 }
1597 }
1598 }
1599
1600 VOID
1601 NTAPI
KdpReportLoadSymbolsStateChange(IN PSTRING PathName,IN PKD_SYMBOLS_INFO SymbolInfo,IN BOOLEAN Unload,IN OUT PCONTEXT Context)1602 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
1603 IN PKD_SYMBOLS_INFO SymbolInfo,
1604 IN BOOLEAN Unload,
1605 IN OUT PCONTEXT Context)
1606 {
1607 PSTRING ExtraData;
1608 STRING Data, Header;
1609 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1610 ULONG PathNameLength;
1611 KCONTINUE_STATUS Status;
1612
1613 /* Start wait loop */
1614 do
1615 {
1616 /* Build the architecture common parts of the message */
1617 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
1618 Context,
1619 &WaitStateChange);
1620
1621 /* Now finish creating the structure */
1622 KdpSetContextState(&WaitStateChange, Context);
1623
1624 /* Fill out load data */
1625 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
1626 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll;
1627 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
1628 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
1629 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
1630
1631 /* Check if we have a path name */
1632 if (PathName)
1633 {
1634 /* Copy it to the path buffer */
1635 KdpCopyMemoryChunks((ULONG_PTR)PathName->Buffer,
1636 KdpPathBuffer,
1637 PathName->Length,
1638 0,
1639 MMDBG_COPY_UNSAFE,
1640 &PathNameLength);
1641
1642 /* Null terminate */
1643 KdpPathBuffer[PathNameLength++] = ANSI_NULL;
1644
1645 /* Set the path length */
1646 WaitStateChange.u.LoadSymbols.PathNameLength = PathNameLength;
1647
1648 /* Set up the data */
1649 Data.Buffer = KdpPathBuffer;
1650 Data.Length = (USHORT)PathNameLength;
1651 ExtraData = &Data;
1652 }
1653 else
1654 {
1655 /* No name */
1656 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
1657 ExtraData = NULL;
1658 }
1659
1660 /* Setup the header */
1661 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1662 Header.Buffer = (PCHAR)&WaitStateChange;
1663
1664 /* Send the packet */
1665 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1666 &Header,
1667 ExtraData,
1668 Context);
1669 } while (Status == ContinueProcessorReselected);
1670 }
1671
1672 VOID
1673 NTAPI
KdpReportCommandStringStateChange(IN PSTRING NameString,IN PSTRING CommandString,IN OUT PCONTEXT Context)1674 KdpReportCommandStringStateChange(IN PSTRING NameString,
1675 IN PSTRING CommandString,
1676 IN OUT PCONTEXT Context)
1677 {
1678 STRING Header, Data;
1679 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1680 ULONG Length, ActualLength, TotalLength;
1681 KCONTINUE_STATUS Status;
1682
1683 /* Start wait loop */
1684 do
1685 {
1686 /* Build the architecture common parts of the message */
1687 KdpSetCommonState(DbgKdCommandStringStateChange,
1688 Context,
1689 &WaitStateChange);
1690
1691 /* Set the context */
1692 KdpSetContextState(&WaitStateChange, Context);
1693
1694 /* Clear the command string structure */
1695 KdpZeroMemory(&WaitStateChange.u.CommandString,
1696 sizeof(DBGKD_COMMAND_STRING));
1697
1698 /* Normalize name string to max */
1699 Length = min(128 - 1, NameString->Length);
1700
1701 /* Copy it to the message buffer */
1702 KdpCopyMemoryChunks((ULONG_PTR)NameString->Buffer,
1703 KdpMessageBuffer,
1704 Length,
1705 0,
1706 MMDBG_COPY_UNSAFE,
1707 &ActualLength);
1708
1709 /* Null terminate and calculate the total length */
1710 TotalLength = ActualLength;
1711 KdpMessageBuffer[TotalLength++] = ANSI_NULL;
1712
1713 /* Check if the command string is too long */
1714 Length = CommandString->Length;
1715 if (Length > (PACKET_MAX_SIZE -
1716 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength))
1717 {
1718 /* Use maximum possible size */
1719 Length = (PACKET_MAX_SIZE -
1720 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength);
1721 }
1722
1723 /* Copy it to the message buffer */
1724 KdpCopyMemoryChunks((ULONG_PTR)CommandString->Buffer,
1725 KdpMessageBuffer + TotalLength,
1726 Length,
1727 0,
1728 MMDBG_COPY_UNSAFE,
1729 &ActualLength);
1730
1731 /* Null terminate and calculate the total length */
1732 TotalLength += ActualLength;
1733 KdpMessageBuffer[TotalLength++] = ANSI_NULL;
1734
1735 /* Now set up the header and the data */
1736 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1737 Header.Buffer = (PCHAR)&WaitStateChange;
1738 Data.Length = (USHORT)TotalLength;
1739 Data.Buffer = KdpMessageBuffer;
1740
1741 /* Send State Change packet and wait for a reply */
1742 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1743 &Header,
1744 &Data,
1745 Context);
1746 } while (Status == ContinueProcessorReselected);
1747 }
1748
1749 BOOLEAN
1750 NTAPI
KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,IN OUT PCONTEXT Context,IN BOOLEAN SecondChanceException)1751 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
1752 IN OUT PCONTEXT Context,
1753 IN BOOLEAN SecondChanceException)
1754 {
1755 STRING Header, Data;
1756 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1757 KCONTINUE_STATUS Status;
1758
1759 /* Start report loop */
1760 do
1761 {
1762 /* Build the architecture common parts of the message */
1763 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
1764
1765 #if !defined(_WIN64)
1766
1767 /* Convert it and copy it over */
1768 ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
1769 &WaitStateChange.u.Exception.ExceptionRecord);
1770
1771 #else
1772
1773 /* Just copy it directly, no need to convert */
1774 KdpMoveMemory(&WaitStateChange.u.Exception.ExceptionRecord,
1775 ExceptionRecord,
1776 sizeof(EXCEPTION_RECORD));
1777
1778 #endif
1779
1780 /* Set the First Chance flag */
1781 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
1782
1783 /* Now finish creating the structure */
1784 KdpSetContextState(&WaitStateChange, Context);
1785
1786 /* Setup the actual header to send to KD */
1787 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1788 Header.Buffer = (PCHAR)&WaitStateChange;
1789
1790 /* Setup the trace data */
1791 DumpTraceData(&Data);
1792
1793 /* Send State Change packet and wait for a reply */
1794 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1795 &Header,
1796 &Data,
1797 Context);
1798 } while (Status == ContinueProcessorReselected);
1799
1800 /* Return */
1801 return Status;
1802 }
1803
1804 KCONTINUE_STATUS
1805 NTAPI
KdReportProcessorChange(VOID)1806 KdReportProcessorChange(
1807 VOID)
1808 {
1809 PKPRCB CurrentPrcb = KeGetCurrentPrcb();
1810 PCONTEXT ContextRecord = &CurrentPrcb->ProcessorState.ContextFrame;
1811 EXCEPTION_RECORD ExceptionRecord = {0};
1812 KCONTINUE_STATUS Status;
1813
1814 /* Save the port data */
1815 KdSave(FALSE);
1816
1817 ExceptionRecord.ExceptionAddress = (PVOID)KeGetContextPc(ContextRecord);
1818 ExceptionRecord.ExceptionCode = STATUS_WAKE_SYSTEM_DEBUGGER;
1819
1820 /* Report the new state */
1821 Status = KdpReportExceptionStateChange(&ExceptionRecord,
1822 ContextRecord,
1823 FALSE);
1824
1825 /* Restore the port data */
1826 KdRestore(FALSE);
1827
1828 return Status;
1829 }
1830
1831 VOID
1832 NTAPI
KdpTimeSlipDpcRoutine(IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)1833 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1834 IN PVOID DeferredContext,
1835 IN PVOID SystemArgument1,
1836 IN PVOID SystemArgument2)
1837 {
1838 LONG OldSlip, NewSlip, PendingSlip;
1839
1840 /* Get the current pending slip */
1841 PendingSlip = KdpTimeSlipPending;
1842 do
1843 {
1844 /* Save the old value and either disable or enable it now. */
1845 OldSlip = PendingSlip;
1846 NewSlip = OldSlip > 1 ? 1 : 0;
1847
1848 /* Try to change the value */
1849 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1850 NewSlip,
1851 OldSlip) != OldSlip);
1852
1853 /* If the New Slip value is 1, then do the Time Slipping */
1854 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1855 }
1856
1857 VOID
1858 NTAPI
KdpTimeSlipWork(IN PVOID Context)1859 KdpTimeSlipWork(IN PVOID Context)
1860 {
1861 KIRQL OldIrql;
1862 LARGE_INTEGER DueTime;
1863
1864 /* Update the System time from the CMOS */
1865 ExAcquireTimeRefreshLock(FALSE);
1866 ExUpdateSystemTimeFromCmos(FALSE, 0);
1867 ExReleaseTimeRefreshLock();
1868
1869 /* Check if we have a registered Time Slip Event and signal it */
1870 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1871 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1872 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1873
1874 /* Delay the DPC until it runs next time */
1875 DueTime.QuadPart = -1800000000;
1876 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1877 }
1878
1879 LARGE_INTEGER
1880 NTAPI
KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)1881 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1882 {
1883 LARGE_INTEGER Null = {{0}};
1884
1885 /* Check if interrupts were disabled */
1886 if (!KeGetTrapFrameInterruptState(TrapFrame))
1887 {
1888 /* Nothing to return */
1889 return Null;
1890 }
1891
1892 /* Otherwise, do the call */
1893 return KeQueryPerformanceCounter(NULL);
1894 }
1895
1896 BOOLEAN
1897 NTAPI
KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,IN PKEXCEPTION_FRAME ExceptionFrame)1898 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1899 IN PKEXCEPTION_FRAME ExceptionFrame)
1900 {
1901 BOOLEAN Enable;
1902
1903 /* Check if we have a trap frame */
1904 if (TrapFrame)
1905 {
1906 /* Calculate the time difference for the enter */
1907 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1908 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1909 KdTimerStart.QuadPart;
1910 }
1911 else
1912 {
1913 /* No trap frame, so can't calculate */
1914 KdTimerStop.QuadPart = 0;
1915 }
1916
1917 /* Save the current IRQL */
1918 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1919
1920 /* Freeze all CPUs, raising also the IRQL to HIGH_LEVEL */
1921 Enable = KeFreezeExecution(TrapFrame, ExceptionFrame);
1922
1923 /* Lock the port, save its state and set the debugger entered flag */
1924 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1925 KdSave(FALSE);
1926 KdEnteredDebugger = TRUE;
1927
1928 /* Check freeze flag */
1929 if (KiFreezeFlag & 1)
1930 {
1931 /* Print out errror */
1932 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1933 }
1934
1935 /* Check processor state */
1936 if (KiFreezeFlag & 2)
1937 {
1938 /* Print out errror */
1939 KdpDprintf("Some processors not frozen in debugger!\n");
1940 }
1941
1942 /* Make sure we acquired the port */
1943 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n");
1944
1945 /* Return if interrupts needs to be re-enabled */
1946 return Enable;
1947 }
1948
1949 VOID
1950 NTAPI
KdExitDebugger(IN BOOLEAN Enable)1951 KdExitDebugger(IN BOOLEAN Enable)
1952 {
1953 ULONG TimeSlip;
1954
1955 /* Reset the debugger entered flag, restore the port state and unlock it */
1956 KdEnteredDebugger = FALSE;
1957 KdRestore(FALSE);
1958 if (KdpPortLocked) KdpPortUnlock();
1959
1960 /* Unfreeze the CPUs, restoring also the IRQL */
1961 KeThawExecution(Enable);
1962
1963 /* Compare time with the one from KdEnterDebugger */
1964 if (!KdTimerStop.QuadPart)
1965 {
1966 /* We didn't get a trap frame earlier in so never got the time */
1967 KdTimerStart = KdTimerStop;
1968 }
1969 else
1970 {
1971 /* Query the timer */
1972 KdTimerStart = KeQueryPerformanceCounter(NULL);
1973 }
1974
1975 /* Check if a Time Slip was on queue */
1976 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1977 if (TimeSlip == 1)
1978 {
1979 /* Queue a DPC for the time slip */
1980 InterlockedIncrement(&KdpTimeSlipPending);
1981 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL); // FIXME: this can trigger context switches!
1982 }
1983 }
1984
1985 NTSTATUS
1986 NTAPI
KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)1987 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)
1988 {
1989 KIRQL OldIrql;
1990
1991 #if defined(__GNUC__)
1992 /* Make gcc happy */
1993 OldIrql = PASSIVE_LEVEL;
1994 #endif
1995
1996 /* Check if enabling the debugger is blocked */
1997 if (KdBlockEnable)
1998 {
1999 /* It is, fail the enable */
2000 return STATUS_ACCESS_DENIED;
2001 }
2002
2003 /* Check if we need to acquire the lock */
2004 if (NeedLock)
2005 {
2006 /* Lock the port */
2007 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2008 KdpPortLock();
2009 }
2010
2011 /* Check if we're not disabled */
2012 if (!KdDisableCount)
2013 {
2014 /* Check if we had locked the port before */
2015 if (NeedLock)
2016 {
2017 /* Do the unlock */
2018 KdpPortUnlock();
2019 KeLowerIrql(OldIrql);
2020
2021 /* Fail: We're already enabled */
2022 return STATUS_INVALID_PARAMETER;
2023 }
2024 else
2025 {
2026 /*
2027 * This can only happen if we are called from a bugcheck
2028 * and were never initialized, so initialize the debugger now.
2029 */
2030 KdInitSystem(0, NULL);
2031
2032 /* Return success since we initialized */
2033 return STATUS_SUCCESS;
2034 }
2035 }
2036
2037 /* Decrease the disable count */
2038 if (!(--KdDisableCount))
2039 {
2040 /* We're now enabled again! Were we enabled before, too? */
2041 if (KdPreviouslyEnabled)
2042 {
2043 /* Reinitialize the Debugger */
2044 KdInitSystem(0, NULL);
2045 KdpRestoreAllBreakpoints();
2046 }
2047 }
2048
2049 /* Check if we had locked the port before */
2050 if (NeedLock)
2051 {
2052 /* Yes, now unlock it */
2053 KdpPortUnlock();
2054 KeLowerIrql(OldIrql);
2055 }
2056
2057 /* We're done */
2058 return STATUS_SUCCESS;
2059 }
2060
2061 NTSTATUS
2062 NTAPI
KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)2063 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)
2064 {
2065 KIRQL OldIrql;
2066 NTSTATUS Status;
2067
2068 #if defined(__GNUC__)
2069 /* Make gcc happy */
2070 OldIrql = PASSIVE_LEVEL;
2071 #endif
2072
2073 /*
2074 * If enabling the debugger is blocked
2075 * then there is nothing to disable (duh)
2076 */
2077 if (KdBlockEnable)
2078 {
2079 /* Fail */
2080 return STATUS_ACCESS_DENIED;
2081 }
2082
2083 /* Check if we need to acquire the lock */
2084 if (NeedLock)
2085 {
2086 /* Lock the port */
2087 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2088 KdpPortLock();
2089 }
2090
2091 /* Check if we're not disabled */
2092 if (!KdDisableCount)
2093 {
2094 /* Check if the debugger was never actually initialized */
2095 if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
2096 {
2097 /* It wasn't, so don't re-enable it later */
2098 KdPreviouslyEnabled = FALSE;
2099 }
2100 else
2101 {
2102 /* It was, so we will re-enable it later */
2103 KdPreviouslyEnabled = TRUE;
2104 }
2105
2106 /* Check if we were called from the exported API and are enabled */
2107 if ((NeedLock) && (KdPreviouslyEnabled))
2108 {
2109 /* Check if it is safe to disable the debugger */
2110 Status = KdpAllowDisable();
2111 if (!NT_SUCCESS(Status))
2112 {
2113 /* Release the lock and fail */
2114 KdpPortUnlock();
2115 KeLowerIrql(OldIrql);
2116 return Status;
2117 }
2118 }
2119
2120 /* Only disable the debugger if it is enabled */
2121 if (KdDebuggerEnabled)
2122 {
2123 /*
2124 * Disable the debugger; suspend breakpoints
2125 * and reset the debug stub
2126 */
2127 KdpSuspendAllBreakPoints();
2128 KiDebugRoutine = KdpStub;
2129
2130 /* We are disabled now */
2131 KdDebuggerEnabled = FALSE;
2132 SharedUserData->KdDebuggerEnabled = FALSE;
2133 }
2134 }
2135
2136 /* Increment the disable count */
2137 KdDisableCount++;
2138
2139 /* Check if we had locked the port before */
2140 if (NeedLock)
2141 {
2142 /* Yes, now unlock it */
2143 KdpPortUnlock();
2144 KeLowerIrql(OldIrql);
2145 }
2146
2147 /* We're done */
2148 return STATUS_SUCCESS;
2149 }
2150
2151 /* PUBLIC FUNCTIONS **********************************************************/
2152
2153 /*
2154 * @implemented
2155 */
2156 NTSTATUS
2157 NTAPI
KdEnableDebugger(VOID)2158 KdEnableDebugger(VOID)
2159 {
2160 /* Use the internal routine */
2161 return KdEnableDebuggerWithLock(TRUE);
2162 }
2163
2164 /*
2165 * @implemented
2166 */
2167 NTSTATUS
2168 NTAPI
KdDisableDebugger(VOID)2169 KdDisableDebugger(VOID)
2170 {
2171 /* Use the internal routine */
2172 return KdDisableDebuggerWithLock(TRUE);
2173 }
2174
2175 /**
2176 * @brief
2177 * Perform various queries to the kernel debugger.
2178 *
2179 * @param[in] Command
2180 * A SYSDBG_COMMAND value describing the kernel debugger command to perform.
2181 *
2182 * @param[in] InputBuffer
2183 * Pointer to a user-provided input command-specific buffer, whose length
2184 * is given by InputBufferLength.
2185 *
2186 * @param[in] InputBufferLength
2187 * The size (in bytes) of the buffer pointed by InputBuffer.
2188 *
2189 * @param[out] OutputBuffer
2190 * Pointer to a user-provided command-specific output buffer, whose length
2191 * is given by OutputBufferLength.
2192 *
2193 * @param[in] OutputBufferLength
2194 * The size (in bytes) of the buffer pointed by OutputBuffer.
2195 *
2196 * @param[out] ReturnLength
2197 * Optional pointer to a ULONG variable that receives the actual length of
2198 * data written written in the output buffer. It is always zero, except for
2199 * the live dump commands where an actual non-zero length is returned.
2200 *
2201 * @param[in] PreviousMode
2202 * The processor mode (KernelMode or UserMode) in which the command is being executed.
2203 *
2204 * @return
2205 * STATUS_SUCCESS in case of success, or a proper error code otherwise.
2206 *
2207 * @remarks
2208 * - This is a kernel-mode function, accessible only by kernel-mode drivers.
2209 *
2210 * @note
2211 * See: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2004-2339
2212 *
2213 * @see NtSystemDebugControl()
2214 **/
2215 NTSTATUS
2216 NTAPI
KdSystemDebugControl(_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,_In_ KPROCESSOR_MODE PreviousMode)2217 KdSystemDebugControl(
2218 _In_ SYSDBG_COMMAND Command,
2219 _In_reads_bytes_(InputBufferLength) PVOID InputBuffer,
2220 _In_ ULONG InputBufferLength,
2221 _Out_writes_bytes_(OutputBufferLength) PVOID OutputBuffer,
2222 _In_ ULONG OutputBufferLength,
2223 _Out_opt_ PULONG ReturnLength,
2224 _In_ KPROCESSOR_MODE PreviousMode)
2225 {
2226 NTSTATUS Status;
2227 ULONG Length = 0;
2228
2229 /* Handle some internal commands */
2230 switch ((ULONG)Command)
2231 {
2232 #if DBG
2233 case ' soR': /* ROS-INTERNAL */
2234 {
2235 switch ((ULONG_PTR)InputBuffer)
2236 {
2237 case 0x21: // DumpAllThreads:
2238 PspDumpThreads(TRUE);
2239 break;
2240
2241 case 0x22: // DumpUserThreads:
2242 PspDumpThreads(FALSE);
2243 break;
2244
2245 case 0x24: // KdSpare3:
2246 MmDumpArmPfnDatabase(FALSE);
2247 break;
2248
2249 default:
2250 break;
2251 }
2252 return STATUS_SUCCESS;
2253 }
2254
2255 #if defined(_M_IX86) && !defined(_WINKD_) // See ke/i386/traphdlr.c
2256 /* Register a debug callback */
2257 case 'CsoR':
2258 {
2259 switch (InputBufferLength)
2260 {
2261 case ID_Win32PreServiceHook:
2262 KeWin32PreServiceHook = InputBuffer;
2263 break;
2264
2265 case ID_Win32PostServiceHook:
2266 KeWin32PostServiceHook = InputBuffer;
2267 break;
2268
2269 }
2270 break;
2271 }
2272 #endif
2273
2274 /* Special case for stack frame dumps */
2275 case 'DsoR':
2276 {
2277 KeRosDumpStackFrames((PULONG_PTR)InputBuffer, InputBufferLength);
2278 break;
2279 }
2280 #ifdef KDBG
2281 /* Register KDBG CLI callback */
2282 case 'RbdK':
2283 {
2284 return KdbRegisterCliCallback(InputBuffer, InputBufferLength);
2285 }
2286 #endif // KDBG
2287 #endif
2288 default:
2289 break;
2290 }
2291
2292 switch (Command)
2293 {
2294 case SysDbgQueryVersion:
2295 if (OutputBufferLength != sizeof(DBGKD_GET_VERSION64))
2296 {
2297 Status = STATUS_INFO_LENGTH_MISMATCH;
2298 }
2299 else
2300 {
2301 KdpSysGetVersion((PDBGKD_GET_VERSION64)OutputBuffer);
2302 Status = STATUS_SUCCESS;
2303 }
2304 break;
2305
2306 case SysDbgReadVirtual:
2307 case SysDbgWriteVirtual:
2308 if (InputBufferLength != sizeof(SYSDBG_VIRTUAL))
2309 {
2310 Status = STATUS_INFO_LENGTH_MISMATCH;
2311 }
2312 else
2313 {
2314 SYSDBG_VIRTUAL Request = *(PSYSDBG_VIRTUAL)InputBuffer;
2315 PVOID LockedBuffer;
2316 PMDL LockVariable;
2317
2318 Status = ExLockUserBuffer(Request.Buffer,
2319 Request.Request,
2320 PreviousMode,
2321 Command == SysDbgReadVirtual ? IoWriteAccess : IoReadAccess,
2322 &LockedBuffer,
2323 &LockVariable);
2324 if (NT_SUCCESS(Status))
2325 {
2326 Status = KdpCopyMemoryChunks((ULONG64)(ULONG_PTR)Request.Address,
2327 Request.Buffer,
2328 Request.Request,
2329 0,
2330 Command == SysDbgReadVirtual ? 0 : MMDBG_COPY_WRITE,
2331 &Length);
2332 ExUnlockUserBuffer(LockVariable);
2333 }
2334 }
2335 break;
2336
2337 case SysDbgReadPhysical:
2338 case SysDbgWritePhysical:
2339 if (InputBufferLength != sizeof(SYSDBG_PHYSICAL))
2340 {
2341 Status = STATUS_INFO_LENGTH_MISMATCH;
2342 }
2343 else
2344 {
2345 SYSDBG_PHYSICAL Request = *(PSYSDBG_PHYSICAL)InputBuffer;
2346 PVOID LockedBuffer;
2347 PMDL LockVariable;
2348
2349 Status = ExLockUserBuffer(Request.Buffer,
2350 Request.Request,
2351 PreviousMode,
2352 Command == SysDbgReadVirtual ? IoWriteAccess : IoReadAccess,
2353 &LockedBuffer,
2354 &LockVariable);
2355 if (NT_SUCCESS(Status))
2356 {
2357 Status = KdpCopyMemoryChunks(Request.Address.QuadPart,
2358 Request.Buffer,
2359 Request.Request,
2360 0,
2361 MMDBG_COPY_PHYSICAL | (Command == SysDbgReadVirtual ? 0 : MMDBG_COPY_WRITE),
2362 &Length);
2363 ExUnlockUserBuffer(LockVariable);
2364 }
2365 }
2366 break;
2367
2368 case SysDbgReadControlSpace:
2369 if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE))
2370 {
2371 Status = STATUS_INFO_LENGTH_MISMATCH;
2372 }
2373 else
2374 {
2375 SYSDBG_CONTROL_SPACE Request = *(PSYSDBG_CONTROL_SPACE)InputBuffer;
2376 PVOID LockedBuffer;
2377 PMDL LockVariable;
2378
2379 Status = ExLockUserBuffer(Request.Buffer,
2380 Request.Request,
2381 PreviousMode,
2382 IoWriteAccess,
2383 &LockedBuffer,
2384 &LockVariable);
2385 if (NT_SUCCESS(Status))
2386 {
2387 Status = KdpSysReadControlSpace(Request.Processor,
2388 Request.Address,
2389 LockedBuffer,
2390 Request.Request,
2391 &Length);
2392 ExUnlockUserBuffer(LockVariable);
2393 }
2394 }
2395 break;
2396
2397 case SysDbgWriteControlSpace:
2398 if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE))
2399 {
2400 Status = STATUS_INFO_LENGTH_MISMATCH;
2401 }
2402 else
2403 {
2404 SYSDBG_CONTROL_SPACE Request = *(PSYSDBG_CONTROL_SPACE)InputBuffer;
2405 PVOID LockedBuffer;
2406 PMDL LockVariable;
2407
2408 Status = ExLockUserBuffer(Request.Buffer,
2409 Request.Request,
2410 PreviousMode,
2411 IoReadAccess,
2412 &LockedBuffer,
2413 &LockVariable);
2414 if (NT_SUCCESS(Status))
2415 {
2416 Status = KdpSysWriteControlSpace(Request.Processor,
2417 Request.Address,
2418 LockedBuffer,
2419 Request.Request,
2420 &Length);
2421 ExUnlockUserBuffer(LockVariable);
2422 }
2423 }
2424 break;
2425
2426 case SysDbgReadIoSpace:
2427 if (InputBufferLength != sizeof(SYSDBG_IO_SPACE))
2428 {
2429 Status = STATUS_INFO_LENGTH_MISMATCH;
2430 }
2431 else
2432 {
2433 SYSDBG_IO_SPACE Request = *(PSYSDBG_IO_SPACE)InputBuffer;
2434 PVOID LockedBuffer;
2435 PMDL LockVariable;
2436
2437 Status = ExLockUserBuffer(Request.Buffer,
2438 Request.Request,
2439 PreviousMode,
2440 IoWriteAccess,
2441 &LockedBuffer,
2442 &LockVariable);
2443 if (NT_SUCCESS(Status))
2444 {
2445 Status = KdpSysReadIoSpace(Request.InterfaceType,
2446 Request.BusNumber,
2447 Request.AddressSpace,
2448 Request.Address,
2449 LockedBuffer,
2450 Request.Request,
2451 &Length);
2452 ExUnlockUserBuffer(LockVariable);
2453 }
2454 }
2455 break;
2456
2457 case SysDbgWriteIoSpace:
2458 if (InputBufferLength != sizeof(SYSDBG_IO_SPACE))
2459 {
2460 Status = STATUS_INFO_LENGTH_MISMATCH;
2461 }
2462 else
2463 {
2464 SYSDBG_IO_SPACE Request = *(PSYSDBG_IO_SPACE)InputBuffer;
2465 PVOID LockedBuffer;
2466 PMDL LockVariable;
2467
2468 Status = ExLockUserBuffer(Request.Buffer,
2469 Request.Request,
2470 PreviousMode,
2471 IoReadAccess,
2472 &LockedBuffer,
2473 &LockVariable);
2474 if (NT_SUCCESS(Status))
2475 {
2476 Status = KdpSysWriteIoSpace(Request.InterfaceType,
2477 Request.BusNumber,
2478 Request.AddressSpace,
2479 Request.Address,
2480 LockedBuffer,
2481 Request.Request,
2482 &Length);
2483 ExUnlockUserBuffer(LockVariable);
2484 }
2485 }
2486 break;
2487
2488 case SysDbgReadMsr:
2489 if (InputBufferLength != sizeof(SYSDBG_MSR))
2490 {
2491 Status = STATUS_INFO_LENGTH_MISMATCH;
2492 }
2493 else
2494 {
2495 PSYSDBG_MSR Request = (PSYSDBG_MSR)InputBuffer;
2496 Status = KdpSysReadMsr(Request->Address, &Request->Data);
2497 }
2498 break;
2499
2500 case SysDbgWriteMsr:
2501 if (InputBufferLength != sizeof(SYSDBG_MSR))
2502 {
2503 Status = STATUS_INFO_LENGTH_MISMATCH;
2504 }
2505 else
2506 {
2507 PSYSDBG_MSR Request = (PSYSDBG_MSR)InputBuffer;
2508 Status = KdpSysWriteMsr(Request->Address, &Request->Data);
2509 }
2510 break;
2511
2512 case SysDbgReadBusData:
2513 if (InputBufferLength != sizeof(SYSDBG_BUS_DATA))
2514 {
2515 Status = STATUS_INFO_LENGTH_MISMATCH;
2516 }
2517 else
2518 {
2519 SYSDBG_BUS_DATA Request = *(PSYSDBG_BUS_DATA)InputBuffer;
2520 PVOID LockedBuffer;
2521 PMDL LockVariable;
2522
2523 Status = ExLockUserBuffer(Request.Buffer,
2524 Request.Request,
2525 PreviousMode,
2526 IoWriteAccess,
2527 &LockedBuffer,
2528 &LockVariable);
2529 if (NT_SUCCESS(Status))
2530 {
2531 Status = KdpSysReadBusData(Request.BusDataType,
2532 Request.BusNumber,
2533 Request.SlotNumber,
2534 Request.Address,
2535 LockedBuffer,
2536 Request.Request,
2537 &Length);
2538 ExUnlockUserBuffer(LockVariable);
2539 }
2540 }
2541 break;
2542
2543 case SysDbgWriteBusData:
2544 if (InputBufferLength != sizeof(SYSDBG_BUS_DATA))
2545 {
2546 Status = STATUS_INFO_LENGTH_MISMATCH;
2547 }
2548 else
2549 {
2550 SYSDBG_BUS_DATA Request = *(PSYSDBG_BUS_DATA)InputBuffer;
2551 PVOID LockedBuffer;
2552 PMDL LockVariable;
2553
2554 Status = ExLockUserBuffer(Request.Buffer,
2555 Request.Request,
2556 PreviousMode,
2557 IoReadAccess,
2558 &LockedBuffer,
2559 &LockVariable);
2560 if (NT_SUCCESS(Status))
2561 {
2562 Status = KdpSysWriteBusData(Request.BusDataType,
2563 Request.BusNumber,
2564 Request.SlotNumber,
2565 Request.Address,
2566 LockedBuffer,
2567 Request.Request,
2568 &Length);
2569 ExUnlockUserBuffer(LockVariable);
2570 }
2571 }
2572 break;
2573
2574 case SysDbgCheckLowMemory:
2575 Status = KdpSysCheckLowMemory(0);
2576 break;
2577
2578 default:
2579 Status = STATUS_INVALID_INFO_CLASS;
2580 break;
2581 }
2582
2583 if (ReturnLength)
2584 *ReturnLength = Length;
2585
2586 return Status;
2587 }
2588
2589 /*
2590 * @implemented
2591 */
2592 NTSTATUS
2593 NTAPI
KdChangeOption(IN KD_OPTION Option,IN ULONG InBufferBytes OPTIONAL,IN PVOID InBuffer,IN ULONG OutBufferBytes OPTIONAL,OUT PVOID OutBuffer,OUT PULONG OutBufferNeeded OPTIONAL)2594 KdChangeOption(IN KD_OPTION Option,
2595 IN ULONG InBufferBytes OPTIONAL,
2596 IN PVOID InBuffer,
2597 IN ULONG OutBufferBytes OPTIONAL,
2598 OUT PVOID OutBuffer,
2599 OUT PULONG OutBufferNeeded OPTIONAL)
2600 {
2601 /* Fail if there is no debugger */
2602 if (KdPitchDebugger)
2603 {
2604 /* No debugger, no options */
2605 return STATUS_DEBUGGER_INACTIVE;
2606 }
2607
2608 /* Do we recognize this option? */
2609 if (Option != KD_OPTION_SET_BLOCK_ENABLE)
2610 {
2611 /* We don't, clear the output length and fail */
2612 if (OutBufferNeeded) *OutBufferNeeded = 0;
2613 return STATUS_INVALID_INFO_CLASS;
2614 }
2615
2616 /* Verify parameters */
2617 if ((InBufferBytes != sizeof(BOOLEAN)) ||
2618 (OutBufferBytes != 0) ||
2619 (OutBuffer != NULL))
2620 {
2621 /* Invalid parameters for this option, fail */
2622 return STATUS_INVALID_PARAMETER;
2623 }
2624
2625 /*
2626 * Check if the high bit is set, meaning we don't
2627 * allow the debugger to be enabled
2628 */
2629 if (KdBlockEnable & 0x80)
2630 {
2631 /* Fail regardless of what state the caller tried to set */
2632 return STATUS_ACCESS_VIOLATION;
2633 }
2634
2635 /* Set the new block enable state */
2636 KdBlockEnable = *(PBOOLEAN)InBuffer;
2637
2638 /* No output buffer required for this option */
2639 if (OutBufferNeeded) *OutBufferNeeded = 0;
2640
2641 /* We are done */
2642 return STATUS_SUCCESS;
2643 }
2644
2645 /*
2646 * @implemented
2647 */
2648 NTSTATUS
2649 NTAPI
KdPowerTransition(IN DEVICE_POWER_STATE NewState)2650 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
2651 {
2652 /* Check what power state this is */
2653 if (NewState == PowerDeviceD0)
2654 {
2655 /* Wake up the debug port */
2656 KdD0Transition();
2657 return STATUS_SUCCESS;
2658 }
2659 else if ((NewState == PowerDeviceD1) ||
2660 (NewState == PowerDeviceD2) ||
2661 (NewState == PowerDeviceD3))
2662 {
2663 /* Power down the debug port */
2664 KdD3Transition();
2665 return STATUS_SUCCESS;
2666 }
2667 else
2668 {
2669 /* Invalid state! */
2670 return STATUS_INVALID_PARAMETER_1;
2671 }
2672 }
2673
2674 /*
2675 * @implemented
2676 */
2677 BOOLEAN
2678 NTAPI
KdRefreshDebuggerNotPresent(VOID)2679 KdRefreshDebuggerNotPresent(VOID)
2680 {
2681 BOOLEAN Enable, DebuggerNotPresent;
2682
2683 /* Check if the debugger is completely disabled */
2684 if (KdPitchDebugger)
2685 {
2686 /* Don't try to refresh then, fail early */
2687 return TRUE;
2688 }
2689
2690 /* Enter the debugger */
2691 Enable = KdEnterDebugger(NULL, NULL);
2692
2693 /*
2694 * Attempt to send a string to the debugger
2695 * to refresh the connection state.
2696 */
2697 KdpDprintf("KDTARGET: Refreshing KD connection\n");
2698
2699 /* Save the state while we are holding the lock */
2700 DebuggerNotPresent = KdDebuggerNotPresent;
2701
2702 /* Exit the debugger and return the state */
2703 KdExitDebugger(Enable);
2704 return DebuggerNotPresent;
2705 }
2706
2707 /*
2708 * @implemented
2709 */
2710 NTSTATUS
2711 NTAPI
NtQueryDebugFilterState(_In_ ULONG ComponentId,_In_ ULONG Level)2712 NtQueryDebugFilterState(
2713 _In_ ULONG ComponentId,
2714 _In_ ULONG Level)
2715 {
2716 PULONG Mask;
2717
2718 /* Check if the ID fits in the component table */
2719 if (ComponentId < KdComponentTableSize)
2720 {
2721 /* It does, so get the mask from there */
2722 Mask = KdComponentTable[ComponentId];
2723 }
2724 else if (ComponentId == MAXULONG)
2725 {
2726 /*
2727 * This is the internal ID used for DbgPrint messages without ID
2728 * and Level. Use the system-wide mask for those.
2729 */
2730 Mask = &Kd_WIN2000_Mask;
2731 }
2732 else
2733 {
2734 #if (NTDDI_VERSION >= NTDDI_VISTA)
2735 /* Use the default component ID */
2736 Mask = &Kd_DEFAULT_Mask;
2737 // Level = DPFLTR_INFO_LEVEL; // Override the Level.
2738 #else
2739 /* Invalid ID, fail */
2740 return STATUS_INVALID_PARAMETER_1;
2741 #endif
2742 }
2743
2744 /* Convert Level to bit field if required */
2745 if (Level < 32) Level = 1 << Level;
2746 Level &= ~DPFLTR_MASK;
2747
2748 /* Determine if this Level is filtered out */
2749 if ((Kd_WIN2000_Mask & Level) || (*Mask & Level))
2750 {
2751 /* This mask will get through to the debugger */
2752 return (NTSTATUS)TRUE;
2753 }
2754 else
2755 {
2756 /* This mask is filtered out */
2757 return (NTSTATUS)FALSE;
2758 }
2759 }
2760
2761 /*
2762 * @implemented
2763 */
2764 NTSTATUS
2765 NTAPI
NtSetDebugFilterState(_In_ ULONG ComponentId,_In_ ULONG Level,_In_ BOOLEAN State)2766 NtSetDebugFilterState(
2767 _In_ ULONG ComponentId,
2768 _In_ ULONG Level,
2769 _In_ BOOLEAN State)
2770 {
2771 PULONG Mask;
2772
2773 /* Modifying debug filters requires the debug privilege */
2774 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode()))
2775 {
2776 /* Fail */
2777 return STATUS_ACCESS_DENIED;
2778 }
2779
2780 /* Check if the ID fits in the component table */
2781 if (ComponentId < KdComponentTableSize)
2782 {
2783 /* It does, so get the mask from there */
2784 Mask = KdComponentTable[ComponentId];
2785 }
2786 else if (ComponentId == MAXULONG)
2787 {
2788 /*
2789 * This is the internal ID used for DbgPrint messages without ID
2790 * and Level. Use the system-wide mask for those.
2791 */
2792 Mask = &Kd_WIN2000_Mask;
2793 }
2794 else
2795 {
2796 #if (NTDDI_VERSION >= NTDDI_VISTA)
2797 /* Use the default component ID */
2798 Mask = &Kd_DEFAULT_Mask;
2799 #else
2800 /* Invalid ID, fail */
2801 return STATUS_INVALID_PARAMETER_1;
2802 #endif
2803 }
2804
2805 /* Convert Level to bit field if required */
2806 if (Level < 32) Level = 1 << Level;
2807 Level &= ~DPFLTR_MASK;
2808
2809 /* Set or remove the Level */
2810 if (State)
2811 *Mask |= Level;
2812 else
2813 *Mask &= ~Level;
2814
2815 return STATUS_SUCCESS;
2816 }
2817