/*++

Copyright (c) 1990  Microsoft Corporation

Module Name:

    vdmexts.h

Abstract:

    This file header defines most of the stuff used in VDMEXTS

Revision History:

    Neil Sandlin (NeilSa) 15-Jan-1996 Merged with vdmexts

--*/


//
// Pointers to WINDBG api
//

extern PWINDBG_OUTPUT_ROUTINE Print;
extern PWINDBG_GET_EXPRESSION GetExpression;
extern PWINDBG_GET_SYMBOL GetSymbol;
extern PWINDBG_DISASM Disassemble;
extern PWINDBG_CHECK_CONTROL_C CheckCtrlC;

extern PWINDBG_READ_PROCESS_MEMORY_ROUTINE  ReadMem;
extern PWINDBG_WRITE_PROCESS_MEMORY_ROUTINE WriteMem;

extern PWINDBG_GET_THREAD_CONTEXT_ROUTINE     ExtGetThreadContext;
extern PWINDBG_SET_THREAD_CONTEXT_ROUTINE     ExtSetThreadContext;
extern PWINDBG_IOCTL_ROUTINE                  ExtIoctl;
extern PWINDBG_STACKTRACE_ROUTINE             ExtStackTrace;

extern HANDLE hCurrentProcess;
extern HANDLE hCurrentThread;
extern LPSTR lpArgumentString;

#define PRINTF          (* Print)
#define EXPRESSION      (* GetExpression)

#define ReadDword(x)     read_dword((ULONG)x, FALSE)
#define ReadWord(x)      read_word ((ULONG)x, FALSE)
#define ReadByte(x)      read_byte ((ULONG)x, FALSE)
#define ReadDwordSafe(x) read_dword((ULONG)x, TRUE)
#define ReadWordSafe(x)  read_word ((ULONG)x, TRUE)
#define ReadByteSafe(x)  read_byte ((ULONG)x, TRUE)
#define ReadGNode32(x,p) read_gnode32((ULONG)x,p,FALSE)
#define ReadGNode32Safe(x,p) read_gnode32((ULONG)x,p,TRUE)

/****** macros common to all versions *******/
#define CMD_ARGLIST  HANDLE CurrentProcess,                 \
                     HANDLE CurrentThread,                  \
                     DWORD CurrentPc,                       \
                     PWINDBG_EXTENSION_APIS pXApis,         \
                     LPSTR ArgumentString

#define CMD_INIT() \
    UNREFERENCED_PARAMETER(CurrentPc);                      \
    hCurrentProcess = CurrentProcess;                       \
    hCurrentThread = CurrentThread;                         \
    lpArgumentString = ArgumentString;                      \
                                                            \
    Print         = pXApis->lpOutputRoutine;                \
    GetSymbol     = pXApis->lpGetSymbolRoutine;             \
    GetExpression = pXApis->lpGetExpressionRoutine;         \
    CheckCtrlC    = pXApis->lpCheckControlCRoutine;         \
                                                            \
    ReadMem       = pXApis->lpReadProcessMemoryRoutine;     \
    WriteMem      = pXApis->lpWriteProcessMemoryRoutine;    \
    ExtGetThreadContext       = pXApis->lpGetThreadContextRoutine;     \
    ExtSetThreadContext       = pXApis->lpSetThreadContextRoutine;     \
    ExtIoctl                  = pXApis->lpIoctlRoutine;                \
    ExtStackTrace             = pXApis->lpStackTraceRoutine;           \


#define READMEM( addr, buff, size ) ReadProcessMem(addr, buff, size)
#define WRITEMEM( addr, buff, size ) WriteProcessMem(addr, buff, size)

#define READMEM_XRET(buff, addr)\
try {\
    READMEM( (LPVOID)(addr), (LPVOID)&(buff), sizeof(buff));\
} except (EXCEPTION_EXECUTE_HANDLER) {\
    Print("ReadProcessMemory Failed !\n");\
    return;\
}


#define READMEM_XRETV(buff, addr, ret)\
try {\
    READMEM((LPVOID) (addr), (LPVOID)&(buff), sizeof(buff));\
} except (EXCEPTION_EXECUTE_HANDLER) {\
    Print("ReadProcessMemory Failed !\n");\
    return ret;\
}


#define WRITEMEM_XRET(addr, buff)\
try {\
    WRITEMEM((LPVOID)(addr), (LPVOID)&(buff), sizeof(buff));\
} except (EXCEPTION_EXECUTE_HANDLER) {\
    Print("WriteProcessMemory Failed !\n");\
    return;\
}

#define WRITEMEM_N_XRET(addr, buff, n)\
try {\
    WRITEMEM((LPVOID)(addr), (LPVOID)(buff), n);\
} except (EXCEPTION_EXECUTE_HANDLER) {\
    Print("WriteProcessMemory Failed !\n");\
    return;\
}


#define GETEXPRVALUE(dst, expr, typ) \
{\
   PVOID lpA = (PVOID)GetExpression(expr);\
   READMEM_XRET(dst, lpA);\
}

#define GETEXPRADDR(dst, expr) \
{\
   dst = (PVOID)GetExpression(expr);\
}


#define ASSERT_WOW_PRESENT {                                        \
    if (!EXPRESSION("wow32!gptdTaskHead")) {                        \
        PRINTF("Could not resolve needed symbols for WOW32\n");     \
        return;                                                     \
    }                                                               \
}

#define ASSERT_CHECKED_WOW_PRESENT {                                \
    if (!EXPRESSION("wow32!iCircBuffer")) {                         \
        PRINTF("Could not resolve needed symbols for checked WOW32\n");    \
        return;                                                     \
    }                                                               \
}

#define BEFORE      0
#define AFTER       1

#define RPL_MASK    0x78
#define V86_BITS    0x20000

#define SELECTOR_LDT            0x04
#define SELECTOR_RPL            0x03

#define V86_MODE    0
#define PROT_MODE   1
#define FLAT_MODE   2
#define NOT_LOADED  3

#define CALL_NEAR_RELATIVE   0xE8
#define CALL_NEAR_INDIRECT   0xFF
#define INDIRECT_NEAR_TYPE   0x02
#define CALL_FAR_ABSOLUTE    0x9A
#define CALL_FAR_INDIRECT    0xFF
#define INDIRECT_FAR_TYPE    0x03
#define PUSH_CS              0x0E
#define ADD_SP               0xC483

#define TYPE_BITS            0x38
#define TYPE0                0x00
#define TYPE1                0x08
#define TYPE2                0x10
#define TYPE3                0x18
#define TYPE4                0x20
#define TYPE5                0x28
#define TYPE6                0x30
#define TYPE7                0x38

#define MOD_BITS             0xC0
#define MOD0                 0x00
#define MOD1                 0x40
#define MOD2                 0x80
#define MOD3                 0xC0

#define RM_BITS              0x07
#define RM0                  0x00
#define RM1                  0x01
#define RM2                  0x02
#define RM3                  0x03
#define RM4                  0x04
#define RM5                  0x05
#define RM6                  0x06
#define RM7                  0x07

#define FLAG_OVERFLOW       0x0800
#define FLAG_DIRECTION      0x0400
#define FLAG_INTERRUPT      0x0200
#define FLAG_SIGN           0x0080
#define FLAG_ZERO           0x0040
#define FLAG_AUXILLIARY     0x0010
#define FLAG_PARITY         0x0004
#define FLAG_CARRY          0x0001


typedef struct _SELECTORINFO {
    DWORD Base;
    DWORD Limit;
    BOOL bCode;
    BOOL bSystem;
    BOOL bPresent;
    BOOL bWrite;
    BOOL bAccessed;
    BOOL bBig;
    BOOL bExpandDown;
} SELECTORINFO;

typedef struct _segentry {
    struct _segentry *Next;
    int     type;
    char    szExePath[MAX_PATH16];
    char    szModule[MAX_MODULE_NAME];
    WORD    selector;
    WORD    segment;
    DWORD   length;
} SEGENTRY, *PSEGENTRY;

#define SEGTYPE_V86         1
#define SEGTYPE_PROT        2

#pragma  pack(1)

typedef struct _GNODE32 {     // GlobalArena
   DWORD pga_next      ;    // next arena entry (last points to self)
   DWORD pga_prev      ;    // previous arena entry (first points to self)
   DWORD pga_address   ;    // 32 bit linear address of memory
   DWORD pga_size      ;    // 32 bit size in bytes
   WORD  pga_handle    ;    // back link to handle table entry
   WORD  pga_owner     ;    // Owner field (current task)
   BYTE  pga_count     ;    // lock count for movable segments
   BYTE  pga_pglock    ;    // # times page locked
   BYTE  pga_flags     ;    // 1 word available for flags
   BYTE  pga_selcount  ;    // Number of selectors allocated
   DWORD pga_lruprev   ;    // Previous entry in lru chain
   DWORD pga_lrunext   ;    // Next entry in lru chain
} GNODE32;
typedef GNODE32 UNALIGNED *PGNODE32;

typedef struct _GHI32 {
    WORD  hi_check     ;    // arena check word (non-zero enables heap checking)
    WORD  hi_freeze    ;    // arena frozen word (non-zero prevents compaction)
    WORD  hi_count     ;    // #entries in arena
    WORD  hi_first     ;    // first arena entry (sentinel, always busy)
    WORD  hi_res1      ;    // reserved
    WORD  hi_last      ;    // last arena entry (sentinel, always busy)
    WORD  hi_res2      ;    // reserved
    BYTE  hi_ncompact  ;    // #compactions done so far (max of 3)
    BYTE  hi_dislevel  ;    // current discard level
    DWORD hi_distotal  ;    // total amount discarded so far
    WORD  hi_htable    ;    // head of handle table list
    WORD  hi_hfree     ;    // head of free handle table list
    WORD  hi_hdelta    ;    // #handles to allocate each time
    WORD  hi_hexpand   ;    // address of near procedure to expand handles for this arena
    WORD  hi_pstats    ;    // address of statistics table or zero
} GHI32;
typedef GHI32 UNALIGNED *PGHI32;

typedef struct _HEAPENTRY {
    GNODE32 gnode;
    DWORD CurrentEntry;
    DWORD NextEntry;
    WORD Selector;
    int  SegmentNumber;
    char OwnerName[9];
    char FileName[9];
    char ModuleArg[9];
} HEAPENTRY;

typedef struct _NEHEADER {
    WORD ne_magic       ;
    BYTE ne_ver         ;
    BYTE ne_rev         ;
    WORD ne_enttab      ;
    WORD ne_cbenttab    ;
    DWORD ne_crc        ;
    WORD ne_flags       ;
    WORD ne_autodata    ;
    WORD ne_heap        ;
    WORD ne_stack       ;
    DWORD ne_csip       ;
    DWORD ne_sssp       ;
    WORD ne_cseg        ;
    WORD ne_cmod        ;
    WORD ne_cbnrestab   ;
    WORD ne_segtab      ;
    WORD ne_rsrctab     ;
    WORD ne_restab      ;
    WORD ne_modtab      ;
    WORD ne_imptab      ;
    DWORD ne_nrestab    ;
    WORD ne_cmovent     ;
    WORD ne_align       ;
    WORD ne_cres        ;
    BYTE ne_exetyp      ;
    BYTE ne_flagsothers ;
    WORD ne_pretthunks  ;
    WORD ne_psegrefbytes;
    WORD ne_swaparea    ;
    WORD ne_expver      ;
} NEHEADER;
typedef NEHEADER UNALIGNED *PNEHEADER;

#pragma  pack()


#ifndef i386

//
// Structures in 486 cpu for obtaining registers (FROM NT_CPU.C)
//

typedef struct NT_CPU_REG {
    ULONG *nano_reg;         /* where the nano CPU keeps the register */
    ULONG *reg;              /* where the light compiler keeps the reg */
    ULONG *saved_reg;        /* where currently unused bits are kept */
    ULONG universe_8bit_mask;/* is register in 8-bit form? */
    ULONG universe_16bit_mask;/* is register in 16-bit form? */
} NT_CPU_REG;

typedef struct NT_CPU_INFO {
    /* Variables for deciding what mode we're in */
    BOOL *in_nano_cpu;      /* is the Nano CPU executing? */
    ULONG *universe;         /* the mode that the CPU is in */

    /* General purpose register pointers */
    NT_CPU_REG eax, ebx, ecx, edx, esi, edi, ebp;

    /* Variables for getting SP or ESP. */
    BOOL *stack_is_big;     /* is the stack 32-bit? */
    ULONG *nano_esp;         /* where the Nano CPU keeps ESP */
    UCHAR **host_sp;          /* ptr to variable holding stack pointer as a
                               host address */
    UCHAR **ss_base;          /* ptr to variables holding base of SS as a
                               host address */
    ULONG *esp_sanctuary;    /* top 16 bits of ESP if we're now using SP */

    ULONG *eip;

    /* Segment registers. */
    USHORT *cs, *ds, *es, *fs, *gs, *ss;

    ULONG *flags;

    /* CR0, mainly to let us figure out if we're in real or protect mode */
    ULONG *cr0;
} NT_CPU_INFO;


#endif // i386



BOOL
WINAPI
ReadProcessMem(
    LPVOID lpBaseAddress,
    LPVOID lpBuffer,
    DWORD nSize
    );

BOOL
WINAPI
WriteProcessMem(
    LPVOID lpBaseAddress,
    LPVOID lpBuffer,
    DWORD nSize
    );

BOOL
ReadMemExpression(
    LPSTR expr,
    LPVOID buffer,
    ULONG len
    );

BOOL
CheckGlobalHeap(
    BOOL bVerbose
    );

int GetContext(
    VDMCONTEXT* lpContext
);

ULONG GetInfoFromSelector(
    WORD                    selector,
    int                     mode,
    SELECTORINFO            *si
);

BOOL
FindHeapEntry(
    HEAPENTRY *he,
    UINT FindMethod,
    BOOL bVerbose
    );

#define FHE_FIND_ANY 0
#define FHE_FIND_SEL_ONLY 1
#define FHE_FIND_MOD_ONLY 2

#define FHE_FIND_QUIET FALSE
#define FHE_FIND_VERBOSE TRUE

BOOL
FindAddress(
    LPSTR       sym_text,
    LPSTR       filename,
    WORD        *psegment,
    WORD        *pselector,
    LONG        *poffset,
    int         *pmode,
    BOOL        bDumpAll
    );

BOOL FindSymbol(
    WORD        selector,
    LONG        offset,
    LPSTR       sym_text,
    LONG        *dist,
    int         direction,
    int         mode
);

int
unassemble_one(
    BYTE *pInstrStart,
    BOOL bDefaultBig,
    WORD wInstrSeg,
    DWORD dwInstrOff,
    char *pchOutput,
    char *pchExtra,
    VDMCONTEXT *pThreadContext,
    int mode
    );


ULONG GetIntelBase(
    VOID
);

DWORD read_dword(
    ULONG   lpAddress,
    BOOL    bSafe
);

WORD read_word(
    ULONG   lpAddress,
    BOOL    bSafe
);

BYTE read_byte(
    ULONG   lpAddress,
    BOOL    bSafe
);

BOOL read_gnode32(
    ULONG   lpAddress,
    PGNODE32  p,
    BOOL    bSafe
);

BOOL GetNextToken(
    VOID
    );

ULONG EvaluateToken(
    VOID
    );

VOID helpAPIProfDmp(
    VOID
    );

VOID helpMsgProfDmp(
    VOID
    );

BOOL
InVdmPrompt(
    VOID
    );

BOOL ParseIntelAddress(
    int *pMode,
    WORD *pSelector,
    PULONG pOffset
    );

VOID
ParseModuleName(
    LPSTR szName,
    LPSTR szPath
    );

VOID
EnableDebuggerBreakpoints(
    VOID
    );

BOOL
IsVdmBreakPoint(
    USHORT selector,
    ULONG offset,
    BOOL bProt,
    PULONG pBpNum,
    PUCHAR pBpData
    );

BOOL
LoadBreakPointCache(
    VOID
    );

BOOL
SkipToNextWhiteSpace(
    VOID
    );

BOOL
IsTokenHex(
    VOID
    );

PSEGENTRY
GetSegtablePointer(
    VOID
    );

VOID Drp (VOID);
VOID Erp (VOID);
VOID EventInfop (VOID);
VOID ProfDumpp (VOID);
VOID ProfIntp (VOID);
VOID ProfStartp (VOID);
VOID ProfStopp (VOID);
VOID VdmTibp (VOID);
VOID Fpup (VOID);
BOOL DumpEnvironment(WORD segEnv, int mode);
ULONG GetCurrentVdmTib(VOID);