Make winkd somewhat portable.
[reactos.git] / reactos / ntoskrnl / kd64 / kdapi.c
index ea161ed..265904c 100644 (file)
 \r
 /* PRIVATE FUNCTIONS *********************************************************/\r
 \r
+VOID\r
+NTAPI\r
+KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,\r
+               IN PCONTEXT Context)\r
+{\r
+    PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;\r
+    STRING Header;\r
+    NTSTATUS Status = STATUS_SUCCESS;\r
+\r
+    /* Validate the address space */\r
+    if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)\r
+    {\r
+        /* Check if this is process memory */\r
+        if ((PVOID)(LONG_PTR)Memory->Address < MmHighestUserAddress)\r
+        {\r
+            /* It is */\r
+            Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;\r
+        }\r
+        else\r
+        {\r
+            /* FIXME: Check if it's session space */\r
+            Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;\r
+        }\r
+\r
+        /* Set flags */\r
+        Memory->Flags = DBGKD_QUERY_MEMORY_READ |\r
+                        DBGKD_QUERY_MEMORY_WRITE |\r
+                        DBGKD_QUERY_MEMORY_EXECUTE;\r
+    }\r
+    else\r
+    {\r
+        /* Invalid */\r
+        Status = STATUS_INVALID_PARAMETER;\r
+    }\r
+\r
+    /* Return structure */\r
+    State->ReturnStatus = Status;\r
+    Memory->Reserved = 0;\r
+\r
+    /* Build header */\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
+\r
+    /* Send the packet */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 NULL,\r
+                 &KdpContext);\r
+}\r
+\r
+VOID\r
+NTAPI\r
+KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,\r
+                   IN PSTRING Data,\r
+                   IN PCONTEXT Context)\r
+{\r
+    PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;\r
+    STRING Header;\r
+\r
+    /* Build header */\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
+    ASSERT(Data->Length == 0);\r
+\r
+    /* Create the breakpoint */\r
+    Breakpoint->BreakPointHandle =\r
+        KdpAddBreakpoint((PVOID)(LONG_PTR)Breakpoint->BreakPointAddress);\r
+    if (!Breakpoint->BreakPointHandle)\r
+    {\r
+        /* We failed */\r
+        State->ReturnStatus = STATUS_UNSUCCESSFUL;\r
+    }\r
+    else\r
+    {\r
+        /* Success! */\r
+        State->ReturnStatus = STATUS_SUCCESS;\r
+    }\r
+\r
+    /* Send the packet */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 NULL,\r
+                 &KdpContext);\r
+}\r
+\r
+VOID\r
+NTAPI\r
+DumpTraceData(IN PSTRING TraceData)\r
+{\r
+    /* Update the buffer */\r
+    TraceDataBuffer[0] = TraceDataBufferPosition;\r
+\r
+    /* Setup the trace data */\r
+    TraceData->Length = TraceDataBufferPosition * sizeof(ULONG);\r
+    TraceData->Buffer = (PCHAR)TraceDataBuffer;\r
+\r
+    /* Reset the buffer location */\r
+    TraceDataBufferPosition = 1;\r
+}\r
+\r
+VOID\r
+NTAPI\r
+KdpGetStateChange(IN PDBGKD_MANIPULATE_STATE64 State,\r
+                  IN PCONTEXT Context)\r
+{\r
+    PKPRCB Prcb;\r
+    ULONG i;\r
+\r
+    /* Check for success */\r
+    if (NT_SUCCESS(State->u.Continue2.ContinueStatus))\r
+    {\r
+        /* Check if we're tracing */\r
+        if (State->u.Continue2.ControlSet.TraceFlag)\r
+        {\r
+            /* Enable TF */\r
+            Context->EFlags |= EFLAGS_TF;\r
+        }\r
+        else\r
+        {\r
+            /* Remove it */\r
+            Context->EFlags &= ~EFLAGS_TF;\r
+        }\r
+\r
+        /* Loop all processors */\r
+        for (i = 0; i < KeNumberProcessors; i++)\r
+        {\r
+            /* Get the PRCB and update DR7 and DR6 */\r
+            Prcb = KiProcessorBlock[i];\r
+            Prcb->ProcessorState.SpecialRegisters.KernelDr7 =\r
+                State->u.Continue2.ControlSet.Dr7;\r
+            Prcb->ProcessorState.SpecialRegisters.KernelDr6 = 0;\r
+        }\r
+\r
+        /* Check if we have new symbol information */\r
+        if (State->u.Continue2.ControlSet.CurrentSymbolStart != 1)\r
+        {\r
+            /* Update it */\r
+            KdpCurrentSymbolStart =\r
+                State->u.Continue2.ControlSet.CurrentSymbolStart;\r
+            KdpCurrentSymbolEnd= State->u.Continue2.ControlSet.CurrentSymbolEnd;\r
+        }\r
+    }\r
+}\r
+\r
 VOID\r
 NTAPI\r
 KdpSetCommonState(IN ULONG NewState,\r
@@ -28,8 +172,14 @@ KdpSetCommonState(IN ULONG NewState,
     WaitStateChange->ProcessorLevel = KeProcessorLevel;\r
     WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;\r
     WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;\r
-    WaitStateChange->Thread = (ULONG)KeGetCurrentThread();\r
-    WaitStateChange->ProgramCounter = (ULONG64)Context->Eip;\r
+    WaitStateChange->Thread = (ULONG)(LONG_PTR)KeGetCurrentThread();\r
+#if defined(_M_X86_)\r
+    WaitStateChange->ProgramCounter = (ULONG)(LONG_PTR)Context->Eip;\r
+#elif defined(_AMD64)\r
+    WaitStateChange->ProgramCounter = (ULONG)(LONG_PTR)Context->Rip;\r
+#else\r
+#error Unknown platform\r
+#endif\r
 \r
     /* Zero out the Control Report */\r
     RtlZeroMemory(&WaitStateChange->ControlReport,\r
@@ -43,13 +193,10 @@ KdpSetCommonState(IN ULONG NewState,
     WaitStateChange->ControlReport.InstructionCount = InstructionCount;\r
 \r
     /* Clear all the breakpoints in this region */\r
-    HadBreakpoints = FALSE;\r
-#if 0\r
-        KdpDeleteBreakpointRange((PVOID)WaitStateChange->ProgramCounter,\r
-                                 (PVOID)(WaitStateChange->ProgramCounter +\r
-                                         WaitStateChange->ControlReport.\r
-                                         InstructionCount - 1));\r
-#endif\r
+    HadBreakpoints =\r
+        KdpDeleteBreakpointRange((PVOID)(LONG_PTR)WaitStateChange->ProgramCounter,\r
+                                 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +\r
+                                         WaitStateChange->ControlReport.InstructionCount - 1));\r
     if (HadBreakpoints)\r
     {\r
         /* Copy the instruction stream again, this time without breakpoints */\r
@@ -61,40 +208,337 @@ KdpSetCommonState(IN ULONG NewState,
 \r
 VOID\r
 NTAPI\r
-KdpSetContextState(IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange,\r
-                   IN PCONTEXT Context)\r
+KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version)\r
+{\r
+    /* Copy the version block */\r
+    RtlCopyMemory(Version, &KdVersionBlock, sizeof(DBGKD_GET_VERSION64));\r
+}\r
+\r
+VOID\r
+NTAPI\r
+KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)\r
 {\r
-    PKPRCB Prcb = KeGetCurrentPrcb();\r
+    STRING Header;\r
 \r
-    /* Copy i386 specific debug registers */\r
-    WaitStateChange->ControlReport.Dr6 = Prcb->ProcessorState.SpecialRegisters.\r
-                                         KernelDr6;\r
-    WaitStateChange->ControlReport.Dr7 = Prcb->ProcessorState.SpecialRegisters.\r
-                                         KernelDr7;\r
+    /* Fill out the header */\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
 \r
-    /* Copy i386 specific segments */\r
-    WaitStateChange->ControlReport.SegCs = (USHORT)Context->SegCs;\r
-    WaitStateChange->ControlReport.SegDs = (USHORT)Context->SegDs;\r
-    WaitStateChange->ControlReport.SegEs = (USHORT)Context->SegEs;\r
-    WaitStateChange->ControlReport.SegFs = (USHORT)Context->SegFs;\r
+    /* Get the version block */\r
+    KdpSysGetVersion(&State->u.GetVersion64);\r
 \r
-    /* Copy EFlags */\r
-    WaitStateChange->ControlReport.EFlags = Context->EFlags;\r
+    /* Fill out the state */\r
+    State->ApiNumber = DbgKdGetVersionApi;\r
+    State->ReturnStatus = STATUS_SUCCESS;\r
 \r
-    /* Set Report Flags */\r
-    WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_SEGS;\r
-    if (WaitStateChange->ControlReport.SegCs == KGDT_R0_CODE)\r
+    /* Send the packet */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 NULL,\r
+                 &KdpContext);\r
+}\r
+\r
+VOID\r
+NTAPI\r
+KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,\r
+                     IN PSTRING Data,\r
+                     IN PCONTEXT Context)\r
+{\r
+    STRING Header;\r
+    ULONG Length = State->u.ReadMemory.TransferCount;\r
+    NTSTATUS Status = STATUS_SUCCESS;\r
+\r
+    /* Validate length */\r
+    if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))\r
+    {\r
+        /* Overflow, set it to maximum possible */\r
+        Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);\r
+    }\r
+\r
+#if 0\r
+    if (!MmIsAddressValid((PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress))\r
+    {\r
+        Ke386SetCr2(State->u.ReadMemory.TargetBaseAddress);\r
+        while (TRUE);\r
+    }\r
+#endif\r
+\r
+    if (!State->u.ReadMemory.TargetBaseAddress)\r
+    {\r
+        Length = 0;\r
+        Status = STATUS_UNSUCCESSFUL;\r
+    }\r
+    else\r
+    {\r
+        RtlCopyMemory(Data->Buffer,\r
+                      (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress,\r
+                      Length);\r
+    }\r
+\r
+    /* Fill out the header */\r
+    Data->Length = Length;\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
+\r
+    /* Fill out the state */\r
+    State->ReturnStatus = Status;\r
+    State->u.ReadMemory.ActualBytesRead = Length;\r
+\r
+    /* Send the packet */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 Data,\r
+                 &KdpContext);\r
+}\r
+\r
+VOID\r
+NTAPI\r
+KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,\r
+                    IN PSTRING Data,\r
+                    IN PCONTEXT Context)\r
+{\r
+    PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;\r
+    STRING Header;\r
+    ULONG Length, RealLength;\r
+    PVOID ControlStart;\r
+\r
+    /* Setup the header */\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
+    ASSERT(Data->Length == 0);\r
+\r
+    /* Check the length requested */\r
+    Length = ReadMemory->TransferCount;\r
+    if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))\r
     {\r
-        WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_CS;\r
+        /* Use maximum allowed */\r
+        Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);\r
     }\r
+\r
+    /* Make sure that this is a valid request */\r
+    if (((ULONG)ReadMemory->TargetBaseAddress < sizeof(KPROCESSOR_STATE)) &&\r
+        (State->Processor < KeNumberProcessors))\r
+    {\r
+        /* Get the actual length */\r
+        RealLength = sizeof(KPROCESSOR_STATE) -\r
+                     (ULONG_PTR)ReadMemory->TargetBaseAddress;\r
+        if (RealLength < Length) Length = RealLength;\r
+\r
+        /* Set the proper address */\r
+        ControlStart = (PVOID)((ULONG_PTR)ReadMemory->TargetBaseAddress +\r
+                               (ULONG_PTR)&KiProcessorBlock[State->Processor]->\r
+                                           ProcessorState);\r
+\r
+        /* Copy the memory */\r
+        RtlCopyMemory(Data->Buffer, ControlStart, Length);\r
+        Data->Length = Length;\r
+\r
+        /* Finish up */\r
+        State->ReturnStatus = STATUS_SUCCESS;\r
+        ReadMemory->ActualBytesRead = Data->Length;\r
+    }\r
+    else\r
+    {\r
+        /* Invalid request */\r
+        Data->Length = 0;\r
+        State->ReturnStatus = STATUS_UNSUCCESSFUL;\r
+        ReadMemory->ActualBytesRead = 0;\r
+    }\r
+\r
+    /* Send the reply */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 Data,\r
+                 &KdpContext);\r
 }\r
 \r
-BOOLEAN\r
+VOID\r
+NTAPI\r
+KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,\r
+                     IN PSTRING Data,\r
+                     IN PCONTEXT Context)\r
+{\r
+    PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;\r
+    STRING Header;\r
+    ULONG Length;\r
+    PVOID ControlStart;\r
+\r
+    /* Setup the header */\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
+\r
+    /* Make sure that this is a valid request */\r
+    Length = WriteMemory->TransferCount;\r
+    if ((((ULONG)WriteMemory->TargetBaseAddress + Length) <=\r
+          sizeof(KPROCESSOR_STATE)) &&\r
+        (State->Processor < KeNumberProcessors))\r
+    {\r
+        /* Set the proper address */\r
+        ControlStart = (PVOID)((ULONG_PTR)WriteMemory->TargetBaseAddress +\r
+                               (ULONG_PTR)&KiProcessorBlock[State->Processor]->\r
+                                           ProcessorState);\r
+\r
+        /* Copy the memory */\r
+        RtlCopyMemory(ControlStart, Data->Buffer, Data->Length);\r
+        Length = Data->Length;\r
+\r
+        /* Finish up */\r
+        State->ReturnStatus = STATUS_SUCCESS;\r
+        WriteMemory->ActualBytesWritten = Length;\r
+    }\r
+    else\r
+    {\r
+        /* Invalid request */\r
+        Data->Length = 0;\r
+        State->ReturnStatus = STATUS_UNSUCCESSFUL;\r
+        WriteMemory->ActualBytesWritten = 0;\r
+    }\r
+\r
+    /* Send the reply */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 Data,\r
+                 &KdpContext);\r
+}\r
+\r
+VOID\r
+NTAPI\r
+KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,\r
+                     IN PSTRING Data,\r
+                     IN PCONTEXT Context)\r
+{\r
+    PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;\r
+    STRING Header;\r
+\r
+    /* Fill out the header */\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
+    ASSERT(Data->Length == 0);\r
+\r
+    /* Get the version block */\r
+    if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))\r
+    {\r
+        /* We're all good */\r
+        State->ReturnStatus = STATUS_SUCCESS;\r
+    }\r
+    else\r
+    {\r
+        /* We failed */\r
+        State->ReturnStatus = STATUS_UNSUCCESSFUL;\r
+    }\r
+\r
+    /* Send the packet */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 NULL,\r
+                 &KdpContext);\r
+}\r
+\r
+VOID\r
+NTAPI\r
+KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,\r
+              IN PSTRING Data,\r
+              IN PCONTEXT Context)\r
+{\r
+    STRING Header;\r
+    PVOID ControlStart;\r
+\r
+    /* Setup the header */\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
+    ASSERT(Data->Length == 0);\r
+\r
+    /* Make sure that this is a valid request */\r
+    if (State->Processor < KeNumberProcessors)\r
+    {\r
+        /* Check if the request is for this CPU */\r
+        if (State->Processor == KeGetCurrentPrcb()->Number)\r
+        {\r
+            /* We're just copying our own context */\r
+            ControlStart = Context;\r
+        }\r
+        else\r
+        {\r
+            /* SMP not yet handled */\r
+            ControlStart = NULL;\r
+            while (TRUE);\r
+        }\r
+\r
+        /* Copy the memory */\r
+        RtlCopyMemory(Data->Buffer, ControlStart, sizeof(CONTEXT));\r
+        Data->Length = sizeof(CONTEXT);\r
+\r
+        /* Finish up */\r
+        State->ReturnStatus = STATUS_SUCCESS;\r
+    }\r
+    else\r
+    {\r
+        /* Invalid request */\r
+        State->ReturnStatus = STATUS_UNSUCCESSFUL;\r
+    }\r
+\r
+    /* Send the reply */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 Data,\r
+                 &KdpContext);\r
+}\r
+\r
+VOID\r
+NTAPI\r
+KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,\r
+              IN PSTRING Data,\r
+              IN PCONTEXT Context)\r
+{\r
+    STRING Header;\r
+    PVOID ControlStart;\r
+\r
+    /* Setup the header */\r
+    Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);\r
+    Header.Buffer = (PCHAR)State;\r
+    ASSERT(Data->Length == sizeof(CONTEXT));\r
+\r
+    /* Make sure that this is a valid request */\r
+    if (State->Processor < KeNumberProcessors)\r
+    {\r
+        /* Check if the request is for this CPU */\r
+        if (State->Processor == KeGetCurrentPrcb()->Number)\r
+        {\r
+            /* We're just copying our own context */\r
+            ControlStart = Context;\r
+        }\r
+        else\r
+        {\r
+            /* SMP not yet handled */\r
+            ControlStart = NULL;\r
+            while (TRUE);\r
+        }\r
+\r
+        /* Copy the memory */\r
+        RtlCopyMemory(ControlStart, Data->Buffer, sizeof(CONTEXT));\r
+\r
+        /* Finish up */\r
+        State->ReturnStatus = STATUS_SUCCESS;\r
+    }\r
+    else\r
+    {\r
+        /* Invalid request */\r
+        State->ReturnStatus = STATUS_UNSUCCESSFUL;\r
+    }\r
+\r
+    /* Send the reply */\r
+    KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
+                 &Header,\r
+                 Data,\r
+                 &KdpContext);\r
+}\r
+\r
+KCONTINUE_STATUS\r
 NTAPI\r
 KdpSendWaitContinue(IN ULONG PacketType,\r
                     IN PSTRING SendHeader,\r
                     IN PSTRING SendData OPTIONAL,\r
-                    IN OUT PCONTEXT ContextRecord)\r
+                    IN OUT PCONTEXT Context)\r
 {\r
     STRING Data, Header;\r
     DBGKD_MANIPULATE_STATE64 ManipulateState;\r
@@ -113,7 +557,7 @@ SendPacket:
     KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);\r
 \r
     /* If the debugger isn't present anymore, just return success */\r
-    if (KdDebuggerNotPresent) return TRUE;\r
+    if (KdDebuggerNotPresent) return ContinueSuccess;\r
 \r
     /* Main processing Loop */\r
     for (;;)\r
@@ -122,7 +566,6 @@ SendPacket:
         do\r
         {\r
             /* Wait to get a reply to our packet */\r
-            ManipulateState.ApiNumber = 0xFFFFFFFF;\r
             RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,\r
                                        &Header,\r
                                        &Data,\r
@@ -138,9 +581,8 @@ SendPacket:
         {\r
             case DbgKdReadVirtualMemoryApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdReadVirtualMemoryApi);\r
-                while (TRUE);\r
+                /* Read virtual memory */\r
+                KdpReadVirtualMemory(&ManipulateState, &Data, Context);\r
                 break;\r
 \r
             case DbgKdWriteVirtualMemoryApi:\r
@@ -152,51 +594,43 @@ SendPacket:
 \r
             case DbgKdGetContextApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdGetContextApi);\r
-                while (TRUE);\r
+                /* Get the current context */\r
+                KdpGetContext(&ManipulateState, &Data, Context);\r
                 break;\r
 \r
             case DbgKdSetContextApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdSetContextApi);\r
-                while (TRUE);\r
+                /* Set a new context */\r
+                KdpSetContext(&ManipulateState, &Data, Context);\r
                 break;\r
 \r
             case DbgKdWriteBreakPointApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdWriteBreakPointApi);\r
-                while (TRUE);\r
+                /* Write the breakpoint */\r
+                KdpWriteBreakpoint(&ManipulateState, &Data, Context);\r
                 break;\r
 \r
             case DbgKdRestoreBreakPointApi:\r
 \r
                 /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdRestoreBreakPointApi);\r
-                while (TRUE);\r
+                KdpRestoreBreakpoint(&ManipulateState, &Data, Context);\r
                 break;\r
 \r
             case DbgKdContinueApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdContinueApi);\r
-                while (TRUE);\r
-                break;\r
+                /* Simply continue */\r
+                return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);\r
 \r
             case DbgKdReadControlSpaceApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdReadControlSpaceApi);\r
-                while (TRUE);\r
+                /* Read control space */\r
+                KdpReadControlSpace(&ManipulateState, &Data, Context);\r
                 break;\r
 \r
             case DbgKdWriteControlSpaceApi:\r
 \r
                 /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdWriteControlSpaceApi);\r
-                while (TRUE);\r
+                KdpWriteControlSpace(&ManipulateState, &Data, Context);\r
                 break;\r
 \r
             case DbgKdReadIoSpaceApi:\r
@@ -222,14 +656,24 @@ SendPacket:
 \r
             case DbgKdContinueApi2:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdContinueApi2);\r
-                while (TRUE);\r
+                /* Check if caller reports success */\r
+                if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))\r
+                {\r
+                    /* Update the state */\r
+                    KdpGetStateChange(&ManipulateState, Context);\r
+                    return ContinueSuccess;\r
+                }\r
+                else\r
+                {\r
+                    /* Return an error */\r
+                    return ContinueError;\r
+                }\r
                 break;\r
 \r
             case DbgKdReadPhysicalMemoryApi:\r
 \r
                 /* FIXME: TODO */\r
+                goto fail;\r
                 Ke386SetCr2(DbgKdReadPhysicalMemoryApi);\r
                 while (TRUE);\r
                 break;\r
@@ -292,9 +736,8 @@ SendPacket:
 \r
             case DbgKdGetVersionApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdGetVersionApi);\r
-                while (TRUE);\r
+                /* Get version data */\r
+                KdpGetVersion(&ManipulateState);\r
                 break;\r
 \r
             case DbgKdWriteBreakPointExApi:\r
@@ -390,9 +833,8 @@ SendPacket:
 \r
             case DbgKdClearAllInternalBreakpointsApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdClearAllInternalBreakpointsApi);\r
-                while (TRUE);\r
+                /* Just clear the counter */\r
+                KdpNumInternalBreakpoints = 0;\r
                 break;\r
 \r
             case DbgKdFillMemoryApi:\r
@@ -404,9 +846,8 @@ SendPacket:
 \r
             case DbgKdQueryMemoryApi:\r
 \r
-                /* FIXME: TODO */\r
-                Ke386SetCr2(DbgKdQueryMemoryApi);\r
-                while (TRUE);\r
+                /* Query memory */\r
+                KdpQueryMemory(&ManipulateState, Context);\r
                 break;\r
 \r
             case DbgKdSwitchPartition:\r
@@ -421,6 +862,7 @@ SendPacket:
 \r
                 /* Setup an empty message, with failure */\r
                 while (TRUE);\r
+fail:\r
                 Data.Length = 0;\r
                 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;\r
 \r
@@ -459,7 +901,7 @@ KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
 \r
         /* Fill out load data */\r
         WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;\r
-        WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG)SymbolInfo->BaseOfDll;\r
+        WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONGLONG)(LONG_PTR)SymbolInfo->BaseOfDll;\r
         WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;\r
         WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;\r
         WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;\r
@@ -469,6 +911,7 @@ KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
         {\r
             /* Setup the information */\r
             WaitStateChange.u.LoadSymbols.PathNameLength = PathName->Length;\r
+            RtlCopyMemory(KdpPathBuffer, PathName->Buffer, PathName->Length);\r
             Data.Buffer = KdpPathBuffer;\r
             Data.Length = WaitStateChange.u.LoadSymbols.PathNameLength;\r
             ExtraData = &Data;\r
@@ -492,7 +935,48 @@ KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
     } while(Status == ContinueProcessorReselected);\r
 \r
     /* Return status */\r
-    while (TRUE);\r
+    return Status;\r
+}\r
+\r
+BOOLEAN\r
+NTAPI\r
+KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,\r
+                              IN OUT PCONTEXT Context,\r
+                              IN BOOLEAN SecondChanceException)\r
+{\r
+    STRING Header, Data;\r
+    DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;\r
+    BOOLEAN Status;\r
+\r
+    /* Start report loop */\r
+    do\r
+    {\r
+        /* Build the architecture common parts of the message */\r
+        KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);\r
+\r
+        /* Convert the exception record to 64-bits and set First Chance flag */\r
+        ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,\r
+                              &WaitStateChange.u.Exception.ExceptionRecord);\r
+        WaitStateChange.u.Exception.FirstChance = !SecondChanceException;\r
+\r
+        /* Now finish creating the structure */\r
+        KdpSetContextState(&WaitStateChange, Context);\r
+\r
+        /* Setup the actual header to send to KD */\r
+        Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);\r
+        Header.Buffer = (PCHAR)&WaitStateChange;\r
+\r
+        /* Setup the trace data */\r
+        DumpTraceData(&Data);\r
+\r
+        /* Send State Change packet and wait for a reply */\r
+        Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,\r
+                                     &Header,\r
+                                     &Data,\r
+                                     Context);\r
+    } while (Status == KdPacketNeedsResend);\r
+\r
+    /* Return */\r
     return Status;\r
 }\r
 \r
@@ -556,13 +1040,9 @@ KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
     KdSave(FALSE);\r
 \r
     /* Report a state change */\r
-#if 0\r
     Status = KdpReportExceptionStateChange(ExceptionRecord,\r
                                            ContextRecord,\r
                                            SecondChanceException);\r
-#else\r
-    Status = FALSE;\r
-#endif\r
 \r
     /* Restore the port data and return */\r
     KdRestore(FALSE);\r
@@ -678,7 +1158,7 @@ NTSTATUS
 NTAPI\r
 KdEnableDebuggerWithLock(BOOLEAN NeedLock)\r
 {\r
-    KIRQL OldIrql;\r
+    KIRQL OldIrql = PASSIVE_LEVEL;\r
 \r
     /* Check if we need to acquire the lock */\r
     if (NeedLock)\r
@@ -711,7 +1191,7 @@ KdEnableDebuggerWithLock(BOOLEAN NeedLock)
         {\r
             /* Reinitialize the Debugger */\r
             KdInitSystem(0, NULL) ;\r
-            //KdpRestoreAllBreakpoints();\r
+            KdpRestoreAllBreakpoints();\r
         }\r
     }\r
 \r
@@ -741,3 +1221,88 @@ KdEnableDebugger(VOID)
     return KdEnableDebuggerWithLock(TRUE);\r
 }\r
 \r
+/*\r
+ * @unimplemented\r
+ */\r
+NTSTATUS\r
+NTAPI\r
+KdSystemDebugControl(IN SYSDBG_COMMAND Command,\r
+                     IN PVOID InputBuffer,\r
+                     IN ULONG InputBufferLength,\r
+                     OUT PVOID OutputBuffer,\r
+                     IN ULONG OutputBufferLength,\r
+                     IN OUT PULONG ReturnLength,\r
+                     IN KPROCESSOR_MODE PreviousMode)\r
+{\r
+    /* HACK */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+/*\r
+ * @unimplemented\r
+ */\r
+NTSTATUS\r
+NTAPI\r
+KdChangeOption(IN KD_OPTION Option,\r
+               IN ULONG InBufferBytes OPTIONAL,\r
+               IN PVOID InBuffer,\r
+               IN ULONG OutBufferBytes OPTIONAL,\r
+               OUT PVOID OutBuffer,\r
+               OUT PULONG OutBufferNeeded OPTIONAL)\r
+{\r
+    /* HACK */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+/*\r
+ * @unimplemented\r
+ */\r
+NTSTATUS\r
+NTAPI\r
+KdPowerTransition(IN DEVICE_POWER_STATE NewState)\r
+{\r
+    /* HACK */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+/*\r
+ * @unimplemented\r
+ */\r
+NTSTATUS\r
+NTAPI\r
+KdDisableDebugger(VOID)\r
+{\r
+    /* HACK */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+/*\r
+ * @unimplemented\r
+ */\r
+BOOLEAN\r
+NTAPI\r
+KdRefreshDebuggerNotPresent(VOID)\r
+{\r
+    /* HACK */\r
+    return KdDebuggerNotPresent;\r
+}\r
+\r
+NTSTATUS\r
+NTAPI\r
+NtQueryDebugFilterState(ULONG ComponentId,\r
+                        ULONG Level)\r
+{\r
+    /* HACK */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS\r
+NTAPI\r
+NtSetDebugFilterState(ULONG ComponentId,\r
+                      ULONG Level,\r
+                      BOOLEAN State)\r
+{\r
+    /* HACK */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r