ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

kdapi.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.