Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkdapi.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/kd64/kdapi.c 00005 * PURPOSE: KD64 Public Routines and Internal Support 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Stefan Ginsberg (stefan.ginsberg@reactos.org) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* PRIVATE FUNCTIONS *********************************************************/ 00017 00018 NTSTATUS 00019 NTAPI 00020 KdpCopyMemoryChunks(IN ULONG64 Address, 00021 IN PVOID Buffer, 00022 IN ULONG TotalSize, 00023 IN ULONG ChunkSize, 00024 IN ULONG Flags, 00025 OUT PULONG ActualSize OPTIONAL) 00026 { 00027 NTSTATUS Status; 00028 ULONG RemainingLength, CopyChunk; 00029 00030 /* Check if we didn't get a chunk size or if it is too big */ 00031 if (ChunkSize == 0) 00032 { 00033 /* Default to 4 byte chunks */ 00034 ChunkSize = 4; 00035 } 00036 else if (ChunkSize > MMDBG_COPY_MAX_SIZE) 00037 { 00038 /* Normalize to maximum size */ 00039 ChunkSize = MMDBG_COPY_MAX_SIZE; 00040 } 00041 00042 /* Copy the whole range in aligned chunks */ 00043 RemainingLength = TotalSize; 00044 CopyChunk = 1; 00045 while (RemainingLength > 0) 00046 { 00047 /* 00048 * Determine the best chunk size for this round. 00049 * The ideal size is aligned, isn't larger than the 00050 * the remaining length and respects the chunk limit. 00051 */ 00052 while (((CopyChunk * 2) <= RemainingLength) && 00053 (CopyChunk < ChunkSize) && 00054 ((Address & ((CopyChunk * 2) - 1)) == 0)) 00055 { 00056 /* Increase it */ 00057 CopyChunk *= 2; 00058 } 00059 00060 /* 00061 * The chunk size can be larger than the remaining size if this isn't 00062 * the first round, so check if we need to shrink it back 00063 */ 00064 while (CopyChunk > RemainingLength) 00065 { 00066 /* Shrink it */ 00067 CopyChunk /= 2; 00068 } 00069 00070 /* Do the copy */ 00071 Status = MmDbgCopyMemory(Address, 00072 Buffer, 00073 CopyChunk, 00074 Flags); 00075 if (!NT_SUCCESS(Status)) 00076 { 00077 /* Copy failed, break out */ 00078 break; 00079 } 00080 00081 /* Update pointers and length for the next run */ 00082 Address = Address + CopyChunk; 00083 Buffer = (PVOID)((ULONG_PTR)Buffer + CopyChunk); 00084 RemainingLength = RemainingLength - CopyChunk; 00085 } 00086 00087 /* 00088 * Return the size we managed to copy 00089 * and return success if we could copy the whole range 00090 */ 00091 if (ActualSize) *ActualSize = TotalSize - RemainingLength; 00092 return RemainingLength == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 00093 } 00094 00095 VOID 00096 NTAPI 00097 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State, 00098 IN PCONTEXT Context) 00099 { 00100 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory; 00101 STRING Header; 00102 NTSTATUS Status = STATUS_SUCCESS; 00103 00104 /* Validate the address space */ 00105 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL) 00106 { 00107 /* Check if this is process memory */ 00108 if ((PVOID)(ULONG_PTR)Memory->Address < MmHighestUserAddress) 00109 { 00110 /* It is */ 00111 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS; 00112 } 00113 else 00114 { 00115 /* Check if it's session space */ 00116 if (MmIsSessionAddress((PVOID)(ULONG_PTR)Memory->Address)) 00117 { 00118 /* It is */ 00119 Memory->AddressSpace = DBGKD_QUERY_MEMORY_SESSION; 00120 } 00121 else 00122 { 00123 /* Not session space but some other kernel memory */ 00124 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL; 00125 } 00126 } 00127 00128 /* Set flags */ 00129 Memory->Flags = DBGKD_QUERY_MEMORY_READ | 00130 DBGKD_QUERY_MEMORY_WRITE | 00131 DBGKD_QUERY_MEMORY_EXECUTE; 00132 } 00133 else 00134 { 00135 /* Invalid */ 00136 Status = STATUS_INVALID_PARAMETER; 00137 } 00138 00139 /* Return structure */ 00140 State->ReturnStatus = Status; 00141 Memory->Reserved = 0; 00142 00143 /* Build header */ 00144 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00145 Header.Buffer = (PCHAR)State; 00146 00147 /* Send the packet */ 00148 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00149 &Header, 00150 NULL, 00151 &KdpContext); 00152 } 00153 00154 VOID 00155 NTAPI 00156 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State, 00157 IN PSTRING Data, 00158 IN PCONTEXT Context) 00159 { 00160 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory; 00161 STRING Header; 00162 00163 /* TODO */ 00164 KdpDprintf("Memory Search support is unimplemented!\n"); 00165 00166 /* Send a failure packet */ 00167 State->ReturnStatus = STATUS_UNSUCCESSFUL; 00168 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00169 Header.Buffer = (PCHAR)State; 00170 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00171 &Header, 00172 NULL, 00173 &KdpContext); 00174 } 00175 00176 VOID 00177 NTAPI 00178 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State, 00179 IN PSTRING Data, 00180 IN PCONTEXT Context) 00181 { 00182 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory; 00183 STRING Header; 00184 00185 /* TODO */ 00186 KdpDprintf("Memory Fill support is unimplemented!\n"); 00187 00188 /* Send a failure packet */ 00189 State->ReturnStatus = STATUS_UNSUCCESSFUL; 00190 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00191 Header.Buffer = (PCHAR)State; 00192 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00193 &Header, 00194 NULL, 00195 &KdpContext); 00196 } 00197 00198 VOID 00199 NTAPI 00200 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State, 00201 IN PSTRING Data, 00202 IN PCONTEXT Context) 00203 { 00204 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint; 00205 STRING Header; 00206 00207 /* Build header */ 00208 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00209 Header.Buffer = (PCHAR)State; 00210 ASSERT(Data->Length == 0); 00211 00212 /* Create the breakpoint */ 00213 Breakpoint->BreakPointHandle = 00214 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress); 00215 if (!Breakpoint->BreakPointHandle) 00216 { 00217 /* We failed */ 00218 State->ReturnStatus = STATUS_UNSUCCESSFUL; 00219 } 00220 else 00221 { 00222 /* Success! */ 00223 State->ReturnStatus = STATUS_SUCCESS; 00224 } 00225 00226 /* Send the packet */ 00227 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00228 &Header, 00229 NULL, 00230 &KdpContext); 00231 } 00232 00233 VOID 00234 NTAPI 00235 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State, 00236 IN PSTRING Data, 00237 IN PCONTEXT Context) 00238 { 00239 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint; 00240 STRING Header; 00241 00242 /* Fill out the header */ 00243 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00244 Header.Buffer = (PCHAR)State; 00245 ASSERT(Data->Length == 0); 00246 00247 /* Get the version block */ 00248 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle)) 00249 { 00250 /* We're all good */ 00251 State->ReturnStatus = STATUS_SUCCESS; 00252 } 00253 else 00254 { 00255 /* We failed */ 00256 State->ReturnStatus = STATUS_UNSUCCESSFUL; 00257 } 00258 00259 /* Send the packet */ 00260 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00261 &Header, 00262 NULL, 00263 &KdpContext); 00264 } 00265 00266 NTSTATUS 00267 NTAPI 00268 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State, 00269 IN PSTRING Data, 00270 IN PCONTEXT Context) 00271 { 00272 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx; 00273 STRING Header; 00274 00275 /* TODO */ 00276 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n"); 00277 00278 /* Send a failure packet */ 00279 State->ReturnStatus = STATUS_UNSUCCESSFUL; 00280 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00281 Header.Buffer = (PCHAR)State; 00282 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00283 &Header, 00284 Data, 00285 &KdpContext); 00286 return STATUS_UNSUCCESSFUL; 00287 } 00288 00289 VOID 00290 NTAPI 00291 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State, 00292 IN PSTRING Data, 00293 IN PCONTEXT Context) 00294 { 00295 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx; 00296 STRING Header; 00297 00298 /* TODO */ 00299 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n"); 00300 00301 /* Send a failure packet */ 00302 State->ReturnStatus = STATUS_UNSUCCESSFUL; 00303 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00304 Header.Buffer = (PCHAR)State; 00305 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00306 &Header, 00307 Data, 00308 &KdpContext); 00309 } 00310 00311 VOID 00312 NTAPI 00313 DumpTraceData(IN PSTRING TraceData) 00314 { 00315 /* Update the buffer */ 00316 TraceDataBuffer[0] = TraceDataBufferPosition; 00317 00318 /* Setup the trace data */ 00319 TraceData->Length = (USHORT)(TraceDataBufferPosition * sizeof(ULONG)); 00320 TraceData->Buffer = (PCHAR)TraceDataBuffer; 00321 00322 /* Reset the buffer location */ 00323 TraceDataBufferPosition = 1; 00324 } 00325 00326 VOID 00327 NTAPI 00328 KdpSetCommonState(IN ULONG NewState, 00329 IN PCONTEXT Context, 00330 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange) 00331 { 00332 ULONG InstructionCount; 00333 BOOLEAN HadBreakpoints; 00334 00335 /* Setup common stuff available for all CPU architectures */ 00336 WaitStateChange->NewState = NewState; 00337 WaitStateChange->ProcessorLevel = KeProcessorLevel; 00338 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number; 00339 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors; 00340 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread(); 00341 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context); 00342 00343 /* Zero out the entire Control Report */ 00344 RtlZeroMemory(&WaitStateChange->AnyControlReport, 00345 sizeof(DBGKD_ANY_CONTROL_REPORT)); 00346 00347 /* Now copy the instruction stream and set the count */ 00348 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter, 00349 &WaitStateChange->ControlReport.InstructionStream[0], 00350 DBGKD_MAXSTREAM, 00351 0, 00352 MMDBG_COPY_UNSAFE, 00353 &InstructionCount); 00354 WaitStateChange->ControlReport.InstructionCount = (USHORT)InstructionCount; 00355 00356 /* Clear all the breakpoints in this region */ 00357 HadBreakpoints = 00358 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter, 00359 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter + 00360 WaitStateChange->ControlReport.InstructionCount - 1)); 00361 if (HadBreakpoints) 00362 { 00363 /* Copy the instruction stream again, this time without breakpoints */ 00364 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter, 00365 &WaitStateChange->ControlReport.InstructionStream[0], 00366 InstructionCount, 00367 0, 00368 MMDBG_COPY_UNSAFE, 00369 NULL); 00370 } 00371 } 00372 00373 VOID 00374 NTAPI 00375 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version) 00376 { 00377 /* Copy the version block */ 00378 RtlCopyMemory(Version, &KdVersionBlock, sizeof(DBGKD_GET_VERSION64)); 00379 } 00380 00381 VOID 00382 NTAPI 00383 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State) 00384 { 00385 STRING Header; 00386 00387 /* Fill out the header */ 00388 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00389 Header.Buffer = (PCHAR)State; 00390 00391 /* Get the version block */ 00392 KdpSysGetVersion(&State->u.GetVersion64); 00393 00394 /* Fill out the state */ 00395 State->ApiNumber = DbgKdGetVersionApi; 00396 State->ReturnStatus = STATUS_SUCCESS; 00397 00398 /* Send the packet */ 00399 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00400 &Header, 00401 NULL, 00402 &KdpContext); 00403 } 00404 00405 VOID 00406 NTAPI 00407 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State, 00408 IN PSTRING Data, 00409 IN PCONTEXT Context) 00410 { 00411 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory; 00412 STRING Header; 00413 ULONG Length = ReadMemory->TransferCount; 00414 00415 /* Setup the header */ 00416 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00417 Header.Buffer = (PCHAR)State; 00418 ASSERT(Data->Length == 0); 00419 00420 /* Validate length */ 00421 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) 00422 { 00423 /* Overflow, set it to maximum possible */ 00424 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); 00425 } 00426 00427 /* Do the read */ 00428 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress, 00429 Data->Buffer, 00430 Length, 00431 0, 00432 MMDBG_COPY_UNSAFE, 00433 &Length); 00434 00435 /* Return the actual length read */ 00436 ReadMemory->ActualBytesRead = Length; 00437 Data->Length = (USHORT)Length; 00438 00439 /* Send the packet */ 00440 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00441 &Header, 00442 Data, 00443 &KdpContext); 00444 } 00445 00446 VOID 00447 NTAPI 00448 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State, 00449 IN PSTRING Data, 00450 IN PCONTEXT Context) 00451 { 00452 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory; 00453 STRING Header; 00454 00455 /* Setup the header */ 00456 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00457 Header.Buffer = (PCHAR)State; 00458 00459 /* Do the write */ 00460 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress, 00461 Data->Buffer, 00462 Data->Length, 00463 0, 00464 MMDBG_COPY_UNSAFE | 00465 MMDBG_COPY_WRITE, 00466 &WriteMemory->ActualBytesWritten); 00467 00468 /* Send the packet */ 00469 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00470 &Header, 00471 NULL, 00472 &KdpContext); 00473 } 00474 00475 VOID 00476 NTAPI 00477 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State, 00478 IN PSTRING Data, 00479 IN PCONTEXT Context) 00480 { 00481 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory; 00482 STRING Header; 00483 ULONG Length = ReadMemory->TransferCount; 00484 ULONG Flags, CacheFlags; 00485 00486 /* Setup the header */ 00487 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00488 Header.Buffer = (PCHAR)State; 00489 ASSERT(Data->Length == 0); 00490 00491 /* Validate length */ 00492 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) 00493 { 00494 /* Overflow, set it to maximum possible */ 00495 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); 00496 } 00497 00498 /* Start with the default flags */ 00499 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_PHYSICAL; 00500 00501 /* Get the caching flags and check if a type is specified */ 00502 CacheFlags = ReadMemory->ActualBytesRead; 00503 if (CacheFlags == DBGKD_CACHING_CACHED) 00504 { 00505 /* Cached */ 00506 Flags |= MMDBG_COPY_CACHED; 00507 } 00508 else if (CacheFlags == DBGKD_CACHING_UNCACHED) 00509 { 00510 /* Uncached */ 00511 Flags |= MMDBG_COPY_UNCACHED; 00512 } 00513 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED) 00514 { 00515 /* Write Combined */ 00516 Flags |= MMDBG_COPY_WRITE_COMBINED; 00517 } 00518 00519 /* Do the read */ 00520 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress, 00521 Data->Buffer, 00522 Length, 00523 0, 00524 Flags, 00525 &Length); 00526 00527 /* Return the actual length read */ 00528 ReadMemory->ActualBytesRead = Length; 00529 Data->Length = (USHORT)Length; 00530 00531 /* Send the packet */ 00532 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00533 &Header, 00534 Data, 00535 &KdpContext); 00536 } 00537 00538 VOID 00539 NTAPI 00540 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State, 00541 IN PSTRING Data, 00542 IN PCONTEXT Context) 00543 { 00544 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory; 00545 STRING Header; 00546 ULONG Flags, CacheFlags; 00547 00548 /* Setup the header */ 00549 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00550 Header.Buffer = (PCHAR)State; 00551 00552 /* Start with the default flags */ 00553 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE | MMDBG_COPY_PHYSICAL; 00554 00555 /* Get the caching flags and check if a type is specified */ 00556 CacheFlags = WriteMemory->ActualBytesWritten; 00557 if (CacheFlags == DBGKD_CACHING_CACHED) 00558 { 00559 /* Cached */ 00560 Flags |= MMDBG_COPY_CACHED; 00561 } 00562 else if (CacheFlags == DBGKD_CACHING_UNCACHED) 00563 { 00564 /* Uncached */ 00565 Flags |= MMDBG_COPY_UNCACHED; 00566 } 00567 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED) 00568 { 00569 /* Write Combined */ 00570 Flags |= MMDBG_COPY_WRITE_COMBINED; 00571 } 00572 00573 /* Do the write */ 00574 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress, 00575 Data->Buffer, 00576 Data->Length, 00577 0, 00578 Flags, 00579 &WriteMemory->ActualBytesWritten); 00580 00581 /* Send the packet */ 00582 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00583 &Header, 00584 NULL, 00585 &KdpContext); 00586 } 00587 00588 VOID 00589 NTAPI 00590 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State, 00591 IN PSTRING Data, 00592 IN PCONTEXT Context) 00593 { 00594 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory; 00595 STRING Header; 00596 ULONG Length; 00597 00598 /* Setup the header */ 00599 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00600 Header.Buffer = (PCHAR)State; 00601 ASSERT(Data->Length == 0); 00602 00603 /* Check the length requested */ 00604 Length = ReadMemory->TransferCount; 00605 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) 00606 { 00607 /* Use maximum allowed */ 00608 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); 00609 } 00610 00611 /* Call the internal routine */ 00612 State->ReturnStatus = KdpSysReadControlSpace(State->Processor, 00613 ReadMemory->TargetBaseAddress, 00614 Data->Buffer, 00615 Length, 00616 &Length); 00617 00618 /* Return the actual length read */ 00619 ReadMemory->ActualBytesRead = Length; 00620 Data->Length = (USHORT)Length; 00621 00622 /* Send the reply */ 00623 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00624 &Header, 00625 Data, 00626 &KdpContext); 00627 } 00628 00629 VOID 00630 NTAPI 00631 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State, 00632 IN PSTRING Data, 00633 IN PCONTEXT Context) 00634 { 00635 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory; 00636 STRING Header; 00637 00638 /* Setup the header */ 00639 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00640 Header.Buffer = (PCHAR)State; 00641 00642 /* Call the internal routine */ 00643 State->ReturnStatus = KdpSysWriteControlSpace(State->Processor, 00644 WriteMemory->TargetBaseAddress, 00645 Data->Buffer, 00646 Data->Length, 00647 &WriteMemory->ActualBytesWritten); 00648 00649 /* Send the reply */ 00650 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00651 &Header, 00652 Data, 00653 &KdpContext); 00654 } 00655 00656 VOID 00657 NTAPI 00658 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State, 00659 IN PSTRING Data, 00660 IN PCONTEXT Context) 00661 { 00662 STRING Header; 00663 PCONTEXT TargetContext; 00664 00665 /* Setup the header */ 00666 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00667 Header.Buffer = (PCHAR)State; 00668 ASSERT(Data->Length == 0); 00669 00670 /* Make sure that this is a valid request */ 00671 if (State->Processor < KeNumberProcessors) 00672 { 00673 /* Check if the request is for this CPU */ 00674 if (State->Processor == KeGetCurrentPrcb()->Number) 00675 { 00676 /* We're just copying our own context */ 00677 TargetContext = Context; 00678 } 00679 else 00680 { 00681 /* Get the context from the PRCB array */ 00682 TargetContext = &KiProcessorBlock[State->Processor]-> 00683 ProcessorState.ContextFrame; 00684 } 00685 00686 /* Copy it over to the debugger */ 00687 RtlCopyMemory(Data->Buffer, TargetContext, sizeof(CONTEXT)); 00688 Data->Length = sizeof(CONTEXT); 00689 00690 /* Let the debugger set the context now */ 00691 KdpContextSent = TRUE; 00692 00693 /* Finish up */ 00694 State->ReturnStatus = STATUS_SUCCESS; 00695 } 00696 else 00697 { 00698 /* Invalid request */ 00699 State->ReturnStatus = STATUS_UNSUCCESSFUL; 00700 } 00701 00702 /* Send the reply */ 00703 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00704 &Header, 00705 Data, 00706 &KdpContext); 00707 } 00708 00709 VOID 00710 NTAPI 00711 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State, 00712 IN PSTRING Data, 00713 IN PCONTEXT Context) 00714 { 00715 STRING Header; 00716 PCONTEXT TargetContext; 00717 00718 /* Setup the header */ 00719 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00720 Header.Buffer = (PCHAR)State; 00721 ASSERT(Data->Length == sizeof(CONTEXT)); 00722 00723 /* Make sure that this is a valid request */ 00724 if ((State->Processor < KeNumberProcessors) && (KdpContextSent == TRUE)) 00725 { 00726 /* Check if the request is for this CPU */ 00727 if (State->Processor == KeGetCurrentPrcb()->Number) 00728 { 00729 /* We're just copying our own context */ 00730 TargetContext = Context; 00731 } 00732 else 00733 { 00734 /* Get the context from the PRCB array */ 00735 TargetContext = &KiProcessorBlock[State->Processor]-> 00736 ProcessorState.ContextFrame; 00737 } 00738 00739 /* Copy the new context to it */ 00740 RtlCopyMemory(TargetContext, Data->Buffer, sizeof(CONTEXT)); 00741 00742 /* Finish up */ 00743 State->ReturnStatus = STATUS_SUCCESS; 00744 } 00745 else 00746 { 00747 /* Invalid request */ 00748 State->ReturnStatus = STATUS_UNSUCCESSFUL; 00749 } 00750 00751 /* Send the reply */ 00752 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00753 &Header, 00754 NULL, 00755 &KdpContext); 00756 } 00757 00758 VOID 00759 NTAPI 00760 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State) 00761 { 00762 /* Crash with the special code */ 00763 KeBugCheck(MANUALLY_INITIATED_CRASH); 00764 } 00765 00766 VOID 00767 NTAPI 00768 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State, 00769 IN PSTRING Data, 00770 IN PCONTEXT Context) 00771 { 00772 STRING Header; 00773 PDBGKD_READ_WRITE_MSR ReadMsr = &State->u.ReadWriteMsr; 00774 LARGE_INTEGER MsrValue; 00775 00776 /* Setup the header */ 00777 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00778 Header.Buffer = (PCHAR)State; 00779 ASSERT(Data->Length == 0); 00780 00781 /* Call the internal routine */ 00782 State->ReturnStatus = KdpSysReadMsr(ReadMsr->Msr, 00783 &MsrValue); 00784 00785 /* Return the data */ 00786 ReadMsr->DataValueLow = MsrValue.LowPart; 00787 ReadMsr->DataValueHigh = MsrValue.HighPart; 00788 00789 /* Send the reply */ 00790 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00791 &Header, 00792 NULL, 00793 &KdpContext); 00794 } 00795 00796 VOID 00797 NTAPI 00798 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State, 00799 IN PSTRING Data, 00800 IN PCONTEXT Context) 00801 { 00802 STRING Header; 00803 PDBGKD_READ_WRITE_MSR WriteMsr = &State->u.ReadWriteMsr; 00804 LARGE_INTEGER MsrValue; 00805 00806 /* Setup the header */ 00807 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00808 Header.Buffer = (PCHAR)State; 00809 ASSERT(Data->Length == 0); 00810 00811 /* Call the internal routine */ 00812 MsrValue.LowPart = WriteMsr->DataValueLow; 00813 MsrValue.HighPart = WriteMsr->DataValueHigh; 00814 State->ReturnStatus = KdpSysWriteMsr(WriteMsr->Msr, 00815 &MsrValue); 00816 00817 /* Send the reply */ 00818 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00819 &Header, 00820 NULL, 00821 &KdpContext); 00822 } 00823 00824 VOID 00825 NTAPI 00826 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State, 00827 IN PSTRING Data, 00828 IN PCONTEXT Context) 00829 { 00830 STRING Header; 00831 PDBGKD_GET_SET_BUS_DATA GetBusData = &State->u.GetSetBusData; 00832 ULONG Length; 00833 00834 /* Setup the header */ 00835 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00836 Header.Buffer = (PCHAR)State; 00837 ASSERT(Data->Length == 0); 00838 00839 /* Check the length requested */ 00840 Length = GetBusData->Length; 00841 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) 00842 { 00843 /* Use maximum allowed */ 00844 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); 00845 } 00846 00847 /* Call the internal routine */ 00848 State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType, 00849 GetBusData->BusNumber, 00850 GetBusData->SlotNumber, 00851 GetBusData->Offset, 00852 Data->Buffer, 00853 Length, 00854 &Length); 00855 00856 /* Return the actual length read */ 00857 GetBusData->Length = Length; 00858 Data->Length = (USHORT)Length; 00859 00860 /* Send the reply */ 00861 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00862 &Header, 00863 Data, 00864 &KdpContext); 00865 } 00866 00867 VOID 00868 NTAPI 00869 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State, 00870 IN PSTRING Data, 00871 IN PCONTEXT Context) 00872 { 00873 STRING Header; 00874 PDBGKD_GET_SET_BUS_DATA SetBusData = &State->u.GetSetBusData; 00875 ULONG Length; 00876 00877 /* Setup the header */ 00878 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00879 Header.Buffer = (PCHAR)State; 00880 00881 /* Call the internal routine */ 00882 State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType, 00883 SetBusData->BusNumber, 00884 SetBusData->SlotNumber, 00885 SetBusData->Offset, 00886 Data->Buffer, 00887 SetBusData->Length, 00888 &Length); 00889 00890 /* Return the actual length written */ 00891 SetBusData->Length = Length; 00892 00893 /* Send the reply */ 00894 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00895 &Header, 00896 NULL, 00897 &KdpContext); 00898 } 00899 00900 VOID 00901 NTAPI 00902 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State, 00903 IN PSTRING Data, 00904 IN PCONTEXT Context) 00905 { 00906 STRING Header; 00907 PDBGKD_READ_WRITE_IO64 ReadIo = &State->u.ReadWriteIo; 00908 00909 /* Setup the header */ 00910 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00911 Header.Buffer = (PCHAR)State; 00912 ASSERT(Data->Length == 0); 00913 00914 /* 00915 * Clear the value so 1 or 2 byte reads 00916 * don't leave the higher bits unmodified 00917 */ 00918 ReadIo->DataValue = 0; 00919 00920 /* Call the internal routine */ 00921 State->ReturnStatus = KdpSysReadIoSpace(Isa, 00922 0, 00923 1, 00924 ReadIo->IoAddress, 00925 &ReadIo->DataValue, 00926 ReadIo->DataSize, 00927 &ReadIo->DataSize); 00928 00929 /* Send the reply */ 00930 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00931 &Header, 00932 NULL, 00933 &KdpContext); 00934 } 00935 00936 VOID 00937 NTAPI 00938 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State, 00939 IN PSTRING Data, 00940 IN PCONTEXT Context) 00941 { 00942 STRING Header; 00943 PDBGKD_READ_WRITE_IO64 WriteIo = &State->u.ReadWriteIo; 00944 00945 /* Setup the header */ 00946 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00947 Header.Buffer = (PCHAR)State; 00948 ASSERT(Data->Length == 0); 00949 00950 /* Call the internal routine */ 00951 State->ReturnStatus = KdpSysWriteIoSpace(Isa, 00952 0, 00953 1, 00954 WriteIo->IoAddress, 00955 &WriteIo->DataValue, 00956 WriteIo->DataSize, 00957 &WriteIo->DataSize); 00958 00959 /* Send the reply */ 00960 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00961 &Header, 00962 NULL, 00963 &KdpContext); 00964 } 00965 00966 VOID 00967 NTAPI 00968 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State, 00969 IN PSTRING Data, 00970 IN PCONTEXT Context) 00971 { 00972 STRING Header; 00973 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended = &State->u. 00974 ReadWriteIoExtended; 00975 00976 /* Setup the header */ 00977 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 00978 Header.Buffer = (PCHAR)State; 00979 ASSERT(Data->Length == 0); 00980 00981 /* 00982 * Clear the value so 1 or 2 byte reads 00983 * don't leave the higher bits unmodified 00984 */ 00985 ReadIoExtended->DataValue = 0; 00986 00987 /* Call the internal routine */ 00988 State->ReturnStatus = KdpSysReadIoSpace(ReadIoExtended->InterfaceType, 00989 ReadIoExtended->BusNumber, 00990 ReadIoExtended->AddressSpace, 00991 ReadIoExtended->IoAddress, 00992 &ReadIoExtended->DataValue, 00993 ReadIoExtended->DataSize, 00994 &ReadIoExtended->DataSize); 00995 00996 /* Send the reply */ 00997 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 00998 &Header, 00999 NULL, 01000 &KdpContext); 01001 } 01002 01003 VOID 01004 NTAPI 01005 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State, 01006 IN PSTRING Data, 01007 IN PCONTEXT Context) 01008 { 01009 STRING Header; 01010 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended = &State->u. 01011 ReadWriteIoExtended; 01012 01013 /* Setup the header */ 01014 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 01015 Header.Buffer = (PCHAR)State; 01016 ASSERT(Data->Length == 0); 01017 01018 /* Call the internal routine */ 01019 State->ReturnStatus = KdpSysReadIoSpace(WriteIoExtended->InterfaceType, 01020 WriteIoExtended->BusNumber, 01021 WriteIoExtended->AddressSpace, 01022 WriteIoExtended->IoAddress, 01023 &WriteIoExtended->DataValue, 01024 WriteIoExtended->DataSize, 01025 &WriteIoExtended->DataSize); 01026 01027 /* Send the reply */ 01028 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 01029 &Header, 01030 NULL, 01031 &KdpContext); 01032 } 01033 01034 VOID 01035 NTAPI 01036 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State) 01037 { 01038 STRING Header; 01039 01040 /* Setup the header */ 01041 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 01042 Header.Buffer = (PCHAR)State; 01043 01044 /* Call the internal routine */ 01045 State->ReturnStatus = KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE); 01046 01047 /* Send the reply */ 01048 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 01049 &Header, 01050 NULL, 01051 &KdpContext); 01052 } 01053 01054 VOID 01055 NTAPI 01056 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State) 01057 { 01058 STRING Header; 01059 01060 /* Set failure */ 01061 State->ReturnStatus = STATUS_UNSUCCESSFUL; 01062 01063 /* Setup the packet */ 01064 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64); 01065 Header.Buffer = (PCHAR)State; 01066 01067 /* Send it */ 01068 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 01069 &Header, 01070 NULL, 01071 &KdpContext); 01072 } 01073 01074 KCONTINUE_STATUS 01075 NTAPI 01076 KdpSendWaitContinue(IN ULONG PacketType, 01077 IN PSTRING SendHeader, 01078 IN PSTRING SendData OPTIONAL, 01079 IN OUT PCONTEXT Context) 01080 { 01081 STRING Data, Header; 01082 DBGKD_MANIPULATE_STATE64 ManipulateState; 01083 ULONG Length; 01084 KDSTATUS RecvCode; 01085 01086 /* Setup the Manipulate State structure */ 01087 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64); 01088 Header.Buffer = (PCHAR)&ManipulateState; 01089 Data.MaximumLength = sizeof(KdpMessageBuffer); 01090 Data.Buffer = KdpMessageBuffer; 01091 01092 /* 01093 * Reset the context state to ensure the debugger has received 01094 * the current context before it sets it 01095 */ 01096 KdpContextSent = FALSE; 01097 01098 SendPacket: 01099 /* Send the Packet */ 01100 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext); 01101 01102 /* If the debugger isn't present anymore, just return success */ 01103 if (KdDebuggerNotPresent) return ContinueSuccess; 01104 01105 /* Main processing Loop */ 01106 for (;;) 01107 { 01108 /* Receive Loop */ 01109 do 01110 { 01111 /* Wait to get a reply to our packet */ 01112 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE, 01113 &Header, 01114 &Data, 01115 &Length, 01116 &KdpContext); 01117 01118 /* If we got a resend request, do it */ 01119 if (RecvCode == KdPacketNeedsResend) goto SendPacket; 01120 } while (RecvCode == KdPacketTimedOut); 01121 01122 /* Now check what API we got */ 01123 switch (ManipulateState.ApiNumber) 01124 { 01125 case DbgKdReadVirtualMemoryApi: 01126 01127 /* Read virtual memory */ 01128 KdpReadVirtualMemory(&ManipulateState, &Data, Context); 01129 break; 01130 01131 case DbgKdWriteVirtualMemoryApi: 01132 01133 /* Write virtual memory */ 01134 KdpWriteVirtualMemory(&ManipulateState, &Data, Context); 01135 break; 01136 01137 case DbgKdGetContextApi: 01138 01139 /* Get the current context */ 01140 KdpGetContext(&ManipulateState, &Data, Context); 01141 break; 01142 01143 case DbgKdSetContextApi: 01144 01145 /* Set a new context */ 01146 KdpSetContext(&ManipulateState, &Data, Context); 01147 break; 01148 01149 case DbgKdWriteBreakPointApi: 01150 01151 /* Write the breakpoint */ 01152 KdpWriteBreakpoint(&ManipulateState, &Data, Context); 01153 break; 01154 01155 case DbgKdRestoreBreakPointApi: 01156 01157 /* Restore the breakpoint */ 01158 KdpRestoreBreakpoint(&ManipulateState, &Data, Context); 01159 break; 01160 01161 case DbgKdContinueApi: 01162 01163 /* Simply continue */ 01164 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus); 01165 01166 case DbgKdReadControlSpaceApi: 01167 01168 /* Read control space */ 01169 KdpReadControlSpace(&ManipulateState, &Data, Context); 01170 break; 01171 01172 case DbgKdWriteControlSpaceApi: 01173 01174 /* Write control space */ 01175 KdpWriteControlSpace(&ManipulateState, &Data, Context); 01176 break; 01177 01178 case DbgKdReadIoSpaceApi: 01179 01180 /* Read I/O Space */ 01181 KdpReadIoSpace(&ManipulateState, &Data, Context); 01182 break; 01183 01184 case DbgKdWriteIoSpaceApi: 01185 01186 /* Write I/O Space */ 01187 KdpWriteIoSpace(&ManipulateState, &Data, Context); 01188 break; 01189 01190 case DbgKdRebootApi: 01191 01192 /* Reboot the system */ 01193 HalReturnToFirmware(HalRebootRoutine); 01194 break; 01195 01196 case DbgKdContinueApi2: 01197 01198 /* Check if caller reports success */ 01199 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus)) 01200 { 01201 /* Update the state */ 01202 KdpGetStateChange(&ManipulateState, Context); 01203 return ContinueSuccess; 01204 } 01205 else 01206 { 01207 /* Return an error */ 01208 return ContinueError; 01209 } 01210 01211 case DbgKdReadPhysicalMemoryApi: 01212 01213 /* Read physical memory */ 01214 KdpReadPhysicalmemory(&ManipulateState, &Data, Context); 01215 break; 01216 01217 case DbgKdWritePhysicalMemoryApi: 01218 01219 /* Write physical memory */ 01220 KdpWritePhysicalmemory(&ManipulateState, &Data, Context); 01221 break; 01222 01223 case DbgKdQuerySpecialCallsApi: 01224 case DbgKdSetSpecialCallApi: 01225 case DbgKdClearSpecialCallsApi: 01226 01227 /* TODO */ 01228 KdpDprintf("Special Call support is unimplemented!\n"); 01229 KdpNotSupported(&ManipulateState); 01230 break; 01231 01232 case DbgKdSetInternalBreakPointApi: 01233 case DbgKdGetInternalBreakPointApi: 01234 01235 /* TODO */ 01236 KdpDprintf("Internal Breakpoint support is unimplemented!\n"); 01237 KdpNotSupported(&ManipulateState); 01238 break; 01239 01240 case DbgKdReadIoSpaceExtendedApi: 01241 01242 /* Read I/O Space */ 01243 KdpReadIoSpaceExtended(&ManipulateState, &Data, Context); 01244 break; 01245 01246 case DbgKdWriteIoSpaceExtendedApi: 01247 01248 /* Write I/O Space */ 01249 KdpWriteIoSpaceExtended(&ManipulateState, &Data, Context); 01250 break; 01251 01252 case DbgKdGetVersionApi: 01253 01254 /* Get version data */ 01255 KdpGetVersion(&ManipulateState); 01256 break; 01257 01258 case DbgKdWriteBreakPointExApi: 01259 01260 /* Write the breakpoint and check if it failed */ 01261 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState, 01262 &Data, 01263 Context))) 01264 { 01265 /* Return an error */ 01266 return ContinueError; 01267 } 01268 break; 01269 01270 case DbgKdRestoreBreakPointExApi: 01271 01272 /* Restore the breakpoint */ 01273 KdpRestoreBreakPointEx(&ManipulateState, &Data, Context); 01274 break; 01275 01276 case DbgKdCauseBugCheckApi: 01277 01278 /* Crash the system */ 01279 KdpCauseBugCheck(&ManipulateState); 01280 break; 01281 01282 case DbgKdSwitchProcessor: 01283 01284 /* TODO */ 01285 KdpDprintf("Processor Switch support is unimplemented!\n"); 01286 KdpNotSupported(&ManipulateState); 01287 break; 01288 01289 case DbgKdPageInApi: 01290 01291 /* TODO */ 01292 KdpDprintf("Page-In support is unimplemented!\n"); 01293 KdpNotSupported(&ManipulateState); 01294 break; 01295 01296 case DbgKdReadMachineSpecificRegister: 01297 01298 /* Read from the specified MSR */ 01299 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context); 01300 break; 01301 01302 case DbgKdWriteMachineSpecificRegister: 01303 01304 /* Write to the specified MSR */ 01305 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context); 01306 break; 01307 01308 case DbgKdSearchMemoryApi: 01309 01310 /* Search memory */ 01311 KdpSearchMemory(&ManipulateState, &Data, Context); 01312 break; 01313 01314 case DbgKdGetBusDataApi: 01315 01316 /* Read from the bus */ 01317 KdpGetBusData(&ManipulateState, &Data, Context); 01318 break; 01319 01320 case DbgKdSetBusDataApi: 01321 01322 /* Write to the bus */ 01323 KdpSetBusData(&ManipulateState, &Data, Context); 01324 break; 01325 01326 case DbgKdCheckLowMemoryApi: 01327 01328 /* Check for memory corruption in the lower 4 GB */ 01329 KdpCheckLowMemory(&ManipulateState); 01330 break; 01331 01332 case DbgKdClearAllInternalBreakpointsApi: 01333 01334 /* Just clear the counter */ 01335 KdpNumInternalBreakpoints = 0; 01336 break; 01337 01338 case DbgKdFillMemoryApi: 01339 01340 /* Fill memory */ 01341 KdpFillMemory(&ManipulateState, &Data, Context); 01342 break; 01343 01344 case DbgKdQueryMemoryApi: 01345 01346 /* Query memory */ 01347 KdpQueryMemory(&ManipulateState, Context); 01348 break; 01349 01350 case DbgKdSwitchPartition: 01351 01352 /* TODO */ 01353 KdpDprintf("Partition Switch support is unimplemented!\n"); 01354 KdpNotSupported(&ManipulateState); 01355 break; 01356 01357 /* Unsupported Message */ 01358 default: 01359 01360 /* Setup an empty message, with failure */ 01361 KdpDprintf("Received Unhandled API %lx\n", ManipulateState.ApiNumber); 01362 Data.Length = 0; 01363 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL; 01364 01365 /* Send it */ 01366 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE, 01367 &Header, 01368 &Data, 01369 &KdpContext); 01370 break; 01371 } 01372 } 01373 } 01374 01375 VOID 01376 NTAPI 01377 KdpReportLoadSymbolsStateChange(IN PSTRING PathName, 01378 IN PKD_SYMBOLS_INFO SymbolInfo, 01379 IN BOOLEAN Unload, 01380 IN OUT PCONTEXT Context) 01381 { 01382 PSTRING ExtraData; 01383 STRING Data, Header; 01384 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 01385 ULONG PathNameLength; 01386 KCONTINUE_STATUS Status; 01387 01388 /* Start wait loop */ 01389 do 01390 { 01391 /* Build the architecture common parts of the message */ 01392 KdpSetCommonState(DbgKdLoadSymbolsStateChange, 01393 Context, 01394 &WaitStateChange); 01395 01396 /* Now finish creating the structure */ 01397 KdpSetContextState(&WaitStateChange, Context); 01398 01399 /* Fill out load data */ 01400 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload; 01401 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll; 01402 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId; 01403 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum; 01404 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage; 01405 01406 /* Check if we have a path name */ 01407 if (PathName) 01408 { 01409 /* Copy it to the path buffer */ 01410 KdpCopyMemoryChunks((ULONG_PTR)PathName->Buffer, 01411 KdpPathBuffer, 01412 PathName->Length, 01413 0, 01414 MMDBG_COPY_UNSAFE, 01415 &PathNameLength); 01416 01417 /* Null terminate */ 01418 KdpPathBuffer[PathNameLength++] = ANSI_NULL; 01419 01420 /* Set the path length */ 01421 WaitStateChange.u.LoadSymbols.PathNameLength = PathNameLength; 01422 01423 /* Set up the data */ 01424 Data.Buffer = KdpPathBuffer; 01425 Data.Length = (USHORT)PathNameLength; 01426 ExtraData = &Data; 01427 } 01428 else 01429 { 01430 /* No name */ 01431 WaitStateChange.u.LoadSymbols.PathNameLength = 0; 01432 ExtraData = NULL; 01433 } 01434 01435 /* Setup the header */ 01436 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 01437 Header.Buffer = (PCHAR)&WaitStateChange; 01438 01439 /* Send the packet */ 01440 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 01441 &Header, 01442 ExtraData, 01443 Context); 01444 } while (Status == ContinueProcessorReselected); 01445 } 01446 01447 VOID 01448 NTAPI 01449 KdpReportCommandStringStateChange(IN PSTRING NameString, 01450 IN PSTRING CommandString, 01451 IN OUT PCONTEXT Context) 01452 { 01453 STRING Header, Data; 01454 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 01455 ULONG Length, ActualLength, TotalLength; 01456 KCONTINUE_STATUS Status; 01457 01458 /* Start wait loop */ 01459 do 01460 { 01461 /* Build the architecture common parts of the message */ 01462 KdpSetCommonState(DbgKdCommandStringStateChange, 01463 Context, 01464 &WaitStateChange); 01465 01466 /* Set the context */ 01467 KdpSetContextState(&WaitStateChange, Context); 01468 01469 /* Clear the command string structure */ 01470 RtlZeroMemory(&WaitStateChange.u.CommandString, 01471 sizeof(DBGKD_COMMAND_STRING)); 01472 01473 /* Normalize name string to max */ 01474 Length = min(128 - 1, NameString->Length); 01475 01476 /* Copy it to the message buffer */ 01477 KdpCopyMemoryChunks((ULONG_PTR)NameString->Buffer, 01478 KdpMessageBuffer, 01479 Length, 01480 0, 01481 MMDBG_COPY_UNSAFE, 01482 &ActualLength); 01483 01484 /* Null terminate and calculate the total length */ 01485 TotalLength = ActualLength; 01486 KdpMessageBuffer[TotalLength++] = ANSI_NULL; 01487 01488 /* Check if the command string is too long */ 01489 Length = CommandString->Length; 01490 if (Length > (PACKET_MAX_SIZE - 01491 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength)) 01492 { 01493 /* Use maximum possible size */ 01494 Length = (PACKET_MAX_SIZE - 01495 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength); 01496 } 01497 01498 /* Copy it to the message buffer */ 01499 KdpCopyMemoryChunks((ULONG_PTR)CommandString->Buffer, 01500 KdpMessageBuffer + TotalLength, 01501 Length, 01502 0, 01503 MMDBG_COPY_UNSAFE, 01504 &ActualLength); 01505 01506 /* Null terminate and calculate the total length */ 01507 TotalLength += ActualLength; 01508 KdpMessageBuffer[TotalLength++] = ANSI_NULL; 01509 01510 /* Now set up the header and the data */ 01511 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 01512 Header.Buffer = (PCHAR)&WaitStateChange; 01513 Data.Length = (USHORT)TotalLength; 01514 Data.Buffer = KdpMessageBuffer; 01515 01516 /* Send State Change packet and wait for a reply */ 01517 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 01518 &Header, 01519 &Data, 01520 Context); 01521 } while (Status == ContinueProcessorReselected); 01522 } 01523 01524 BOOLEAN 01525 NTAPI 01526 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord, 01527 IN OUT PCONTEXT Context, 01528 IN BOOLEAN SecondChanceException) 01529 { 01530 STRING Header, Data; 01531 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; 01532 KCONTINUE_STATUS Status; 01533 01534 /* Start report loop */ 01535 do 01536 { 01537 /* Build the architecture common parts of the message */ 01538 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange); 01539 01540 /* Copy the Exception Record and set First Chance flag */ 01541 #if !defined(_WIN64) 01542 ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord, 01543 &WaitStateChange.u.Exception.ExceptionRecord); 01544 #else 01545 RtlCopyMemory(&WaitStateChange.u.Exception.ExceptionRecord, 01546 ExceptionRecord, 01547 sizeof(EXCEPTION_RECORD)); 01548 #endif 01549 WaitStateChange.u.Exception.FirstChance = !SecondChanceException; 01550 01551 /* Now finish creating the structure */ 01552 KdpSetContextState(&WaitStateChange, Context); 01553 01554 /* Setup the actual header to send to KD */ 01555 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE); 01556 Header.Buffer = (PCHAR)&WaitStateChange; 01557 01558 /* Setup the trace data */ 01559 DumpTraceData(&Data); 01560 01561 /* Send State Change packet and wait for a reply */ 01562 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64, 01563 &Header, 01564 &Data, 01565 Context); 01566 } while (Status == ContinueProcessorReselected); 01567 01568 /* Return */ 01569 return Status; 01570 } 01571 01572 VOID 01573 NTAPI 01574 KdpTimeSlipDpcRoutine(IN PKDPC Dpc, 01575 IN PVOID DeferredContext, 01576 IN PVOID SystemArgument1, 01577 IN PVOID SystemArgument2) 01578 { 01579 LONG OldSlip, NewSlip, PendingSlip; 01580 01581 /* Get the current pending slip */ 01582 PendingSlip = KdpTimeSlipPending; 01583 do 01584 { 01585 /* Save the old value and either disable or enable it now. */ 01586 OldSlip = PendingSlip; 01587 NewSlip = OldSlip > 1 ? 1 : 0; 01588 01589 /* Try to change the value */ 01590 } while (InterlockedCompareExchange(&KdpTimeSlipPending, 01591 NewSlip, 01592 OldSlip) != OldSlip); 01593 01594 /* If the New Slip value is 1, then do the Time Slipping */ 01595 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue); 01596 } 01597 01598 VOID 01599 NTAPI 01600 KdpTimeSlipWork(IN PVOID Context) 01601 { 01602 KIRQL OldIrql; 01603 LARGE_INTEGER DueTime; 01604 01605 /* Update the System time from the CMOS */ 01606 ExAcquireTimeRefreshLock(FALSE); 01607 ExUpdateSystemTimeFromCmos(FALSE, 0); 01608 ExReleaseTimeRefreshLock(); 01609 01610 /* Check if we have a registered Time Slip Event and signal it */ 01611 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql); 01612 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE); 01613 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql); 01614 01615 /* Delay the DPC until it runs next time */ 01616 DueTime.QuadPart = -1800000000; 01617 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc); 01618 } 01619 01620 BOOLEAN 01621 NTAPI 01622 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord, 01623 IN OUT PCONTEXT ContextRecord, 01624 IN BOOLEAN SecondChanceException) 01625 { 01626 BOOLEAN Status; 01627 01628 /* Save the port data */ 01629 KdSave(FALSE); 01630 01631 /* Report a state change */ 01632 Status = KdpReportExceptionStateChange(ExceptionRecord, 01633 ContextRecord, 01634 SecondChanceException); 01635 01636 /* Restore the port data and return */ 01637 KdRestore(FALSE); 01638 return Status; 01639 } 01640 01641 LARGE_INTEGER 01642 NTAPI 01643 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame) 01644 { 01645 LARGE_INTEGER Null = {{0}}; 01646 01647 /* Check if interrupts were disabled */ 01648 if (!KeGetTrapFrameInterruptState(TrapFrame)) 01649 { 01650 /* Nothing to return */ 01651 return Null; 01652 } 01653 01654 /* Otherwise, do the call */ 01655 return KeQueryPerformanceCounter(NULL); 01656 } 01657 01658 BOOLEAN 01659 NTAPI 01660 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame, 01661 IN PKEXCEPTION_FRAME ExceptionFrame) 01662 { 01663 BOOLEAN Enable; 01664 01665 /* Check if we have a trap frame */ 01666 if (TrapFrame) 01667 { 01668 /* Calculate the time difference for the enter */ 01669 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame); 01670 KdTimerDifference.QuadPart = KdTimerStop.QuadPart - 01671 KdTimerStart.QuadPart; 01672 } 01673 else 01674 { 01675 /* No trap frame, so can't calculate */ 01676 KdTimerStop.QuadPart = 0; 01677 } 01678 01679 /* Save the current IRQL */ 01680 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql(); 01681 01682 /* Freeze all CPUs */ 01683 Enable = KeFreezeExecution(TrapFrame, ExceptionFrame); 01684 01685 /* Lock the port, save the state and set debugger entered */ 01686 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock); 01687 KdSave(FALSE); 01688 KdEnteredDebugger = TRUE; 01689 01690 /* Check freeze flag */ 01691 if (KiFreezeFlag & 1) 01692 { 01693 /* Print out errror */ 01694 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n"); 01695 } 01696 01697 /* Check processor state */ 01698 if (KiFreezeFlag & 2) 01699 { 01700 /* Print out errror */ 01701 KdpDprintf("Some processors not frozen in debugger!\n"); 01702 } 01703 01704 /* Make sure we acquired the port */ 01705 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n"); 01706 01707 /* Return if interrupts needs to be re-enabled */ 01708 return Enable; 01709 } 01710 01711 VOID 01712 NTAPI 01713 KdExitDebugger(IN BOOLEAN Enable) 01714 { 01715 ULONG TimeSlip; 01716 01717 /* Restore the state and unlock the port */ 01718 KdRestore(FALSE); 01719 if (KdpPortLocked) KdpPortUnlock(); 01720 01721 /* Unfreeze the CPUs */ 01722 KeThawExecution(Enable); 01723 01724 /* Compare time with the one from KdEnterDebugger */ 01725 if (!KdTimerStop.QuadPart) 01726 { 01727 /* We didn't get a trap frame earlier in so never got the time */ 01728 KdTimerStart = KdTimerStop; 01729 } 01730 else 01731 { 01732 /* Query the timer */ 01733 KdTimerStart = KeQueryPerformanceCounter(NULL); 01734 } 01735 01736 /* Check if a Time Slip was on queue */ 01737 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending); 01738 if (TimeSlip == 1) 01739 { 01740 /* Queue a DPC for the time slip */ 01741 InterlockedIncrement(&KdpTimeSlipPending); 01742 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL); 01743 } 01744 } 01745 01746 NTSTATUS 01747 NTAPI 01748 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock) 01749 { 01750 KIRQL OldIrql; 01751 01752 #if defined(__GNUC__) 01753 /* Make gcc happy */ 01754 OldIrql = PASSIVE_LEVEL; 01755 #endif 01756 01757 /* Check if enabling the debugger is blocked */ 01758 if (KdBlockEnable) 01759 { 01760 /* It is, fail the enable */ 01761 return STATUS_ACCESS_DENIED; 01762 } 01763 01764 /* Check if we need to acquire the lock */ 01765 if (NeedLock) 01766 { 01767 /* Lock the port */ 01768 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 01769 KdpPortLock(); 01770 } 01771 01772 /* Check if we're not disabled */ 01773 if (!KdDisableCount) 01774 { 01775 /* Check if we had locked the port before */ 01776 if (NeedLock) 01777 { 01778 /* Do the unlock */ 01779 KeLowerIrql(OldIrql); 01780 KdpPortUnlock(); 01781 01782 /* Fail: We're already enabled */ 01783 return STATUS_INVALID_PARAMETER; 01784 } 01785 else 01786 { 01787 /* 01788 * This can only happen if we are called from a bugcheck 01789 * and were never initialized, so initialize the debugger now. 01790 */ 01791 KdInitSystem(0, NULL); 01792 01793 /* Return success since we initialized */ 01794 return STATUS_SUCCESS; 01795 } 01796 } 01797 01798 /* Decrease the disable count */ 01799 if (!(--KdDisableCount)) 01800 { 01801 /* We're now enabled again! Were we enabled before, too? */ 01802 if (KdPreviouslyEnabled) 01803 { 01804 /* Reinitialize the Debugger */ 01805 KdInitSystem(0, NULL) ; 01806 KdpRestoreAllBreakpoints(); 01807 } 01808 } 01809 01810 /* Check if we had locked the port before */ 01811 if (NeedLock) 01812 { 01813 /* Yes, now unlock it */ 01814 KeLowerIrql(OldIrql); 01815 KdpPortUnlock(); 01816 } 01817 01818 /* We're done */ 01819 return STATUS_SUCCESS; 01820 } 01821 01822 NTSTATUS 01823 NTAPI 01824 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock) 01825 { 01826 KIRQL OldIrql; 01827 NTSTATUS Status; 01828 01829 #if defined(__GNUC__) 01830 /* Make gcc happy */ 01831 OldIrql = PASSIVE_LEVEL; 01832 #endif 01833 01834 /* 01835 * If enabling the debugger is blocked 01836 * then there is nothing to disable (duh) 01837 */ 01838 if (KdBlockEnable) 01839 { 01840 /* Fail */ 01841 return STATUS_ACCESS_DENIED; 01842 } 01843 01844 /* Check if we need to acquire the lock */ 01845 if (NeedLock) 01846 { 01847 /* Lock the port */ 01848 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 01849 KdpPortLock(); 01850 } 01851 01852 /* Check if we're not disabled */ 01853 if (!KdDisableCount) 01854 { 01855 /* Check if the debugger was never actually initialized */ 01856 if (!(KdDebuggerEnabled) && !(KdPitchDebugger)) 01857 { 01858 /* It wasn't, so don't re-enable it later */ 01859 KdPreviouslyEnabled = FALSE; 01860 } 01861 else 01862 { 01863 /* It was, so we will re-enable it later */ 01864 KdPreviouslyEnabled = TRUE; 01865 } 01866 01867 /* Check if we were called from the exported API and are enabled */ 01868 if ((NeedLock) && (KdPreviouslyEnabled)) 01869 { 01870 /* Check if it is safe to disable the debugger */ 01871 Status = KdpAllowDisable(); 01872 if (!NT_SUCCESS(Status)) 01873 { 01874 /* Release the lock and fail */ 01875 KeLowerIrql(OldIrql); 01876 KdpPortUnlock(); 01877 return Status; 01878 } 01879 } 01880 01881 /* Only disable the debugger if it is enabled */ 01882 if (KdDebuggerEnabled) 01883 { 01884 /* 01885 * Disable the debugger; suspend breakpoints 01886 * and reset the debug stub 01887 */ 01888 KdpSuspendAllBreakPoints(); 01889 KiDebugRoutine = KdpStub; 01890 01891 /* We are disabled now */ 01892 KdDebuggerEnabled = FALSE; 01893 #undef KdDebuggerEnabled 01894 SharedUserData->KdDebuggerEnabled = FALSE; 01895 #define KdDebuggerEnabled _KdDebuggerEnabled 01896 } 01897 } 01898 01899 /* Increment the disable count */ 01900 KdDisableCount++; 01901 01902 /* Check if we had locked the port before */ 01903 if (NeedLock) 01904 { 01905 /* Yes, now unlock it */ 01906 KeLowerIrql(OldIrql); 01907 KdpPortUnlock(); 01908 } 01909 01910 /* We're done */ 01911 return STATUS_SUCCESS; 01912 } 01913 01914 /* PUBLIC FUNCTIONS **********************************************************/ 01915 01916 /* 01917 * @implemented 01918 */ 01919 NTSTATUS 01920 NTAPI 01921 KdEnableDebugger(VOID) 01922 { 01923 /* Use the internal routine */ 01924 return KdEnableDebuggerWithLock(TRUE); 01925 } 01926 01927 /* 01928 * @implemented 01929 */ 01930 NTSTATUS 01931 NTAPI 01932 KdDisableDebugger(VOID) 01933 { 01934 /* Use the internal routine */ 01935 return KdDisableDebuggerWithLock(TRUE); 01936 } 01937 01938 /* 01939 * @unimplemented 01940 */ 01941 NTSTATUS 01942 NTAPI 01943 KdSystemDebugControl(IN SYSDBG_COMMAND Command, 01944 IN PVOID InputBuffer, 01945 IN ULONG InputBufferLength, 01946 OUT PVOID OutputBuffer, 01947 IN ULONG OutputBufferLength, 01948 IN OUT PULONG ReturnLength, 01949 IN KPROCESSOR_MODE PreviousMode) 01950 { 01951 /* handle sime internal commands */ 01952 if (Command == ' soR') 01953 { 01954 switch ((ULONG_PTR)InputBuffer) 01955 { 01956 case 0x24: 01957 MmDumpArmPfnDatabase(FALSE); 01958 break; 01959 } 01960 return STATUS_SUCCESS; 01961 } 01962 01963 /* Local kernel debugging is not yet supported */ 01964 DbgPrint("KdSystemDebugControl is unimplemented!\n"); 01965 return STATUS_NOT_IMPLEMENTED; 01966 } 01967 01968 /* 01969 * @implemented 01970 */ 01971 NTSTATUS 01972 NTAPI 01973 KdChangeOption(IN KD_OPTION Option, 01974 IN ULONG InBufferBytes OPTIONAL, 01975 IN PVOID InBuffer, 01976 IN ULONG OutBufferBytes OPTIONAL, 01977 OUT PVOID OutBuffer, 01978 OUT PULONG OutBufferNeeded OPTIONAL) 01979 { 01980 /* Fail if there is no debugger */ 01981 if (KdPitchDebugger) 01982 { 01983 /* No debugger, no options */ 01984 return STATUS_DEBUGGER_INACTIVE; 01985 } 01986 01987 /* Do we recognize this option? */ 01988 if (Option != KD_OPTION_SET_BLOCK_ENABLE) 01989 { 01990 /* We don't, clear the output length and fail */ 01991 if (OutBufferNeeded) *OutBufferNeeded = 0; 01992 return STATUS_INVALID_INFO_CLASS; 01993 } 01994 01995 /* Verify parameters */ 01996 if ((InBufferBytes != sizeof(BOOLEAN)) || 01997 (OutBufferBytes != 0) || 01998 (OutBuffer != NULL)) 01999 { 02000 /* Invalid parameters for this option, fail */ 02001 return STATUS_INVALID_PARAMETER; 02002 } 02003 02004 /* 02005 * Check if the high bit is set, meaning we don't 02006 * allow the debugger to be enabled 02007 */ 02008 if (KdBlockEnable & 0x80) 02009 { 02010 /* Fail regardless of what state the caller tried to set */ 02011 return STATUS_ACCESS_VIOLATION; 02012 } 02013 02014 /* Set the new block enable state */ 02015 KdBlockEnable = *(PBOOLEAN)InBuffer; 02016 02017 /* No output buffer required for this option */ 02018 if (OutBufferNeeded) *OutBufferNeeded = 0; 02019 02020 /* We are done */ 02021 return STATUS_SUCCESS; 02022 } 02023 02024 /* 02025 * @implemented 02026 */ 02027 NTSTATUS 02028 NTAPI 02029 KdPowerTransition(IN DEVICE_POWER_STATE NewState) 02030 { 02031 /* Check what power state this is */ 02032 if (NewState == PowerDeviceD0) 02033 { 02034 /* Wake up the debug port */ 02035 KdD0Transition(); 02036 return STATUS_SUCCESS; 02037 } 02038 else if ((NewState == PowerDeviceD1) || 02039 (NewState == PowerDeviceD2) || 02040 (NewState == PowerDeviceD3)) 02041 { 02042 /* Power down the debug port */ 02043 KdD3Transition(); 02044 return STATUS_SUCCESS; 02045 } 02046 else 02047 { 02048 /* Invalid state! */ 02049 return STATUS_INVALID_PARAMETER_1; 02050 } 02051 } 02052 02053 /* 02054 * @implemented 02055 */ 02056 BOOLEAN 02057 NTAPI 02058 KdRefreshDebuggerNotPresent(VOID) 02059 { 02060 BOOLEAN Enable, DebuggerNotPresent; 02061 02062 /* Check if the debugger is completely disabled */ 02063 if (KdPitchDebugger) 02064 { 02065 /* Don't try to refresh then -- fail early */ 02066 return TRUE; 02067 } 02068 02069 /* Enter the debugger */ 02070 Enable = KdEnterDebugger(NULL, NULL); 02071 02072 /* 02073 * Attempt to send a string to the debugger to refresh the 02074 * connection state 02075 */ 02076 KdpDprintf("KDTARGET: Refreshing KD connection\n"); 02077 02078 /* Save the state while we are holding the lock */ 02079 DebuggerNotPresent = KdDebuggerNotPresent; 02080 02081 /* Exit the debugger and return the state */ 02082 KdExitDebugger(Enable); 02083 return DebuggerNotPresent; 02084 } 02085 02086 /* 02087 * @implemented 02088 */ 02089 NTSTATUS 02090 NTAPI 02091 NtQueryDebugFilterState(IN ULONG ComponentId, 02092 IN ULONG Level) 02093 { 02094 PULONG Mask; 02095 02096 /* Check if the ID fits in the component table */ 02097 if (ComponentId < KdComponentTableSize) 02098 { 02099 /* It does, so get the mask from there */ 02100 Mask = KdComponentTable[ComponentId]; 02101 } 02102 else if (ComponentId == MAXULONG) 02103 { 02104 /* 02105 * This is the internal ID used for DbgPrint messages without ID and 02106 * Level. Use the system-wide mask for those. 02107 */ 02108 Mask = &Kd_WIN2000_Mask; 02109 } 02110 else 02111 { 02112 /* Invalid ID, fail */ 02113 return STATUS_INVALID_PARAMETER_1; 02114 } 02115 02116 /* Convert Level to bit field if necessary */ 02117 if (Level < 32) Level = 1 << Level; 02118 02119 /* Determine if this Level is filtered out */ 02120 if ((Kd_WIN2000_Mask & Level) || 02121 (*Mask & Level)) 02122 { 02123 /* This mask will get through to the debugger */ 02124 return (NTSTATUS)TRUE; 02125 } 02126 else 02127 { 02128 /* This mask is filtered out */ 02129 return (NTSTATUS)FALSE; 02130 } 02131 } 02132 02133 /* 02134 * @implemented 02135 */ 02136 NTSTATUS 02137 NTAPI 02138 NtSetDebugFilterState(IN ULONG ComponentId, 02139 IN ULONG Level, 02140 IN BOOLEAN State) 02141 { 02142 PULONG Mask; 02143 02144 /* Modifying debug filters requires the debug privilege */ 02145 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, 02146 ExGetPreviousMode())) 02147 { 02148 /* Fail */ 02149 return STATUS_ACCESS_DENIED; 02150 } 02151 02152 /* Check if the ID fits in the component table */ 02153 if (ComponentId < KdComponentTableSize) 02154 { 02155 /* It does, so get the mask from there */ 02156 Mask = KdComponentTable[ComponentId]; 02157 } 02158 else if (ComponentId == MAXULONG) 02159 { 02160 /* 02161 * This is the internal ID used for DbgPrint messages without ID and 02162 * Level. Use the system-wide mask for those. 02163 */ 02164 Mask = &Kd_WIN2000_Mask; 02165 } 02166 else 02167 { 02168 /* Invalid ID, fail */ 02169 return STATUS_INVALID_PARAMETER_1; 02170 } 02171 02172 /* Convert Level to bit field if required */ 02173 if (Level < 32) Level = 1 << Level; 02174 02175 /* Check what kind of operation this is */ 02176 if (State) 02177 { 02178 /* Set the Level */ 02179 *Mask |= Level; 02180 } 02181 else 02182 { 02183 /* Remove the Level */ 02184 *Mask &= ~Level; 02185 } 02186 02187 /* Success */ 02188 return STATUS_SUCCESS; 02189 } Generated on Sat May 26 2012 04:36:15 for ReactOS by
1.7.6.1
|