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