c4a213df3de83bf061a22da7516fb52a7464805f
[reactos.git] / reactos / ntoskrnl / kd64 / kdapi.c
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 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PRIVATE FUNCTIONS *********************************************************/
16
17 VOID
18 NTAPI
19 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,
20 IN PCONTEXT Context)
21 {
22 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;
23 STRING Header;
24 NTSTATUS Status = STATUS_SUCCESS;
25
26 /* Validate the address space */
27 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)
28 {
29 /* Check if this is process memory */
30 if ((PVOID)(ULONG_PTR)Memory->Address < MmHighestUserAddress)
31 {
32 /* It is */
33 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
34 }
35 else
36 {
37 /* FIXME: Check if it's session space */
38 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
39 }
40
41 /* Set flags */
42 Memory->Flags = DBGKD_QUERY_MEMORY_READ |
43 DBGKD_QUERY_MEMORY_WRITE |
44 DBGKD_QUERY_MEMORY_EXECUTE;
45 }
46 else
47 {
48 /* Invalid */
49 Status = STATUS_INVALID_PARAMETER;
50 }
51
52 /* Return structure */
53 State->ReturnStatus = Status;
54 Memory->Reserved = 0;
55
56 /* Build header */
57 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
58 Header.Buffer = (PCHAR)State;
59
60 /* Send the packet */
61 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
62 &Header,
63 NULL,
64 &KdpContext);
65 }
66
67 VOID
68 NTAPI
69 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,
70 IN PSTRING Data,
71 IN PCONTEXT Context)
72 {
73 /* FIXME: STUB */
74 KdpDprintf("KdpSearchMemory called\n");
75 while (TRUE);
76 }
77
78 VOID
79 NTAPI
80 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,
81 IN PSTRING Data,
82 IN PCONTEXT Context)
83 {
84 /* FIXME: STUB */
85 KdpDprintf("KdpFillMemory called\n");
86 while (TRUE);
87 }
88
89 VOID
90 NTAPI
91 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
92 IN PSTRING Data,
93 IN PCONTEXT Context)
94 {
95 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
96 STRING Header;
97
98 /* Build header */
99 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
100 Header.Buffer = (PCHAR)State;
101 ASSERT(Data->Length == 0);
102
103 /* Create the breakpoint */
104 Breakpoint->BreakPointHandle =
105 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress);
106 if (!Breakpoint->BreakPointHandle)
107 {
108 /* We failed */
109 State->ReturnStatus = STATUS_UNSUCCESSFUL;
110 }
111 else
112 {
113 /* Success! */
114 State->ReturnStatus = STATUS_SUCCESS;
115 }
116
117 /* Send the packet */
118 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
119 &Header,
120 NULL,
121 &KdpContext);
122 }
123
124 VOID
125 NTAPI
126 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
127 IN PSTRING Data,
128 IN PCONTEXT Context)
129 {
130 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
131 STRING Header;
132
133 /* Fill out the header */
134 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
135 Header.Buffer = (PCHAR)State;
136 ASSERT(Data->Length == 0);
137
138 /* Get the version block */
139 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
140 {
141 /* We're all good */
142 State->ReturnStatus = STATUS_SUCCESS;
143 }
144 else
145 {
146 /* We failed */
147 State->ReturnStatus = STATUS_UNSUCCESSFUL;
148 }
149
150 /* Send the packet */
151 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
152 &Header,
153 NULL,
154 &KdpContext);
155 }
156
157 NTSTATUS
158 NTAPI
159 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
160 IN PSTRING Data,
161 IN PCONTEXT Context)
162 {
163 /* FIXME: STUB */
164 KdpDprintf("KdpWriteBreakPointEx called\n");
165 while (TRUE);
166 return STATUS_UNSUCCESSFUL;
167 }
168
169 VOID
170 NTAPI
171 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
172 IN PSTRING Data,
173 IN PCONTEXT Context)
174 {
175 /* FIXME: STUB */
176 KdpDprintf("KdpRestoreBreakPointEx called\n");
177 while (TRUE);
178 }
179
180 VOID
181 NTAPI
182 DumpTraceData(IN PSTRING TraceData)
183 {
184 /* Update the buffer */
185 TraceDataBuffer[0] = TraceDataBufferPosition;
186
187 /* Setup the trace data */
188 TraceData->Length = TraceDataBufferPosition * sizeof(ULONG);
189 TraceData->Buffer = (PCHAR)TraceDataBuffer;
190
191 /* Reset the buffer location */
192 TraceDataBufferPosition = 1;
193 }
194
195 VOID
196 NTAPI
197 KdpSetCommonState(IN ULONG NewState,
198 IN PCONTEXT Context,
199 IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange)
200 {
201 USHORT InstructionCount;
202 BOOLEAN HadBreakpoints;
203
204 /* Setup common stuff available for all CPU architectures */
205 WaitStateChange->NewState = NewState;
206 WaitStateChange->ProcessorLevel = KeProcessorLevel;
207 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
208 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
209 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
210 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
211
212 /* Zero out the Control Report */
213 RtlZeroMemory(&WaitStateChange->ControlReport,
214 sizeof(DBGKD_CONTROL_REPORT));
215
216 /* Now copy the instruction stream and set the count */
217 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
218 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
219 DBGKD_MAXSTREAM);
220 InstructionCount = DBGKD_MAXSTREAM;
221 WaitStateChange->ControlReport.InstructionCount = InstructionCount;
222
223 /* Clear all the breakpoints in this region */
224 HadBreakpoints =
225 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
226 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
227 WaitStateChange->ControlReport.InstructionCount - 1));
228 if (HadBreakpoints)
229 {
230 /* Copy the instruction stream again, this time without breakpoints */
231 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
232 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
233 WaitStateChange->ControlReport.InstructionCount);
234 }
235 }
236
237 VOID
238 NTAPI
239 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
240 {
241 STRING Header;
242
243 /* Fill out the header */
244 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
245 Header.Buffer = (PCHAR)State;
246
247 /* Get the version block */
248 KdpSysGetVersion(&State->u.GetVersion64);
249
250 /* Fill out the state */
251 State->ApiNumber = DbgKdGetVersionApi;
252 State->ReturnStatus = STATUS_SUCCESS;
253
254 /* Send the packet */
255 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
256 &Header,
257 NULL,
258 &KdpContext);
259 }
260
261 VOID
262 NTAPI
263 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
264 IN PSTRING Data,
265 IN PCONTEXT Context)
266 {
267 STRING Header;
268 ULONG Length = State->u.ReadMemory.TransferCount;
269 NTSTATUS Status = STATUS_SUCCESS;
270
271 /* Validate length */
272 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
273 {
274 /* Overflow, set it to maximum possible */
275 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
276 }
277
278 #if 0
279 if (!MmIsAddressValid((PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress))
280 {
281 KdpDprintf("Tried to read invalid address %p\n",
282 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress);
283 while (TRUE);
284 }
285 #endif
286
287 if (!State->u.ReadMemory.TargetBaseAddress)
288 {
289 Length = 0;
290 Status = STATUS_UNSUCCESSFUL;
291 }
292 else
293 {
294 RtlCopyMemory(Data->Buffer,
295 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress,
296 Length);
297 }
298
299 /* Fill out the header */
300 Data->Length = Length;
301 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
302 Header.Buffer = (PCHAR)State;
303
304 /* Fill out the state */
305 State->ReturnStatus = Status;
306 State->u.ReadMemory.ActualBytesRead = Length;
307
308 /* Send the packet */
309 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
310 &Header,
311 Data,
312 &KdpContext);
313 }
314
315 VOID
316 NTAPI
317 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
318 IN PSTRING Data,
319 IN PCONTEXT Context)
320 {
321 /* FIXME: STUB */
322 KdpDprintf("KdpWriteVirtualMemory called for Address: %p Length %x\n",
323 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress,
324 State->u.ReadMemory.TransferCount);
325 while (TRUE);
326 }
327
328 VOID
329 NTAPI
330 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State,
331 IN PSTRING Data,
332 IN PCONTEXT Context)
333 {
334 STRING Header;
335
336 /* FIXME: STUB */
337 KdpDprintf("KdpWritePhysicalMemory called for Address %I64x Length: %x\n",
338 State->u.ReadMemory.TargetBaseAddress,
339 State->u.ReadMemory.TransferCount);
340
341 /* Setup an empty message, with failure */
342 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
343 Header.Buffer = (PCHAR)State;
344 Data->Length = 0;
345 State->ReturnStatus = STATUS_UNSUCCESSFUL;
346
347 /* Send it */
348 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
349 &Header,
350 Data,
351 &KdpContext);
352 }
353
354 VOID
355 NTAPI
356 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State,
357 IN PSTRING Data,
358 IN PCONTEXT Context)
359 {
360 STRING Header;
361
362 /* FIXME: STUB */
363 KdpDprintf("KdpWritePhysicalMemory called for Address %I64x Length: %x\n",
364 State->u.ReadMemory.TargetBaseAddress,
365 State->u.ReadMemory.TransferCount);
366
367 /* Setup an empty message, with failure */
368 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
369 Header.Buffer = (PCHAR)State;
370 Data->Length = 0;
371 State->ReturnStatus = STATUS_UNSUCCESSFUL;
372
373 /* Send it */
374 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
375 &Header,
376 Data,
377 &KdpContext);
378 }
379
380 VOID
381 NTAPI
382 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
383 IN PSTRING Data,
384 IN PCONTEXT Context)
385 {
386 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
387 STRING Header;
388 ULONG Length;
389
390 /* Setup the header */
391 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
392 Header.Buffer = (PCHAR)State;
393 ASSERT(Data->Length == 0);
394
395 /* Check the length requested */
396 Length = ReadMemory->TransferCount;
397 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
398 {
399 /* Use maximum allowed */
400 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
401 }
402
403 /* Call the internal routine */
404 State->ReturnStatus = KdpSysReadControlSpace(State->Processor,
405 ReadMemory->TargetBaseAddress,
406 Data->Buffer,
407 Length,
408 &Length);
409
410 /* Return the actual length read */
411 Data->Length = ReadMemory->ActualBytesRead = Length;
412
413 /* Send the reply */
414 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
415 &Header,
416 Data,
417 &KdpContext);
418 }
419
420 VOID
421 NTAPI
422 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
423 IN PSTRING Data,
424 IN PCONTEXT Context)
425 {
426 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
427 STRING Header;
428 ULONG Length;
429
430 /* Setup the header */
431 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
432 Header.Buffer = (PCHAR)State;
433
434 /* Call the internal routine */
435 State->ReturnStatus = KdpSysWriteControlSpace(State->Processor,
436 WriteMemory->TargetBaseAddress,
437 Data->Buffer,
438 Data->Length,
439 &Length);
440
441 /* Return the length written */
442 WriteMemory->ActualBytesWritten = Length;
443
444 /* Send the reply */
445 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
446 &Header,
447 Data,
448 &KdpContext);
449 }
450
451 VOID
452 NTAPI
453 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
454 IN PSTRING Data,
455 IN PCONTEXT Context)
456 {
457 STRING Header;
458 PVOID ControlStart;
459
460 /* Setup the header */
461 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
462 Header.Buffer = (PCHAR)State;
463 ASSERT(Data->Length == 0);
464
465 /* Make sure that this is a valid request */
466 if (State->Processor < KeNumberProcessors)
467 {
468 /* Check if the request is for this CPU */
469 if (State->Processor == KeGetCurrentPrcb()->Number)
470 {
471 /* We're just copying our own context */
472 ControlStart = Context;
473 }
474 else
475 {
476 /* SMP not yet handled */
477 KdpDprintf("SMP UNHANDLED\n");
478 ControlStart = NULL;
479 while (TRUE);
480 }
481
482 /* Copy the memory */
483 RtlCopyMemory(Data->Buffer, ControlStart, sizeof(CONTEXT));
484 Data->Length = sizeof(CONTEXT);
485
486 /* Finish up */
487 State->ReturnStatus = STATUS_SUCCESS;
488 }
489 else
490 {
491 /* Invalid request */
492 State->ReturnStatus = STATUS_UNSUCCESSFUL;
493 }
494
495 /* Send the reply */
496 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
497 &Header,
498 Data,
499 &KdpContext);
500 }
501
502 VOID
503 NTAPI
504 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
505 IN PSTRING Data,
506 IN PCONTEXT Context)
507 {
508 STRING Header;
509 PVOID ControlStart;
510
511 /* Setup the header */
512 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
513 Header.Buffer = (PCHAR)State;
514 ASSERT(Data->Length == sizeof(CONTEXT));
515
516 /* Make sure that this is a valid request */
517 if (State->Processor < KeNumberProcessors)
518 {
519 /* Check if the request is for this CPU */
520 if (State->Processor == KeGetCurrentPrcb()->Number)
521 {
522 /* We're just copying our own context */
523 ControlStart = Context;
524 }
525 else
526 {
527 /* SMP not yet handled */
528 KdpDprintf("SMP UNHANDLED\n");
529 ControlStart = NULL;
530 while (TRUE);
531 }
532
533 /* Copy the memory */
534 RtlCopyMemory(ControlStart, Data->Buffer, sizeof(CONTEXT));
535
536 /* Finish up */
537 State->ReturnStatus = STATUS_SUCCESS;
538 }
539 else
540 {
541 /* Invalid request */
542 State->ReturnStatus = STATUS_UNSUCCESSFUL;
543 }
544
545 /* Send the reply */
546 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
547 &Header,
548 Data,
549 &KdpContext);
550 }
551
552 VOID
553 NTAPI
554 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)
555 {
556 /* Crash with the special code */
557 KeBugCheck(MANUALLY_INITIATED_CRASH);
558 }
559
560 VOID
561 NTAPI
562 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
563 IN PSTRING Data,
564 IN PCONTEXT Context)
565 {
566 STRING Header;
567 PDBGKD_READ_WRITE_MSR ReadMsr = &State->u.ReadWriteMsr;
568 LARGE_INTEGER MsrValue;
569
570 /* Setup the header */
571 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
572 Header.Buffer = (PCHAR)State;
573 ASSERT(Data->Length == 0);
574
575 /* Call the internal routine */
576 State->ReturnStatus = KdpSysReadMsr(ReadMsr->Msr,
577 &MsrValue);
578
579 /* Return the data */
580 ReadMsr->DataValueLow = MsrValue.LowPart;
581 ReadMsr->DataValueHigh = MsrValue.HighPart;
582
583 /* Send the reply */
584 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
585 &Header,
586 NULL,
587 &KdpContext);
588 }
589
590 VOID
591 NTAPI
592 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
593 IN PSTRING Data,
594 IN PCONTEXT Context)
595 {
596 STRING Header;
597 PDBGKD_READ_WRITE_MSR WriteMsr = &State->u.ReadWriteMsr;
598 LARGE_INTEGER MsrValue;
599
600 /* Setup the header */
601 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
602 Header.Buffer = (PCHAR)State;
603 ASSERT(Data->Length == 0);
604
605 /* Call the internal routine */
606 MsrValue.LowPart = WriteMsr->DataValueLow;
607 MsrValue.HighPart = WriteMsr->DataValueHigh;
608 State->ReturnStatus = KdpSysWriteMsr(WriteMsr->Msr,
609 &MsrValue);
610
611 /* Send the reply */
612 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
613 &Header,
614 NULL,
615 &KdpContext);
616 }
617
618 VOID
619 NTAPI
620 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
621 IN PSTRING Data,
622 IN PCONTEXT Context)
623 {
624 STRING Header;
625 PDBGKD_GET_SET_BUS_DATA GetBusData = &State->u.GetSetBusData;
626 ULONG Length;
627
628 /* Setup the header */
629 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
630 Header.Buffer = (PCHAR)State;
631 ASSERT(Data->Length == 0);
632
633 /* Check the length requested */
634 Length = GetBusData->Length;
635 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
636 {
637 /* Use maximum allowed */
638 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
639 }
640
641 /* Call the internal routine */
642 State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType,
643 GetBusData->BusNumber,
644 GetBusData->SlotNumber,
645 Data->Buffer,
646 GetBusData->Offset,
647 Length,
648 &Length);
649
650 /* Return the actual length read */
651 Data->Length = GetBusData->Length = Length;
652
653 /* Send the reply */
654 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
655 &Header,
656 Data,
657 &KdpContext);
658 }
659
660 VOID
661 NTAPI
662 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
663 IN PSTRING Data,
664 IN PCONTEXT Context)
665 {
666 STRING Header;
667 PDBGKD_GET_SET_BUS_DATA SetBusData = &State->u.GetSetBusData;
668 ULONG Length;
669
670 /* Setup the header */
671 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
672 Header.Buffer = (PCHAR)State;
673
674 /* Call the internal routine */
675 State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType,
676 SetBusData->BusNumber,
677 SetBusData->SlotNumber,
678 Data->Buffer,
679 SetBusData->Offset,
680 SetBusData->Length,
681 &Length);
682
683 /* Return the actual length written */
684 SetBusData->Length = Length;
685
686 /* Send the reply */
687 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
688 &Header,
689 Data,
690 &KdpContext);
691 }
692
693 VOID
694 NTAPI
695 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
696 IN PSTRING Data,
697 IN PCONTEXT Context)
698 {
699 STRING Header;
700 PDBGKD_READ_WRITE_IO64 ReadIo = &State->u.ReadWriteIo;
701
702 /* Setup the header */
703 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
704 Header.Buffer = (PCHAR)State;
705 ASSERT(Data->Length == 0);
706
707 /*
708 * Clear the value so 1 or 2 byte reads
709 * don't leave the higher bits unmodified
710 */
711 ReadIo->DataValue = 0;
712
713 /* Call the internal routine */
714 State->ReturnStatus = KdpSysReadIoSpace(Isa,
715 0,
716 1,
717 ReadIo->IoAddress,
718 &ReadIo->DataValue,
719 ReadIo->DataSize,
720 &ReadIo->DataSize);
721
722 /* Send the reply */
723 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
724 &Header,
725 NULL,
726 &KdpContext);
727 }
728
729 VOID
730 NTAPI
731 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
732 IN PSTRING Data,
733 IN PCONTEXT Context)
734 {
735 STRING Header;
736 PDBGKD_READ_WRITE_IO64 WriteIo = &State->u.ReadWriteIo;
737
738 /* Setup the header */
739 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
740 Header.Buffer = (PCHAR)State;
741 ASSERT(Data->Length == 0);
742
743 /* Call the internal routine */
744 State->ReturnStatus = KdpSysWriteIoSpace(Isa,
745 0,
746 1,
747 WriteIo->IoAddress,
748 &WriteIo->DataValue,
749 WriteIo->DataSize,
750 &WriteIo->DataSize);
751
752 /* Send the reply */
753 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
754 &Header,
755 NULL,
756 &KdpContext);
757 }
758
759 VOID
760 NTAPI
761 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
762 IN PSTRING Data,
763 IN PCONTEXT Context)
764 {
765 STRING Header;
766 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended = &State->u.
767 ReadWriteIoExtended;
768
769 /* Setup the header */
770 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
771 Header.Buffer = (PCHAR)State;
772 ASSERT(Data->Length == 0);
773
774 /*
775 * Clear the value so 1 or 2 byte reads
776 * don't leave the higher bits unmodified
777 */
778 ReadIoExtended->DataValue = 0;
779
780 /* Call the internal routine */
781 State->ReturnStatus = KdpSysReadIoSpace(ReadIoExtended->InterfaceType,
782 ReadIoExtended->BusNumber,
783 ReadIoExtended->AddressSpace,
784 ReadIoExtended->IoAddress,
785 &ReadIoExtended->DataValue,
786 ReadIoExtended->DataSize,
787 &ReadIoExtended->DataSize);
788
789 /* Send the reply */
790 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
791 &Header,
792 NULL,
793 &KdpContext);
794 }
795
796 VOID
797 NTAPI
798 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
799 IN PSTRING Data,
800 IN PCONTEXT Context)
801 {
802 STRING Header;
803 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended = &State->u.
804 ReadWriteIoExtended;
805
806 /* Setup the header */
807 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
808 Header.Buffer = (PCHAR)State;
809 ASSERT(Data->Length == 0);
810
811 /* Call the internal routine */
812 State->ReturnStatus = KdpSysReadIoSpace(WriteIoExtended->InterfaceType,
813 WriteIoExtended->BusNumber,
814 WriteIoExtended->AddressSpace,
815 WriteIoExtended->IoAddress,
816 &WriteIoExtended->DataValue,
817 WriteIoExtended->DataSize,
818 &WriteIoExtended->DataSize);
819
820 /* Send the reply */
821 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
822 &Header,
823 NULL,
824 &KdpContext);
825 }
826
827 VOID
828 NTAPI
829 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State)
830 {
831 STRING Header;
832
833 /* Setup the header */
834 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
835 Header.Buffer = (PCHAR)State;
836
837 /* Call the internal routine */
838 State->ReturnStatus = KdpSysCheckLowMemory(0x4);
839
840 /* Send the reply */
841 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
842 &Header,
843 NULL,
844 &KdpContext);
845 }
846
847 KCONTINUE_STATUS
848 NTAPI
849 KdpSendWaitContinue(IN ULONG PacketType,
850 IN PSTRING SendHeader,
851 IN PSTRING SendData OPTIONAL,
852 IN OUT PCONTEXT Context)
853 {
854 STRING Data, Header;
855 DBGKD_MANIPULATE_STATE64 ManipulateState;
856 ULONG Length;
857 KDSTATUS RecvCode;
858
859 /* Setup the Manipulate State structure */
860 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
861 Header.Buffer = (PCHAR)&ManipulateState;
862 Data.MaximumLength = sizeof(KdpMessageBuffer);
863 Data.Buffer = KdpMessageBuffer;
864 //KdpContextSent = FALSE;
865
866 SendPacket:
867 /* Send the Packet */
868 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
869
870 /* If the debugger isn't present anymore, just return success */
871 if (KdDebuggerNotPresent) return ContinueSuccess;
872
873 /* Main processing Loop */
874 for (;;)
875 {
876 /* Receive Loop */
877 do
878 {
879 /* Wait to get a reply to our packet */
880 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
881 &Header,
882 &Data,
883 &Length,
884 &KdpContext);
885
886 /* If we got a resend request, do it */
887 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
888 } while (RecvCode == KdPacketTimedOut);
889
890 /* Now check what API we got */
891 switch (ManipulateState.ApiNumber)
892 {
893 case DbgKdReadVirtualMemoryApi:
894
895 /* Read virtual memory */
896 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
897 break;
898
899 case DbgKdWriteVirtualMemoryApi:
900
901 /* Write virtual memory */
902 KdpWriteVirtualMemory(&ManipulateState, &Data, Context);
903 break;
904
905 case DbgKdGetContextApi:
906
907 /* Get the current context */
908 KdpGetContext(&ManipulateState, &Data, Context);
909 break;
910
911 case DbgKdSetContextApi:
912
913 /* Set a new context */
914 KdpSetContext(&ManipulateState, &Data, Context);
915 break;
916
917 case DbgKdWriteBreakPointApi:
918
919 /* Write the breakpoint */
920 KdpWriteBreakpoint(&ManipulateState, &Data, Context);
921 break;
922
923 case DbgKdRestoreBreakPointApi:
924
925 /* Restore the breakpoint */
926 KdpRestoreBreakpoint(&ManipulateState, &Data, Context);
927 break;
928
929 case DbgKdContinueApi:
930
931 /* Simply continue */
932 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);
933
934 case DbgKdReadControlSpaceApi:
935
936 /* Read control space */
937 KdpReadControlSpace(&ManipulateState, &Data, Context);
938 break;
939
940 case DbgKdWriteControlSpaceApi:
941
942 /* Write control space */
943 KdpWriteControlSpace(&ManipulateState, &Data, Context);
944 break;
945
946 case DbgKdReadIoSpaceApi:
947
948 /* Read I/O Space */
949 KdpReadIoSpace(&ManipulateState, &Data, Context);
950 break;
951
952 case DbgKdWriteIoSpaceApi:
953
954 /* Write I/O Space */
955 KdpWriteIoSpace(&ManipulateState, &Data, Context);
956 break;
957
958 case DbgKdRebootApi:
959
960 /* Reboot the system */
961 HalReturnToFirmware(HalRebootRoutine);
962 break;
963
964 case DbgKdContinueApi2:
965
966 /* Check if caller reports success */
967 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))
968 {
969 /* Update the state */
970 KdpGetStateChange(&ManipulateState, Context);
971 return ContinueSuccess;
972 }
973 else
974 {
975 /* Return an error */
976 return ContinueError;
977 }
978
979 case DbgKdReadPhysicalMemoryApi:
980
981 /* Read physical memory */
982 KdpReadPhysicalmemory(&ManipulateState, &Data, Context);
983 break;
984
985 case DbgKdWritePhysicalMemoryApi:
986
987 /* Write physical memory */
988 KdpWritePhysicalmemory(&ManipulateState, &Data, Context);
989 break;
990
991 case DbgKdQuerySpecialCallsApi:
992
993 /* FIXME: TODO */
994 KdpDprintf("DbgKdQuerySpecialCallsApi called\n");
995 while (TRUE);
996 break;
997
998 case DbgKdSetSpecialCallApi:
999
1000 /* FIXME: TODO */
1001 KdpDprintf("DbgKdSetSpecialCallApi called\n");
1002 while (TRUE);
1003 break;
1004
1005 case DbgKdClearSpecialCallsApi:
1006
1007 /* FIXME: TODO */
1008 KdpDprintf("DbgKdClearSpecialCallsApi called\n");
1009 while (TRUE);
1010 break;
1011
1012 case DbgKdSetInternalBreakPointApi:
1013
1014 /* FIXME: TODO */
1015 KdpDprintf("DbgKdSetInternalBreakPointApi called\n");
1016 while (TRUE);
1017 break;
1018
1019 case DbgKdGetInternalBreakPointApi:
1020
1021 /* FIXME: TODO */
1022 KdpDprintf("DbgKdGetInternalBreakPointApi called\n");
1023 while (TRUE);
1024 break;
1025
1026 case DbgKdReadIoSpaceExtendedApi:
1027
1028 /* Read I/O Space */
1029 KdpReadIoSpaceExtended(&ManipulateState, &Data, Context);
1030 break;
1031
1032 case DbgKdWriteIoSpaceExtendedApi:
1033
1034 /* Write I/O Space */
1035 KdpWriteIoSpaceExtended(&ManipulateState, &Data, Context);
1036 break;
1037
1038 case DbgKdGetVersionApi:
1039
1040 /* Get version data */
1041 KdpGetVersion(&ManipulateState);
1042 break;
1043
1044 case DbgKdWriteBreakPointExApi:
1045
1046 /* Write the breakpoint and check if it failed */
1047 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState,
1048 &Data,
1049 Context)))
1050 {
1051 /* Return an error */
1052 return ContinueError;
1053 }
1054 break;
1055
1056 case DbgKdRestoreBreakPointExApi:
1057
1058 /* Restore the breakpoint */
1059 KdpRestoreBreakPointEx(&ManipulateState, &Data, Context);
1060 break;
1061
1062 case DbgKdCauseBugCheckApi:
1063
1064 /* Crash the system */
1065 KdpCauseBugCheck(&ManipulateState);
1066 break;
1067
1068 case DbgKdSwitchProcessor:
1069
1070 /* FIXME: TODO */
1071 KdpDprintf("DbgKdSwitchProcessor called\n");
1072 while (TRUE);
1073 break;
1074
1075 case DbgKdPageInApi:
1076
1077 /* FIXME: TODO */
1078 KdpDprintf("DbgKdPageInApi called\n");
1079 while (TRUE);
1080 break;
1081
1082 case DbgKdReadMachineSpecificRegister:
1083
1084 /* Read from the specified MSR */
1085 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context);
1086 break;
1087
1088 case DbgKdWriteMachineSpecificRegister:
1089
1090 /* Write to the specified MSR */
1091 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context);
1092 break;
1093
1094 case DbgKdSearchMemoryApi:
1095
1096 /* Search memory */
1097 KdpSearchMemory(&ManipulateState, &Data, Context);
1098 break;
1099
1100 case DbgKdGetBusDataApi:
1101
1102 /* Read from the bus */
1103 KdpGetBusData(&ManipulateState, &Data, Context);
1104 break;
1105
1106 case DbgKdSetBusDataApi:
1107
1108 /* Write to the bus */
1109 KdpSetBusData(&ManipulateState, &Data, Context);
1110 break;
1111
1112 case DbgKdCheckLowMemoryApi:
1113
1114 /* Check for memory corruption in the lower 4 GB */
1115 KdpCheckLowMemory(&ManipulateState);
1116 break;
1117
1118 case DbgKdClearAllInternalBreakpointsApi:
1119
1120 /* Just clear the counter */
1121 KdpNumInternalBreakpoints = 0;
1122 break;
1123
1124 case DbgKdFillMemoryApi:
1125
1126 /* Fill memory */
1127 KdpFillMemory(&ManipulateState, &Data, Context);
1128 break;
1129
1130 case DbgKdQueryMemoryApi:
1131
1132 /* Query memory */
1133 KdpQueryMemory(&ManipulateState, Context);
1134 break;
1135
1136 case DbgKdSwitchPartition:
1137
1138 /* FIXME: TODO */
1139 KdpDprintf("DbgKdSwitchPartition called\n");
1140 while (TRUE);
1141 break;
1142
1143 /* Unsupported Message */
1144 default:
1145
1146 /* Setup an empty message, with failure */
1147 KdpDprintf("Received Unhandled API %lx\n", ManipulateState.ApiNumber);
1148 Data.Length = 0;
1149 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
1150
1151 /* Send it */
1152 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1153 &Header,
1154 &Data,
1155 &KdpContext);
1156 break;
1157 }
1158 }
1159 }
1160
1161 BOOLEAN
1162 NTAPI
1163 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
1164 IN PKD_SYMBOLS_INFO SymbolInfo,
1165 IN BOOLEAN Unload,
1166 IN OUT PCONTEXT Context)
1167 {
1168 PSTRING ExtraData;
1169 STRING Data, Header;
1170 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
1171 KCONTINUE_STATUS Status;
1172
1173 /* Start wait loop */
1174 do
1175 {
1176 /* Build the architecture common parts of the message */
1177 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
1178 Context,
1179 &WaitStateChange);
1180
1181 /* Now finish creating the structure */
1182 KdpSetContextState(&WaitStateChange, Context);
1183
1184 /* Fill out load data */
1185 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
1186 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll;
1187 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
1188 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
1189 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
1190
1191 /* Check if we have a symbol name */
1192 if (PathName)
1193 {
1194 /* Setup the information */
1195 WaitStateChange.u.LoadSymbols.PathNameLength = PathName->Length;
1196 RtlCopyMemory(KdpPathBuffer, PathName->Buffer, PathName->Length);
1197 Data.Buffer = KdpPathBuffer;
1198 Data.Length = WaitStateChange.u.LoadSymbols.PathNameLength;
1199 ExtraData = &Data;
1200 }
1201 else
1202 {
1203 /* No name */
1204 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
1205 ExtraData = NULL;
1206 }
1207
1208 /* Setup the header */
1209 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
1210 Header.Buffer = (PCHAR)&WaitStateChange;
1211
1212 /* Send the packet */
1213 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1214 &Header,
1215 ExtraData,
1216 Context);
1217 } while (Status == ContinueProcessorReselected);
1218
1219 /* Return status */
1220 return Status;
1221 }
1222
1223 BOOLEAN
1224 NTAPI
1225 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
1226 IN OUT PCONTEXT Context,
1227 IN BOOLEAN SecondChanceException)
1228 {
1229 STRING Header, Data;
1230 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
1231 KCONTINUE_STATUS Status;
1232
1233 /* Start report loop */
1234 do
1235 {
1236 /* Build the architecture common parts of the message */
1237 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
1238
1239 /* Copy the Exception Record and set First Chance flag */
1240 CopyExceptionRecord(ExceptionRecord,
1241 &WaitStateChange.u.Exception.ExceptionRecord);
1242 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
1243
1244 /* Now finish creating the structure */
1245 KdpSetContextState(&WaitStateChange, Context);
1246
1247 /* Setup the actual header to send to KD */
1248 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
1249 Header.Buffer = (PCHAR)&WaitStateChange;
1250
1251 /* Setup the trace data */
1252 DumpTraceData(&Data);
1253
1254 /* Send State Change packet and wait for a reply */
1255 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1256 &Header,
1257 &Data,
1258 Context);
1259 } while (Status == ContinueProcessorReselected);
1260
1261 /* Return */
1262 return Status;
1263 }
1264
1265 VOID
1266 NTAPI
1267 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1268 IN PVOID DeferredContext,
1269 IN PVOID SystemArgument1,
1270 IN PVOID SystemArgument2)
1271 {
1272 LONG OldSlip, NewSlip, PendingSlip;
1273
1274 /* Get the current pending slip */
1275 PendingSlip = KdpTimeSlipPending;
1276 do
1277 {
1278 /* Save the old value and either disable or enable it now. */
1279 OldSlip = PendingSlip;
1280 NewSlip = OldSlip > 1 ? 1 : 0;
1281
1282 /* Try to change the value */
1283 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1284 NewSlip,
1285 OldSlip) != OldSlip);
1286
1287 /* If the New Slip value is 1, then do the Time Slipping */
1288 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1289 }
1290
1291 VOID
1292 NTAPI
1293 KdpTimeSlipWork(IN PVOID Context)
1294 {
1295 KIRQL OldIrql;
1296 LARGE_INTEGER DueTime;
1297
1298 /* Update the System time from the CMOS */
1299 ExAcquireTimeRefreshLock(FALSE);
1300 ExUpdateSystemTimeFromCmos(FALSE, 0);
1301 ExReleaseTimeRefreshLock();
1302
1303 /* Check if we have a registered Time Slip Event and signal it */
1304 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1305 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1306 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1307
1308 /* Delay the DPC until it runs next time */
1309 DueTime.QuadPart = -1800000000;
1310 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1311 }
1312
1313 BOOLEAN
1314 NTAPI
1315 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
1316 IN OUT PCONTEXT ContextRecord,
1317 IN BOOLEAN SecondChanceException)
1318 {
1319 BOOLEAN Status;
1320
1321 /* Save the port data */
1322 KdSave(FALSE);
1323
1324 /* Report a state change */
1325 Status = KdpReportExceptionStateChange(ExceptionRecord,
1326 ContextRecord,
1327 SecondChanceException);
1328
1329 /* Restore the port data and return */
1330 KdRestore(FALSE);
1331 return Status;
1332 }
1333
1334 LARGE_INTEGER
1335 NTAPI
1336 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1337 {
1338 LARGE_INTEGER Null = {{0}};
1339
1340 /* Check if interrupts were disabled */
1341 if (!KeGetTrapFrameInterruptState(TrapFrame))
1342 {
1343 /* Nothing to return */
1344 return Null;
1345 }
1346
1347 /* Otherwise, do the call */
1348 return KeQueryPerformanceCounter(NULL);
1349 }
1350
1351 BOOLEAN
1352 NTAPI
1353 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1354 IN PKEXCEPTION_FRAME ExceptionFrame)
1355 {
1356 BOOLEAN Entered;
1357
1358 /* Check if we have a trap frame */
1359 if (TrapFrame)
1360 {
1361 /* Calculate the time difference for the enter */
1362 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1363 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1364 KdTimerStart.QuadPart;
1365 }
1366 else
1367 {
1368 /* No trap frame, so can't calculate */
1369 KdTimerStop.QuadPart = 0;
1370 }
1371
1372 /* Save the current IRQL */
1373 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1374
1375 /* Freeze all CPUs */
1376 Entered = KeFreezeExecution(TrapFrame, ExceptionFrame);
1377
1378 /* Lock the port, save the state and set debugger entered */
1379 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1380 KdSave(FALSE);
1381 KdEnteredDebugger = TRUE;
1382
1383 /* Check freeze flag */
1384 if (KiFreezeFlag & 1)
1385 {
1386 /* Print out errror */
1387 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1388 }
1389
1390 /* Check processor state */
1391 if (KiFreezeFlag & 2)
1392 {
1393 /* Print out errror */
1394 KdpDprintf("Some processors not frozen in debugger!\n");
1395 }
1396
1397 /* Make sure we acquired the port */
1398 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n");
1399
1400 /* Return enter state */
1401 return Entered;
1402 }
1403
1404 VOID
1405 NTAPI
1406 KdExitDebugger(IN BOOLEAN Entered)
1407 {
1408 ULONG TimeSlip;
1409
1410 /* Restore the state and unlock the port */
1411 KdRestore(FALSE);
1412 if (KdpPortLocked) KdpPortUnlock();
1413
1414 /* Unfreeze the CPUs */
1415 KeThawExecution(Entered);
1416
1417 /* Compare time with the one from KdEnterDebugger */
1418 if (!KdTimerStop.QuadPart)
1419 {
1420 /* We didn't get a trap frame earlier in so never got the time */
1421 KdTimerStart = KdTimerStop;
1422 }
1423 else
1424 {
1425 /* Query the timer */
1426 KdTimerStart = KeQueryPerformanceCounter(NULL);
1427 }
1428
1429 /* Check if a Time Slip was on queue */
1430 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1431 if (TimeSlip == 1)
1432 {
1433 /* Queue a DPC for the time slip */
1434 InterlockedIncrement(&KdpTimeSlipPending);
1435 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
1436 }
1437 }
1438
1439 NTSTATUS
1440 NTAPI
1441 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)
1442 {
1443 KIRQL OldIrql;
1444
1445 #if defined(__GNUC__)
1446 /* Make gcc happy */
1447 OldIrql = PASSIVE_LEVEL;
1448 #endif
1449
1450 /* Check if we need to acquire the lock */
1451 if (NeedLock)
1452 {
1453 /* Lock the port */
1454 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1455 KdpPortLock();
1456 }
1457
1458 /* Check if we're not disabled */
1459 if (!KdDisableCount)
1460 {
1461 /* Check if we had locked the port before */
1462 if (NeedLock)
1463 {
1464 /* Do the unlock */
1465 KeLowerIrql(OldIrql);
1466 KdpPortUnlock();
1467 }
1468
1469 /* Fail: We're already enabled */
1470 return STATUS_INVALID_PARAMETER;
1471 }
1472
1473 /* Decrease the disable count */
1474 if (!(--KdDisableCount))
1475 {
1476 /* We're now enabled again! Were we enabled before, too? */
1477 if (KdPreviouslyEnabled)
1478 {
1479 /* Reinitialize the Debugger */
1480 KdInitSystem(0, NULL) ;
1481 KdpRestoreAllBreakpoints();
1482 }
1483 }
1484
1485 /* Check if we had locked the port before */
1486 if (NeedLock)
1487 {
1488 /* Yes, now unlock it */
1489 KeLowerIrql(OldIrql);
1490 KdpPortUnlock();
1491 }
1492
1493 /* We're done */
1494 return STATUS_SUCCESS;
1495 }
1496
1497 /* PUBLIC FUNCTIONS **********************************************************/
1498
1499 /*
1500 * @implemented
1501 */
1502 NTSTATUS
1503 NTAPI
1504 KdEnableDebugger(VOID)
1505 {
1506 /* Use the internal routine */
1507 KdpDprintf("KdEnableDebugger called\n");
1508 while (TRUE);
1509 return KdEnableDebuggerWithLock(TRUE);
1510 }
1511
1512 /*
1513 * @unimplemented
1514 */
1515 NTSTATUS
1516 NTAPI
1517 KdSystemDebugControl(IN SYSDBG_COMMAND Command,
1518 IN PVOID InputBuffer,
1519 IN ULONG InputBufferLength,
1520 OUT PVOID OutputBuffer,
1521 IN ULONG OutputBufferLength,
1522 IN OUT PULONG ReturnLength,
1523 IN KPROCESSOR_MODE PreviousMode)
1524 {
1525 /* HACK */
1526 return STATUS_SUCCESS;
1527 }
1528
1529 /*
1530 * @unimplemented
1531 */
1532 NTSTATUS
1533 NTAPI
1534 KdChangeOption(IN KD_OPTION Option,
1535 IN ULONG InBufferBytes OPTIONAL,
1536 IN PVOID InBuffer,
1537 IN ULONG OutBufferBytes OPTIONAL,
1538 OUT PVOID OutBuffer,
1539 OUT PULONG OutBufferNeeded OPTIONAL)
1540 {
1541 /* HACK */
1542 return STATUS_SUCCESS;
1543 }
1544
1545 /*
1546 * @unimplemented
1547 */
1548 NTSTATUS
1549 NTAPI
1550 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
1551 {
1552 /* HACK */
1553 return STATUS_SUCCESS;
1554 }
1555
1556 /*
1557 * @unimplemented
1558 */
1559 NTSTATUS
1560 NTAPI
1561 KdDisableDebugger(VOID)
1562 {
1563 /* HACK */
1564 return STATUS_SUCCESS;
1565 }
1566
1567 /*
1568 * @unimplemented
1569 */
1570 BOOLEAN
1571 NTAPI
1572 KdRefreshDebuggerNotPresent(VOID)
1573 {
1574 /* HACK */
1575 return KdDebuggerNotPresent;
1576 }
1577
1578 NTSTATUS
1579 NTAPI
1580 NtQueryDebugFilterState(ULONG ComponentId,
1581 ULONG Level)
1582 {
1583 /* HACK */
1584 return STATUS_SUCCESS;
1585 }
1586
1587 NTSTATUS
1588 NTAPI
1589 NtSetDebugFilterState(ULONG ComponentId,
1590 ULONG Level,
1591 BOOLEAN State)
1592 {
1593 /* HACK */
1594 return STATUS_SUCCESS;
1595 }
1596