/* $Id: $ */
/** @file
 *
 * spy1 - header for structure and protptypes shared with the hook.
 *
 * Copyright (c) 2006 knut st. osmundsen <bird@anduin.net>
 *
 * GPL
 *
 */

#ifndef __spy1_h__
#define __spy1_h__

/** @name Various OS/2 stuff from the DDK.
 * Mainly from video/rel/.../pmwinp.mac and pmwinx.h.
 * @{ */

/**
 * Keyboard event.
 */
typedef struct _KBDEVENT {    /* kevt */
    BYTE monFlags;          /* Open, Close and Flush monitor flags */
    BYTE scancode;          /* Original scan code (actually high byte of
                               monitor flags */
    BYTE xlatedchar;        /* Output of interrupt level character translation
                               table */

    BYTE xlatedscan;        /* Translated scan code.  Different only for
                               the enhanced keyboard */

    USHORT shiftDBCS;         /* DBCS shift state and status */
    USHORT shiftstate;        /* Current state of shift keys */
    ULONG time;             /* millisecond counter time stamp */
    USHORT ddFlags;           /* Keyboard device driver flags */
} KBDEVENT;
typedef KBDEVENT *PKBDEVENT;

// guess MON_* are for the monFlags field.
#define MON_OPEN	EQU	0001H
#define MON_CLOSE	EQU	0002H
#define MON_FLUSH	EQU	0004H
// guess KSS_* is for the shiftstate field.
#define KSS_SYSREQ	EQU	8000H
#define KSS_CAPSLOCK	EQU	4000H
#define KSS_NUMLOCK	EQU	2000H
#define KSS_SCROLLLOCK	EQU	1000H
#define KSS_RIGHTALT	EQU	0800H
#define KSS_RIGHTCTRL	EQU	0400H
#define KSS_LEFTALT	EQU	0200H
#define KSS_LEFTCTRL	EQU	0100H
#define KSS_INSERTON	EQU	0080H
#define KSS_CAPSLOCKON	EQU	0040H
#define KSS_NUMLOCKON	EQU	0020H
#define KSS_SCROLLLOCKON	EQU	0010H
#define KSS_EITHERALT	EQU	0008H
#define KSS_EITHERCTRL	EQU	0004H
#define KSS_LEFTSHIFT	EQU	0002H
#define KSS_RIGHTSHIFT	EQU	0001H
#define KSS_EITHERSHIFT	EQU	0003H
/* Valid values for ddFlags field */
#define KDD_MONFLAG1    0x8000 // bird: conflicts with KDD_KC_LONEKEY - relevant for VIOCHAR?
#define KDD_MONFLAG2	0x4000 // bird: conflicts with KDD_KC_PREVDOWN - relevant for VIOCHAR?
#define KDD_RESERVED	0x3C00
#define KDD_ACCENTED	0x0200
#define KDD_MULTIMAKE	0x0100
#define KDD_SECONDARY	0x0080
#define KDD_BREAK	0x0040
#define KDD_EXTENDEDKEY	0x0020
#define KDD_ACTIONFIELD	0x001F
#define KDD_KC_LONEKEY	0x8000
#define KDD_KC_PREVDOWN	0x4000
#define KDD_KC_KEYUP	0x2000
#define KDD_KC_ALT	0x1000
#define KDD_KC_CTRL	0x0800
#define KDD_KC_SHIFT	0x0400
#define KDD_KC_FLAGS	0x0FC00
/* Valid values for KDD_ACTIONFIELD portion of ddFlags field */
#define KDD_PUTINKIB	0x0000
#define KDD_ACK	0x0001
#define KDD_PREFIXKEY	0x0002
#define KDD_OVERRUN	0x0003
#define KDD_RESEND	0x0004
#define KDD_REBOOTKEY	0x0005
#define KDD_DUMPKEY	0x0006
#define KDD_SHIFTKEY	0x0007
#define KDD_PAUSEKEY	0x0008
#define KDD_PSEUDOPAUSE	0x0009
#define KDD_WAKEUPKEY	0x000A
#define KDD_BADACCENT	0x000B
#define KDD_HOTKEY	0x000C
#define KDD_ACCENTKEY	0x0010
#define KDD_BREAKKEY	0x0011
#define KDD_PSEUDOBREAK	0x0012
#define KDD_PRTSCKEY	0x0013
#define KDD_PRTECHOKEY	0x0014
#define KDD_PSEUDOPRECH	0x0015
#define KDD_STATUSCHG	0x0016
#define KDD_WRITTENKEY	0x0017
#define KDD_UNDEFINED	0x001F

/// PMWIN.174
KBDEVENT KbdPacket[2];

/** @} */


/** The event type. */
typedef enum SPY1EVENTTYPE
{
    /** The usual invalid entry. */
    SPY1EVENTTYPE_INVALID = 0,
    /** A qmsg being removed.
     * SPY1EVENT::u::Msg contains the message. */
    SPY1EVENTTYPE_MSG_REMOVED,
    /** A qmsg being peeked at.
     * SPY1EVENT::u::Msg contains the message. */
    SPY1EVENTTYPE_MSG_PEEK
} SPY1EVENTTYPE;

/**
 * A recorded event.
 */
typedef struct SPY1EVENT
{
    /** the type of event. */
    SPY1EVENTTYPE   enmType;
    /** The process in which we recorded the event. */
    ULONG           pid;
    /** The thread in which we recorded the event. */
    ULONG           tid;
    /** The hook type which recorded the event. */
    ULONG           ulHook;
    /** Type specific data. */
    union
    {
        /** A message. */
        QMSG        Msg;
        /* ... more ... */
    } u;
} SPY1EVENT, *PSPY1EVENT;


int EXPENTRY SetHooks(HAB hab);
int EXPENTRY ReleaseHooks(HAB hab);
int EXPENTRY GetEvent(PSPY1EVENT pEvent, ULONG ulTimeout);


/** @name The hook functions.
 * @{ */
BOOL EXPENTRY InputHook(HAB hab, PQMSG pQmsg, ULONG fs);
VOID EXPENTRY JournalRecordHook(HAB hab, PQMSG pQmsg);
/** @} */

#endif

