/*++ BUILD Version: 0002    // Increment this if a change has global effects

Copyright (c) 1989-1993  Microsoft Corporation

Module Name:

    ntdbg.h

Abstract:

    This module contains the public data structures, data types,
    and procedures exported by the NT Dbg subsystem.

Author:

    Mark Lucovsky (markl) 19-Jan-1990

Revision History:

--*/

#ifndef _NTDBG_
#define _NTDBG_

#include <nt.h>

//
// DbgKm Apis are from the kernel component (Dbgk) thru a process
// debug port.
//

#define DBGKM_MSG_OVERHEAD 8

#define DBGKM_API_MSG_LENGTH(TypeSize) \
            sizeof(DBGKM_APIMSG)<<16 | (DBGKM_MSG_OVERHEAD + (TypeSize))

#define DBGKM_FORMAT_API_MSG(m,Number,TypeSize)             \
    (m).h.u1.Length = DBGKM_API_MSG_LENGTH((TypeSize));     \
    (m).h.u2.ZeroInit = LPC_DEBUG_EVENT;                    \
    (m).ApiNumber = (Number)

typedef enum _DBGKM_APINUMBER {
    DbgKmExceptionApi,
    DbgKmCreateThreadApi,
    DbgKmCreateProcessApi,
    DbgKmExitThreadApi,
    DbgKmExitProcessApi,
    DbgKmLoadDllApi,
    DbgKmUnloadDllApi,
    DbgKmMaxApiNumber
} DBGKM_APINUMBER;

// begin_windbgkd

typedef struct _DBGKM_EXCEPTION {
    EXCEPTION_RECORD ExceptionRecord;
    ULONG FirstChance;
} DBGKM_EXCEPTION, *PDBGKM_EXCEPTION;

// end_windbgkd

typedef struct _DBGKM_CREATE_THREAD {
    ULONG SubSystemKey;
    PVOID StartAddress;
} DBGKM_CREATE_THREAD, *PDBGKM_CREATE_THREAD;

typedef struct _DBGKM_CREATE_PROCESS {
    ULONG SubSystemKey;
    HANDLE FileHandle;
    PVOID BaseOfImage;
    ULONG DebugInfoFileOffset;
    ULONG DebugInfoSize;
    DBGKM_CREATE_THREAD InitialThread;
} DBGKM_CREATE_PROCESS, *PDBGKM_CREATE_PROCESS;

typedef struct _DBGKM_EXIT_THREAD {
    NTSTATUS ExitStatus;
} DBGKM_EXIT_THREAD, *PDBGKM_EXIT_THREAD;

typedef struct _DBGKM_EXIT_PROCESS {
    NTSTATUS ExitStatus;
} DBGKM_EXIT_PROCESS, *PDBGKM_EXIT_PROCESS;

typedef struct _DBGKM_LOAD_DLL {
    HANDLE FileHandle;
    PVOID BaseOfDll;
    ULONG DebugInfoFileOffset;
    ULONG DebugInfoSize;
} DBGKM_LOAD_DLL, *PDBGKM_LOAD_DLL;

typedef struct _DBGKM_UNLOAD_DLL {
    PVOID BaseAddress;
} DBGKM_UNLOAD_DLL, *PDBGKM_UNLOAD_DLL;

typedef struct _DBGKM_APIMSG {
    PORT_MESSAGE h;
    DBGKM_APINUMBER ApiNumber;
    NTSTATUS ReturnedStatus;
    union {
        DBGKM_EXCEPTION Exception;
        DBGKM_CREATE_THREAD CreateThread;
        DBGKM_CREATE_PROCESS CreateProcessInfo;
        DBGKM_EXIT_THREAD ExitThread;
        DBGKM_EXIT_PROCESS ExitProcess;
        DBGKM_LOAD_DLL LoadDll;
        DBGKM_UNLOAD_DLL UnloadDll;
    } u;
} DBGKM_APIMSG, *PDBGKM_APIMSG;

//
// DbgSrv Messages are from Dbg subsystem to emulation subsystem.
// The only defined message at this time is continue
//

#define DBGSRV_MSG_OVERHEAD ( 12 )

#define DBGSRV_API_MSG_LENGTH(TypeSize) \
            sizeof(DBGSRV_APIMSG)<<16 | (DBGSRV_MSG_OVERHEAD + (TypeSize))

#define DBGSRV_FORMAT_API_MSG(m,Number,TypeSize,CKey)     \
    (m).h.u1.Length = DBGSRV_API_MSG_LENGTH((TypeSize));  \
    (m).h.u2.ZeroInit = 0L;                               \
    (m).ApiNumber = (Number);                             \
    (m).ContinueKey = (PVOID)(CKey)

typedef enum _DBGSRV_APINUMBER {
    DbgSrvContinueApi,
    DbgSrvMaxApiNumber
} DBGSRV_APINUMBER;

typedef struct _DBGSRV_APIMSG {
    PORT_MESSAGE h;
    DBGSRV_APINUMBER ApiNumber;
    NTSTATUS ReturnedStatus;
    PVOID ContinueKey;
} DBGSRV_APIMSG, *PDBGSRV_APIMSG;

//
//
// DbgSs Apis are from the system service emulation subsystems to the Dbg
// subsystem
//

typedef enum _DBG_STATE {
    DbgIdle,
    DbgReplyPending,
    DbgCreateThreadStateChange,
    DbgCreateProcessStateChange,
    DbgExitThreadStateChange,
    DbgExitProcessStateChange,
    DbgExceptionStateChange,
    DbgBreakpointStateChange,
    DbgSingleStepStateChange,
    DbgLoadDllStateChange,
    DbgUnloadDllStateChange
} DBG_STATE, *PDBG_STATE;

#define DBGSS_MSG_OVERHEAD (12 + sizeof(CLIENT_ID) )

#define DBGSS_API_MSG_LENGTH(TypeSize) \
            sizeof(DBGSS_APIMSG)<<16 | (DBGSS_MSG_OVERHEAD + (TypeSize))

#define DBGSS_FORMAT_API_MSG(m,Number,TypeSize,pApp,CKey)  \
    (m).h.u1.Length = DBGSS_API_MSG_LENGTH((TypeSize));   \
    (m).h.u2.ZeroInit = 0L;                               \
    (m).ApiNumber = (Number);                             \
    (m).AppClientId = *(pApp);                            \
    (m).ContinueKey = (PVOID)(CKey)

typedef enum _DBGSS_APINUMBER {
    DbgSsExceptionApi,
    DbgSsCreateThreadApi,
    DbgSsCreateProcessApi,
    DbgSsExitThreadApi,
    DbgSsExitProcessApi,
    DbgSsLoadDllApi,
    DbgSsUnloadDllApi,
    DbgSsMaxApiNumber
} DBGSS_APINUMBER;

typedef struct _DBGSS_CREATE_PROCESS {
    CLIENT_ID DebugUiClientId;
    DBGKM_CREATE_PROCESS NewProcess;
} DBGSS_CREATE_PROCESS, *PDBGSS_CREATE_PROCESS;

typedef struct _DBGSS_APIMSG {
    PORT_MESSAGE h;
    DBGKM_APINUMBER ApiNumber;
    NTSTATUS ReturnedStatus;
    CLIENT_ID AppClientId;
    PVOID ContinueKey;
    union {
        DBGKM_EXCEPTION Exception;
        DBGKM_CREATE_THREAD CreateThread;
        DBGSS_CREATE_PROCESS CreateProcessInfo;
        DBGKM_EXIT_THREAD ExitThread;
        DBGKM_EXIT_PROCESS ExitProcess;
        DBGKM_LOAD_DLL LoadDll;
        DBGKM_UNLOAD_DLL UnloadDll;
    } u;
} DBGSS_APIMSG, *PDBGSS_APIMSG;

#define DBGUI_MSG_OVERHEAD 8

#define DBGUI_API_MSG_LENGTH(TypeSize) \
            sizeof(DBGUI_APIMSG)<<16 | (DBGUI_MSG_OVERHEAD + (TypeSize))

#define DBGUI_FORMAT_API_MSG(m,Number,TypeSize)            \
    (m).h.u1.Length = DBGUI_API_MSG_LENGTH((TypeSize));     \
    (m).h.u2.ZeroInit = 0L;                               \
    (m).ApiNumber = (Number)

typedef enum _DBGUI_APINUMBER {
    DbgUiWaitStateChangeApi,
    DbgUiContinueApi,
    DbgUiMaxApiNumber
} DBGUI_APINUMBER;

typedef struct _DBGUI_CREATE_THREAD {
    HANDLE HandleToThread;
    DBGKM_CREATE_THREAD NewThread;
} DBGUI_CREATE_THREAD, *PDBGUI_CREATE_THREAD;

typedef struct _DBGUI_CREATE_PROCESS {
    HANDLE HandleToProcess;
    HANDLE HandleToThread;
    DBGKM_CREATE_PROCESS NewProcess;
} DBGUI_CREATE_PROCESS, *PDBGUI_CREATE_PROCESS;

typedef struct _DBGUI_WAIT_STATE_CHANGE {
    DBG_STATE NewState;
    CLIENT_ID AppClientId;
    union {
        DBGKM_EXCEPTION Exception;
        DBGUI_CREATE_THREAD CreateThread;
        DBGUI_CREATE_PROCESS CreateProcessInfo;
        DBGKM_EXIT_THREAD ExitThread;
        DBGKM_EXIT_PROCESS ExitProcess;
        DBGKM_LOAD_DLL LoadDll;
        DBGKM_UNLOAD_DLL UnloadDll;
    } StateInfo;
} DBGUI_WAIT_STATE_CHANGE, *PDBGUI_WAIT_STATE_CHANGE;

typedef struct _DBGUI_CONTINUE {
    CLIENT_ID AppClientId;
    NTSTATUS ContinueStatus;
} DBGUI_CONTINUE, *PDBGUI_CONTINUE;

typedef struct _DBGUI_APIMSG {
    PORT_MESSAGE h;
    union {
        HANDLE DbgStateChangeSemaphore;
        struct {
            DBGKM_APINUMBER ApiNumber;
            NTSTATUS ReturnedStatus;
            union {
                DBGUI_CONTINUE Continue;
                DBGUI_WAIT_STATE_CHANGE WaitStateChange;
            } u;
        };
    };
} DBGUI_APIMSG, *PDBGUI_APIMSG;


typedef
NTSTATUS
(*PDBGSS_UI_LOOKUP) (
    IN PCLIENT_ID AppClientId,
    OUT PCLIENT_ID DebugUiClientId
    );

typedef
NTSTATUS
(*PDBGSS_DBGKM_APIMSG_FILTER) (
    IN OUT PDBGKM_APIMSG ApiMsg
    );

typedef
NTSTATUS
(*PDBGSS_SUBSYSTEMKEY_LOOKUP) (
    IN PCLIENT_ID AppClientId,
    OUT PULONG SubsystemKey,
    IN BOOLEAN ProcessKey
    );
//
// DbgSs APIs
//

NTSTATUS
NTAPI
DbgSsInitialize(
    IN HANDLE KmReplyPort,
    IN PDBGSS_UI_LOOKUP UiLookUpRoutine,
    IN PDBGSS_SUBSYSTEMKEY_LOOKUP SubsystemKeyLookupRoutine OPTIONAL,
    IN PDBGSS_DBGKM_APIMSG_FILTER KmApiMsgFilter OPTIONAL
    );

VOID
NTAPI
DbgSsHandleKmApiMsg(
    IN PDBGKM_APIMSG ApiMsg,
    IN HANDLE ReplyEvent OPTIONAL
    );

typedef
NTSTATUS
(*PDBGSS_INITIALIZE_ROUTINE)(
    IN HANDLE KmReplyPort,
    IN PDBGSS_UI_LOOKUP UiLookUpRoutine,
    IN PDBGSS_SUBSYSTEMKEY_LOOKUP SubsystemKeyLookupRoutine OPTIONAL,
    IN PDBGSS_DBGKM_APIMSG_FILTER KmApiMsgFilter OPTIONAL
    );

typedef
VOID
(*PDBGSS_HANDLE_MSG_ROUTINE)(
    IN PDBGKM_APIMSG ApiMsg,
    IN HANDLE ReplyEvent OPTIONAL
    );

//
// DbgUi APIs
//

NTSTATUS
NTAPI
DbgUiConnectToDbg( VOID );

NTSTATUS
NTAPI
DbgUiWaitStateChange (
    OUT PDBGUI_WAIT_STATE_CHANGE StateChange,
    IN PLARGE_INTEGER Timeout OPTIONAL
    );

NTSTATUS
NTAPI
DbgUiContinue (
    IN PCLIENT_ID AppClientId,
    IN NTSTATUS ContinueStatus
    );

// begin_windbgkd

//
// DbgKd APIs are for the portable kernel debugger
//

//
// KD_PACKETS are the low level data format used in KD. All packets
// begin with a packet leader, byte count, packet type. The sequence
// for accepting a packet is:
//
//  - read 4 bytes to get packet leader.  If read times out (10 seconds)
//    with a short read, or if packet leader is incorrect, then retry
//    the read.
//
//  - next read 2 byte packet type.  If read times out (10 seconds) with
//    a short read, or if packet type is bad, then start again looking
//    for a packet leader.
//
//  - next read 4 byte packet Id.  If read times out (10 seconds)
//    with a short read, or if packet Id is not what we expect, then
//    ask for resend and restart again looking for a packet leader.
//
//  - next read 2 byte byte count.  If read times out (10 seconds) with
//    a short read, or if byte count is greater than PACKET_MAX_SIZE,
//    then start again looking for a packet leader.
//
//  - next read 4 byte packet data checksum.
//
//  - The packet data immediately follows the packet.  There should be
//    ByteCount bytes following the packet header.  Read the packet
//    data, if read times out (10 seconds) then start again looking for
//    a packet leader.
//


typedef struct _KD_PACKET {
    ULONG PacketLeader;
    USHORT PacketType;
    USHORT ByteCount;
    ULONG PacketId;
    ULONG Checksum;
} KD_PACKET, *PKD_PACKET;


#define PACKET_MAX_SIZE 4000
#define INITIAL_PACKET_ID 0x80800000    // DON't use 0
#define SYNC_PACKET_ID    0x00000800    // Or in with INITIAL_PACKET_ID
                                        // to force a packet ID reset.

//
// BreakIn packet
//

#define BREAKIN_PACKET                  0x62626262
#define BREAKIN_PACKET_BYTE             0x62

//
// Packet lead in sequence
//

#define PACKET_LEADER                   0x30303030 //0x77000077
#define PACKET_LEADER_BYTE              0x30

#define CONTROL_PACKET_LEADER           0x69696969
#define CONTROL_PACKET_LEADER_BYTE      0x69

//
// Packet Trailing Byte
//

#define PACKET_TRAILING_BYTE            0xAA

//
// Packet Types
//

#define PACKET_TYPE_UNUSED              0
#define PACKET_TYPE_KD_STATE_CHANGE     1
#define PACKET_TYPE_KD_STATE_MANIPULATE 2
#define PACKET_TYPE_KD_DEBUG_IO         3
#define PACKET_TYPE_KD_ACKNOWLEDGE      4       // Packet-control type
#define PACKET_TYPE_KD_RESEND           5       // Packet-control type
#define PACKET_TYPE_KD_RESET            6       // Packet-control type
#define PACKET_TYPE_MAX                 7

//
// If the packet type is PACKET_TYPE_KD_STATE_CHANGE, then
// the format of the packet data is as follows:
//

#define DbgKdExceptionStateChange   0x00003030L
#define DbgKdLoadSymbolsStateChange 0x00003031L

//
// Pathname Data follows directly
//

typedef struct _DBGKD_LOAD_SYMBOLS {
    ULONG PathNameLength;
    PVOID BaseOfDll;
    ULONG ProcessId;
    ULONG CheckSum;
    ULONG SizeOfImage;
    BOOLEAN UnloadSymbols;
} DBGKD_LOAD_SYMBOLS, *PDBGKD_LOAD_SYMBOLS;

typedef struct _DBGKD_WAIT_STATE_CHANGE {
    ULONG NewState;
    USHORT ProcessorType;
    USHORT Processor;
    ULONG NumberProcessors;
    PVOID Thread;
    PVOID ProgramCounter;
    union {
        DBGKM_EXCEPTION Exception;
        DBGKD_LOAD_SYMBOLS LoadSymbols;
    } u;
    DBGKD_CONTROL_REPORT ControlReport;
    CONTEXT Context;
} DBGKD_WAIT_STATE_CHANGE, *PDBGKD_WAIT_STATE_CHANGE;

//
// If the packet type is PACKET_TYPE_KD_STATE_MANIPULATE, then
// the format of the packet data is as follows:
//
// Api Numbers for state manipulation
//

#define DbgKdReadVirtualMemoryApi     0x00003130L
#define DbgKdWriteVirtualMemoryApi    0x00003131L
#define DbgKdGetContextApi            0x00003132L
#define DbgKdSetContextApi            0x00003133L
#define DbgKdWriteBreakPointApi       0x00003134L
#define DbgKdRestoreBreakPointApi     0x00003135L
#define DbgKdContinueApi              0x00003136L
#define DbgKdReadControlSpaceApi      0x00003137L
#define DbgKdWriteControlSpaceApi     0x00003138L
#define DbgKdReadIoSpaceApi           0x00003139L
#define DbgKdWriteIoSpaceApi          0x0000313AL
#define DbgKdRebootApi                0x0000313BL
#define DbgKdContinueApi2             0x0000313CL
#define DbgKdReadPhysicalMemoryApi    0x0000313DL
#define DbgKdWritePhysicalMemoryApi   0x0000313EL
#define DbgKdQuerySpecialCallsApi     0x0000313FL
#define DbgKdSetSpecialCallApi        0x00003140L
#define DbgKdClearSpecialCallsApi     0x00003141L
#define DbgKdSetInternalBreakPointApi 0x00003142L
#define DbgKdGetInternalBreakPointApi 0x00003143L
#define DbgKdReadIoSpaceExtendedApi   0x00003144L
#define DbgKdWriteIoSpaceExtendedApi  0x00003145L
#define DbgKdGetVersionApi            0x00003146L
#define DbgKdWriteBreakPointExApi     0x00003147L
#define DbgKdRestoreBreakPointExApi   0x00003148L
#define DbgKdCauseBugCheckApi         0x00003149L
#define DbgKdSwitchProcessor          0x00003150L

//
// Response is a read memory message with data following
//

typedef struct _DBGKD_READ_MEMORY {
    PVOID TargetBaseAddress;
    ULONG TransferCount;
    ULONG ActualBytesRead;
} DBGKD_READ_MEMORY, *PDBGKD_READ_MEMORY;

//
// Data follows directly
//

typedef struct _DBGKD_WRITE_MEMORY {
    PVOID TargetBaseAddress;
    ULONG TransferCount;
    ULONG ActualBytesWritten;
} DBGKD_WRITE_MEMORY, *PDBGKD_WRITE_MEMORY;

//
// Response is a get context message with a full context record following
//

typedef struct _DBGKD_GET_CONTEXT {
    ULONG ContextFlags;
} DBGKD_GET_CONTEXT, *PDBGKD_GET_CONTEXT;

//
// Full Context record follows
//

typedef struct _DBGKD_SET_CONTEXT {
    ULONG ContextFlags;
} DBGKD_SET_CONTEXT, *PDBGKD_SET_CONTEXT;

typedef struct _DBGKD_WRITE_BREAKPOINT {
    PVOID BreakPointAddress;
    ULONG BreakPointHandle;
} DBGKD_WRITE_BREAKPOINT, *PDBGKD_WRITE_BREAKPOINT;

typedef struct _DBGKD_RESTORE_BREAKPOINT {
    ULONG BreakPointHandle;
} DBGKD_RESTORE_BREAKPOINT, *PDBGKD_RESTORE_BREAKPOINT;

typedef struct _DBGKD_BREAKPOINTEX {
    ULONG     BreakPointCount;
    NTSTATUS  ContinueStatus;
} DBGKD_BREAKPOINTEX, *PDBGKD_BREAKPOINTEX;

typedef struct _DBGKD_CONTINUE {
    NTSTATUS ContinueStatus;
} DBGKD_CONTINUE, *PDBGKD_CONTINUE;

typedef struct _DBGKD_CONTINUE2 {
    NTSTATUS ContinueStatus;
    DBGKD_CONTROL_SET ControlSet;
} DBGKD_CONTINUE2, *PDBGKD_CONTINUE2;

typedef struct _DBGKD_READ_WRITE_IO {
    ULONG DataSize;                     // 1, 2, 4
    PVOID IoAddress;
    ULONG DataValue;
} DBGKD_READ_WRITE_IO, *PDBGKD_READ_WRITE_IO;

typedef struct _DBGKD_READ_WRITE_IO_EXTENDED {
    ULONG DataSize;                     // 1, 2, 4
    ULONG InterfaceType;
    ULONG BusNumber;
    ULONG AddressSpace;
    PVOID IoAddress;
    ULONG DataValue;
} DBGKD_READ_WRITE_IO_EXTENDED, *PDBGKD_READ_WRITE_IO_EXTENDED;

typedef struct _DBGKD_QUERY_SPECIAL_CALLS {
    ULONG NumberOfSpecialCalls;
    // ULONG SpecialCalls[];
} DBGKD_QUERY_SPECIAL_CALLS, *PDBGKD_QUERY_SPECIAL_CALLS;

typedef struct _DBGKD_SET_SPECIAL_CALL {
    ULONG SpecialCall;
} DBGKD_SET_SPECIAL_CALL, *PDBGKD_SET_SPECIAL_CALL;

typedef struct _DBGKD_SET_INTERNAL_BREAKPOINT {
    ULONG BreakpointAddress;
    ULONG Flags;
} DBGKD_SET_INTERNAL_BREAKPOINT, *PDBGKD_SET_INTERNAL_BREAKPOINT;

typedef struct _DBGKD_GET_INTERNAL_BREAKPOINT {
    ULONG BreakpointAddress;
    ULONG Flags;
    ULONG Calls;
    ULONG MaxCallsPerPeriod;
    ULONG MinInstructions;
    ULONG MaxInstructions;
    ULONG TotalInstructions;
} DBGKD_GET_INTERNAL_BREAKPOINT, *PDBGKD_GET_INTERNAL_BREAKPOINT;

#define DBGKD_INTERNAL_BP_FLAG_COUNTONLY 0x00000001 // don't count instructions
#define DBGKD_INTERNAL_BP_FLAG_INVALID   0x00000002 // disabled BP
#define DBGKD_INTERNAL_BP_FLAG_SUSPENDED 0x00000004 // temporarily suspended
#define DBGKD_INTERNAL_BP_FLAG_DYING     0x00000008 // kill on exit

typedef struct _DBGKD_GET_VERSION {
    USHORT  MajorVersion;
    USHORT  MinorVersion;
    USHORT  ProtocolVersion;
    USHORT  Flags;
    ULONG   KernBase;
    ULONG   PsLoadedModuleList;
} DBGKD_GET_VERSION, *PDBGKD_GET_VERSION;

#define DBGKD_VERS_FLAG_MP      0x0001      // kernel is MP built


typedef struct _DBGKD_MANIPULATE_STATE {
    ULONG ApiNumber;
    USHORT ProcessorType;
    USHORT Processor;
    NTSTATUS ReturnStatus;
    union {
        DBGKD_READ_MEMORY ReadMemory;
        DBGKD_WRITE_MEMORY WriteMemory;
        DBGKD_GET_CONTEXT GetContext;
        DBGKD_SET_CONTEXT SetContext;
        DBGKD_WRITE_BREAKPOINT WriteBreakPoint;
        DBGKD_RESTORE_BREAKPOINT RestoreBreakPoint;
        DBGKD_CONTINUE Continue;
        DBGKD_CONTINUE2 Continue2;
        DBGKD_READ_WRITE_IO ReadWriteIo;
        DBGKD_READ_WRITE_IO_EXTENDED ReadWriteIoExtended;
        DBGKD_QUERY_SPECIAL_CALLS QuerySpecialCalls;
        DBGKD_SET_SPECIAL_CALL SetSpecialCall;
        DBGKD_SET_INTERNAL_BREAKPOINT SetInternalBreakpoint;
        DBGKD_GET_INTERNAL_BREAKPOINT GetInternalBreakpoint;
        DBGKD_GET_VERSION GetVersion;
        DBGKD_BREAKPOINTEX BreakPointEx;
    } u;
} DBGKD_MANIPULATE_STATE, *PDBGKD_MANIPULATE_STATE;

//
// This is the format for the trace data passed back from the kernel to
// the debugger to describe multiple calls that have returned since the
// last trip back.  The basic format is that there are a bunch of these
// (4 byte) unions stuck together.  Each union is of one of two types: a
// 4 byte unsigned long interger, or a three field struct, describing a
// call (where "call" is delimited by returning or exiting the symbol
// scope).  If the number of instructions executed is too big to fit
// into a USHORT -1, then the Instructions field has
// TRACE_DATA_INSTRUCTIONS_BIG and the next union is a LongNumber
// containing the real number of instructions executed.
//
// The very first union returned in each callback is a LongNumber
// containing the number of unions returned (including the "size"
// record, os it's always at least 1 even if there's no data to return).
//
// This is all returned to the debugger when one of two things
// happens:
//
//   1) The pc moves out of all defined symbol ranges
//   2) The buffer of trace data entries is filled.
//
// The "trace done" case is hacked around on the debugger side.  It
// guarantees that the pc address that indicates a trace exit never
// winds up in a defined symbol range.
//
// The only other complexity in this system is handling the SymbolNumber
// table.  This table is kept in parallel by the kernel and the
// debugger.  When the PC exits a known symbol range, the Begin and End
// symbol ranges are set by the debugger and are allocated to the next
// symbol slot upon return.  "The next symbol slot" means the numerical
// next slot number, unless we've filled all slots, in which case it is
// #0.  (ie., allocation is cyclic and not LRU or something).  The
// SymbolNumber table is flushed when a SpecialCalls call is made (ie.,
// at the beginning of the WatchTrace).
//

typedef union _DBGKD_TRACE_DATA {
    struct {
        UCHAR SymbolNumber;
        CHAR LevelChange;
        USHORT Instructions;
    } s;
    ULONG LongNumber;
} DBGKD_TRACE_DATA, *PDBGKD_TRACE_DATA;

#define TRACE_DATA_INSTRUCTIONS_BIG 0xffff

#define TRACE_DATA_BUFFER_MAX_SIZE 40

//
// If the packet type is PACKET_TYPE_KD_DEBUG_IO, then
// the format of the packet data is as follows:
//

#define DbgKdPrintStringApi     0x00003230L
#define DbgKdGetStringApi       0x00003231L

//
// For print string, the Null terminated string to print
// immediately follows the message
//
typedef struct _DBGKD_PRINT_STRING {
    ULONG LengthOfString;
} DBGKD_PRINT_STRING, *PDBGKD_PRINT_STRING;

//
// For get string, the Null terminated promt string
// immediately follows the message. The LengthOfStringRead
// field initially contains the maximum number of characters
// to read. Upon reply, this contains the number of bytes actually
// read. The data read immediately follows the message.
//
//
typedef struct _DBGKD_GET_STRING {
    ULONG LengthOfPromptString;
    ULONG LengthOfStringRead;
} DBGKD_GET_STRING, *PDBGKD_GET_STRING;

typedef struct _DBGKD_DEBUG_IO {
    ULONG ApiNumber;
    USHORT ProcessorType;
    USHORT Processor;
    union {
        DBGKD_PRINT_STRING PrintString;
        DBGKD_GET_STRING GetString;
    } u;
} DBGKD_DEBUG_IO, *PDBGKD_DEBUG_IO;


VOID
NTAPI
DbgKdSendBreakIn(
    VOID
    );

PUCHAR
NTAPI
DbgKdGets(
    PUCHAR Buffer,
    USHORT Length
    );
// end_windbgkd

NTSTATUS
NTAPI
DbgKdConnectAndInitialize(
    IN ULONG CommunicationPortNumber OPTIONAL,
    IN PSTRING BootImageName OPTIONAL,
    IN PUSHORT LogHandle
    );

// begin_windbgkd

NTSTATUS
NTAPI
DbgKdWaitStateChange(
    OUT PDBGKD_WAIT_STATE_CHANGE StateChange,
    OUT PVOID Buffer,
    IN ULONG BufferLength
    );

NTSTATUS
NTAPI
DbgKdContinue (
    IN NTSTATUS ContinueStatus
    );

NTSTATUS
NTAPI
DbgKdContinue2 (
    IN NTSTATUS ContinueStatus,
    IN DBGKD_CONTROL_SET ControlSet
    );

NTSTATUS
NTAPI
DbgKdReadVirtualMemory(
    IN PVOID TargetBaseAddress,
    OUT PVOID UserInterfaceBuffer,
    IN ULONG TransferCount,
    OUT PULONG ActualBytesRead OPTIONAL
    );

NTSTATUS
NTAPI
DbgKdWriteVirtualMemory(
    IN PVOID TargetBaseAddress,
    OUT PVOID UserInterfaceBuffer,
    IN ULONG TransferCount,
    OUT PULONG ActualBytesWritten OPTIONAL
    );

NTSTATUS
NTAPI
DbgKdReadPhysicalMemory(
    IN PHYSICAL_ADDRESS TargetBaseAddress,
    OUT PVOID UserInterfaceBuffer,
    IN ULONG TransferCount,
    OUT PULONG ActualBytesRead OPTIONAL
    );

NTSTATUS
NTAPI
DbgKdWritePhysicalMemory(
    IN PHYSICAL_ADDRESS TargetBaseAddress,
    OUT PVOID UserInterfaceBuffer,
    IN ULONG TransferCount,
    OUT PULONG ActualBytesWritten OPTIONAL
    );

NTSTATUS
NTAPI
DbgKdReadControlSpace(
    IN USHORT Processor,
    IN PVOID TargetBaseAddress,
    OUT PVOID UserInterfaceBuffer,
    IN ULONG TransferCount,
    OUT PULONG ActualBytesRead OPTIONAL
    );

NTSTATUS
NTAPI
DbgKdWriteControlSpace(
    IN USHORT Processor,
    IN PVOID TargetBaseAddress,
    OUT PVOID UserInterfaceBuffer,
    IN ULONG TransferCount,
    OUT PULONG ActualBytesWritten OPTIONAL
    );

NTSTATUS
NTAPI
DbgKdReadIoSpace(
    IN PVOID IoAddress,
    OUT PVOID ReturnedData,
    IN ULONG DataSize
    );

NTSTATUS
NTAPI
DbgKdWriteIoSpace(
    IN PVOID IoAddress,
    IN ULONG DataValue,
    IN ULONG DataSize
    );

NTSTATUS
NTAPI
DbgKdGetContext(
    IN USHORT Processor,
    IN OUT PCONTEXT Context
    );

NTSTATUS
NTAPI
DbgKdSetContext(
    IN USHORT Processor,
    IN PCONTEXT Context
    );

NTSTATUS
NTAPI
DbgKdWriteBreakPoint(
    IN PVOID BreakPointAddress,
    OUT PULONG BreakPointHandle
    );

NTSTATUS
NTAPI
DbgKdRestoreBreakPoint(
    IN ULONG BreakPointHandle
    );

NTSTATUS
NTAPI
DbgKdReboot(
    VOID
    );

#ifdef _X86_
NTSTATUS
NTAPI
DbgKdLookupSelector(
    IN USHORT Processor,
    IN OUT PDESCRIPTOR_TABLE_ENTRY pDescriptorTableEntry
    );
#endif

// end_windbgkd

//
// Dbg Status Codes
//

//
//  Success values
//

#define DBG_EXCEPTION_HANDLED           ((NTSTATUS)0x00010001L) // windbgkd

#define DBG_CONTINUE                    ((NTSTATUS)0x00010002L) // winnt

//
// Informational values
//

#define DBG_REPLY_LATER                 ((NTSTATUS)0x40010001L)

#define DBG_UNABLE_TO_PROVIDE_HANDLE    ((NTSTATUS)0x40010002L)

#define DBG_TERMINATE_THREAD            ((NTSTATUS)0x40010003L) // winnt

#define DBG_TERMINATE_PROCESS           ((NTSTATUS)0x40010004L) // winnt

#define DBG_CONTROL_C                   ((NTSTATUS)0x40010005L) // winnt

#define DBG_PRINTEXCEPTION_C            ((NTSTATUS)0x40010006L)

#define DBG_RIPEXCEPTION                ((NTSTATUS)0x40010007L)

#define DBG_CONTROL_BREAK               ((NTSTATUS)0x40010008L) // winnt

//
// Warning values
//

#define DBG_EXCEPTION_NOT_HANDLED       ((NTSTATUS)0x80010001L) // winnt

//
// Error values
//

#define DBG_NO_STATE_CHANGE             ((NTSTATUS)0xc0010001L)

#define DBG_APP_NOT_IDLE                ((NTSTATUS)0xc0010002L)



#endif // _NTDBG_
