/*static char *SCCSID = "@(#)tklibi.h   6.3 91/12/15";*/
/*      static char *SCCSID = "@(#)tklibi.h     6.3 91/12/15"
 *
 *      IBM/Microsoft Confidential
 *
 *      Copyright (c) IBM Corporation 1987, 1989
 *      Copyright (c) Microsoft Corporation 1987, 1989
 *
 *      All Rights Reserved
 */

#define LIBI_HASINIT    0x0001  // Some MTE has a init routine to be run
#define LIBI_TOPBLOCK   0x0002  // Marks current block as 1st for this level
#define LIBI_LOADMODULE 0x0004  // Marks the top level block as a call from
                                // DOSLOADMODULE as against a DOSEXECPGM call
#define LIBI_DISPATCHED 0x0008  // Indicates that atleast one init routine has
                                // been dispatched
#define LIBI_FREEMODULE 0x0010  // If set then tkLibiFreeModule will do a
                                // LDRFreeModule on the first module at that
                                // level
#define MAXHDL          64      // Maximum # of MTE handles in this block

#define LIBI_STK_CHK    0x0020  // Indicates that the size of the stack has
                                // been validated.
                                // Only valid for the top block pointed
                                // to by TCBpLibiHead.  //p025236
#define LIBI_STK_ALLOC  0x0040  // This flag indicates if a stack has been
                                // allocated for library initialization.
                                // Only valid for the top block pointed
                                // to by TCBpLibiHead.  //p025236

/***LT+  LibInit block structure
 *
 *      These blocks are chained with its head in the threads TCB. When
 *      TKLibiRecordMTE is called for the first time following a DOSLOADMODULE
 *      or DOSEXECPGM the first of these is created and linked to the thread's
 *      TCB. Each of these blocks hold MAXHDL MTE handles and links to the
 *      immediately previous block.
 *      TKLibiStartDispatch dispatches in the reverse order.
 */

struct  libi_s
{
        char            libi_rcnt;              // count of handles in this
                                                // block not yet dispatched
        char            libi_tcnt;              // total count of modules in
                                                // this level
        UCHAR           libi_status;            // status flags
        char            libi_dbgcnt;            // count of handles passed
                                                // to Debug
        struct  libi_s  *libi_pprev;            // link to previous block at
                                                // the same level
        struct  libi_s  *libi_pnext;            // link to next block at
                                                // the same level
        struct  libi_s  *libi_pancs;            // link to immediate ancestor
        struct  libi_s  *libi_psibl;            // link to next sibling
        struct  kmreg_s *libi_pregs;            // Saved registers from pkstack
        PUCHAR          libi_objnamebuf;        // Copied from TCB
        USHORT          libi_objnamebufL;       // Copied from TCB
        VMHOB           libi_handles[MAXHDL];   // Stored MTE handles
        struct  libi_s  *libi_pdesc[MAXHDL];    // links to descendant blocks
        USHORT          libi_stackSel;          // Sel of temp stack  //p025236
};
typedef struct  libi_s  LIBI;
typedef struct  libi_s  *PLIBI;

/*end*/

#define IsTopBlock(plibi)       (plibi->libi_status & LIBI_TOPBLOCK)
#define HasInit(plibi)          (plibi->libi_status & LIBI_HASINIT)
#define IsDispatched(plibi)     (plibi->libi_status & LIBI_DISPATCHED)
#define IsFreeMod(plibi)        (plibi->libi_status & LIBI_FREEMODULE)
#define IsLoadMod(plibi)        (plibi->libi_status & LIBI_LOADMODULE)
#define StackChecked(plibi)     (plibi->libi_status & LIBI_STK_CHK)
#define StackAllocated(plibi)   (plibi->libi_status & LIBI_STK_ALLOC)

/***LT+  LibInit structure for module unload notification
 *
 *      This block is pointed to by the thread's TCB.  The size of
 *      a block varies with the number of notifications to perform.
 *      TKLibiNextDbgDLL dispatches in the reverse order.  Since
 *      the block is allocated before DLL termination is performed
 *      but not used until after it is performed, there may be
 *      nested levels of blocks.
 */

struct  libf_s {
        struct libf_s   *libf_pprev;
        USHORT          libf_count;
        VMHOB           libf_handles[1];
};

typedef struct  libf_s  LIBF;
typedef struct  libf_s  *PLIBF;

extern  int     tkLibiAddMTE(VMHOB, int);
extern  void    tkLibiFree(PTCB, int);
extern  void    tkLibiGlobalDone(PLIBI, int);
extern  void    tkGetLibiDispatcherAddr(void);
extern  void    tkLibiKillProc(ULONG);
extern  void    tkLibiFreeModules(PLIBI, int, int);
extern  void    tkLibiFreeHeap(PLIBI, int);
extern  int     tkLibiCheckReference(VMHOB, PLIBI);

extern  struct  FarPtr  LibiDispatcher;
extern  struct  FarPtr  LibiDispatcher16;
extern  ULONG           LibiDispatcher32;
