/********************************************************************/
/**                     Microsoft LAN Manager                      **/
/**               Copyright(c) Microsoft Corp., 1990-1992          **/
/********************************************************************/
/* :ts=4 */


//**    cxport.h - Common transport environment include file.
//
//  This file defines the structures and external declarations needed
//  to use the common transport environment.
//

//
// Typedefs used in this file
//
#ifndef CTE_TYPEDEFS_DEFINED
#define CTE_TYPEDEFS_DEFINED  1

typedef unsigned long ulong;
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned int uint;

#endif // CTE_TYPEDEFS_DEFINED


#ifdef VXD
//////////////////////////////////////////////////////////////////////////////
//
// Following are the VXD definitions
//
//////////////////////////////////////////////////////////////////////////////

/*NOINC*/
#ifndef i386
#define i386
#endif

#ifndef FAR
#define FAR
#endif

#define UNALIGNED

#define STRUCT_OF(s, a, f) (s *)((char *)(a) - offsetof(s, f))
/*INC*/

//
// BUGBUG: Yank this when ndis gets it right.
//
/*NOINC*/

//
// Macros to portably manipulate NDIS buffers.
//

#define NDIS_BUFFER_LINKAGE(Buf) (Buf)->Next
#define NdisAdjustBufferLength(Buf, Len)  (Buf)->Length = (Len)

#define NdisBufferLength(Buffer)  (Buffer)->Length
#define NdisBufferVirtualAddress(Buffer)  (Buffer)->VirtualAddress


/*INC*/


//* Initialization function.
//
// A routine to initialize the CTE. All users must call this during
// initialization, and must not attempt to call any other CTE functions
// if it fails.
//
// This routine returns 0 if it fails, non-0 if it succeeds.
extern int CTEInitialize(void);

//* Lock related definitions.
//
// In the VxD environment, locks correspond to disabling interrupts. There
// in no exact lock structure - the 'handle' returned by the locking routines
// is all the space needed.
//
// For debugging purposes we define a simple lock structure to keep
// track of lock collisions - this should hopefully make the port to NT
// easier.

#ifdef DEBUG

struct CTELock {
    int     l_count;        // The lock count.
    void    *l_owner;       // The owner of the lock.
}; /* CTELock */

typedef struct CTELock  CTELock;

/*NOINC*/
#define DEFINE_LOCK_STRUCTURE(x) CTELock    x;
#define LOCK_STRUCTURE_SIZE sizeof(CTELock)
#define EXTERNAL_LOCK(x)    extern CTELock x;
/*INC*/
#else

/*NOINC*/
// Macro for defining a lock structure.
#define DEFINE_LOCK_STRUCTURE(x)

// Lock structure size
#define LOCK_STRUCTURE_SIZE 0
#define EXTERNAL_LOCK(x)
/*INC*/

#endif // DEBUG

// Initialize lock macro. This macro must be used once before a lock
// can be used.
/*NOINC*/
#ifdef DEBUG
#define CTEInitLock(l) (l)->l_count = 0

#else
#define CTEInitLock(l)
#endif // DEBUG
/*INC*/

typedef unsigned    int *CTELockHandle;

// Get lock routine. This routine takes a lock address (unused), and
// a pointer to a handle. The handle is the only interesting thing here.
#ifdef DEBUG
extern void _ICTEGetLock(CTELock *, CTELockHandle *);   // The real lock routine.
/*NOINC*/
#define CTEGetLock(l,h) _ICTEGetLock((l),(h))
#define	DEFAULT_SIMIRQL	0
/*INC*/

#else

/*NOINC*/
#define CTEGetLock(l, h)
/*INC*/
#endif // DEBUG

/*NOINC*/
#define CTEGetLockAtDPC(l, h) CTEGetLock((l),(h))
#define CTEFreeLockFromDPC(l, h) CTEFreeLock((l), (h))
/*INC*/

// Free lock routine. This routine takes a lock (unused) and a handle and
// frees the lock.
#ifdef DEBUG
extern void _ICTEFreeLock(CTELock *, CTELockHandle);
/*NOINC*/
#define CTEFreeLock(l, h) _ICTEFreeLock((l),(h))
/*INC*/

#else
/*NOINC*/
#define CTEFreeLock(l, h)
/*INC*/
#endif

// Multiprocessor safe counter management routines. In the VXD environment,
// these routines do not actually use any locks.
//

/*NOINC*/
#define RESULT_ZERO     1
#define RESULT_POSITIVE 0
#define RESULT_NEGATIVE 2

typedef enum CTE_INTERLOCKED_RESULT {
    ResultZero = RESULT_ZERO,
    ResultPositive = RESULT_POSITIVE,
    ResultNegative = RESULT_NEGATIVE
} CTEInterlockedResult;

// Adds an increment to a ULong. The increment may be negative. Returns the
// original value of the addend.
//
#define CTEInterlockedAddUlong(AddendPtr, Increment, LockPtr) \
    (*(AddendPtr)); { *(AddendPtr) += (Increment); }

// Decrements a long Addend. Returns an INTERLOCKED_RESULT value denoting
// the post-decrement state of the addend.
//
#define CTEInterlockedDecrementLong(AddendPtr, LockPtr) \
    (((--(*(AddendPtr)) <= 0) ? 1 : 0) +        \
        ( (*(AddendPtr) < 0) ? 1 : 0 ))

// Increments a long Addend. Returns an INTERLOCKED_RESULT value denoting
// the post-increment state of the addend.
//
#define CTEInterlockedIncrementLong(AddendPtr, LockPtr) \
    (((++(*(AddendPtr)) <= 0) ? 1 : 0) +        \
        ( (*(AddendPtr) < 0) ? 1 : 0 ))

/*INC*/

//* VxD defintions of a CTEULargeInt
struct CTEULargeInt {
    ulong       LowPart;
    ulong       HighPart;
}; /* CTEULargeInt */

typedef struct  CTEULargeInt    CTEULargeInt;

/*NOINC*/

__inline ulong
CTEEnlargedUnsignedDivide (
    CTEULargeInt Dividend,
    ulong Divisor,
    ulong *Remainder
    )
{
    _asm {
        mov     eax, Dividend.LowPart
        mov     edx, Dividend.HighPart
        mov     ecx, Remainder
        div     Divisor             ; eax = eax:edx / divisor
        or      ecx, ecx            ; save remainer?
        jz      short done
        mov     [ecx], edx
done:
    }
}

/*INC*/

//* Delayed event definitions
//
// Delayed events are events scheduled that can be scheduled to
// occur 'later', without a timeout. They happen as soon as the system
// is ready for them. The caller specifies a parameter that will be
// passed to the event proc when the event is called.
//
typedef void (*CTEEventRtn)(struct CTEEvent *, void *);

struct CTEEvent {
	struct CTEEvent *ce_next;	// Linkage field.
    CTEEventRtn ce_event;       // Procedure to be called.
    void        *ce_param;      // Parameter to be passed to event proc.
    void        *ce_ehandle;    // VMM event handle;
}; /* CTEEvent */

typedef struct CTEEvent CTEEvent;

// Macro to initialize an event. This macro must be used once on each event.
/*NOINC*/
#define CTEInitEvent(e,p)   (e)->ce_ehandle = (void *)0;\
                            (e)->ce_event = (p)
/*INC*/
// Routine to schedule an event.
extern int CTEScheduleEvent(CTEEvent *, void *);

// Routine to cancel an event.
extern int CTECancelEvent(CTEEvent *);

//* Timer related declarations
//

//  Each timer requires a structure of type CTETimer.
//


//  CTETimer definitions for a VxD environment.
//
// Note: It is IMPORTANT that t_event be the first thing in the CTETimer
// structure. Don't change this without looking at vtdirtns.asm.
struct  CTETimer {
    struct  CTEEvent t_event;   // Event structure to be called when TO happens.
    void    *t_thandle;         // VMM timer handle. 0 if no timer running
}; /* CTETimer */

typedef struct CTETimer CTETimer;

/*NOINC*/
// Macro to initialize a timer. This macro must be used once on
// every timer. It must not be invoked on a running timer.
#define CTEInitTimer(t) (t)->t_thandle = (t)->t_event.ce_ehandle = (void *)0

// Start timer routine. CTEStartTimer takes a pointer to a timer structure,
// a time (in milliseconds) for the timer, the time out routine to be
// called upon expiration, and a context value to be passed to the time out
// routine.
extern void * CTEStartTimer(CTETimer *, unsigned long, CTEEventRtn, void *);

// Stop timer routine. This routine stops a timer. It may be called on
// a timer that is already stopped - doing so has no effect. This function
// returns non-zero if the timer was succesfully stopped, 0 if it couldn't
// be stopped or wasn't running.
extern int CTEStopTimer(CTETimer *);

// System up time routine. This routine returns the time in milliseconds
// that the system has been up.
extern unsigned long CTESystemUpTime(void);
/*INC*/

//* Memory allocation functions.
//
// There are only two main functions, CTEAllocMem and CTEFreeMem. Locks
// should not be held while calling these functions, and it is possible
// that they may yield when called, particularly in the VxD environment.
//
//  In the VxD environment there is a third auxillary function CTERefillMem,
//  used to refill the VxD heap manager.

// Routine to allocate memory.
extern void *CTEAllocMem(unsigned int);

// Routine to free memory.
extern void *CTEFreeMem(void *);

// Routine to Refill memory.
extern void CTERefillMem(void);


//
//* String definitions and manipulation routines
//
//

//
// Converts a C style ASCII string to an NDIS_STRING. Resources needed for
// the NDIS_STRING are allocated and must be freed by a call to
// CTEFreeString. Returns TRUE if initialization succeeded. FALSE otherwise.
//
/*NOINC*/
#define CTEInitString(D, S) \
        ( (CTEAllocateString((D), strlen((S)) + 1) == TRUE) ?   \
          ((D)->Length = (D)->MaximumLength, strcpy((D)->Buffer, (S)), TRUE) : \
          FALSE)

//
// Allocates a data buffer for Length characters in an uninitialized
// NDIS_STRING. The allocated space must be freed by a call to CTEFreeString.
// Returns TRUE if it succeeds. FALSE otherwise.
//
#define CTEAllocateString(S, L) \
        ( (((S)->Buffer = CTEAllocMem(L)) != NULL) ?           \
        ((S)->Length = 0, (S)->MaximumLength = (L), TRUE) :      \
          FALSE)

//
// Routine to free the string buffer associated with an NDIS_STRING. The
// buffer must have been allocated by a previous call to CTEInitString.
// Returns nothing.
//
#define CTEFreeString(String) CTEFreeMem((String)->Buffer)


//
// Calculates and returns the length of an NDIS_STRING in bytes.
//
#define CTELengthString(String) ((String)->Length)


//
// Compares two NDIS_STRING variables for case-sensitive equality
// Returns TRUE if the strings are equivalent. FALSE otherwise.
//
#define CTEEqualString(S1, S2) \
            ((strcmp((S1)->Buffer, (S2)->Buffer) == 0) ? TRUE : FALSE)


//
//     Copies one NDIS_STRING to another. Behavior is undefined if the
//     destination is not long enough to hold the source. Returns nothing.
//
#define CTECopyString(D, S)  (void) strcpy((D)->Buffer, (S)->Buffer); \
            (D)->Length = (S)->Length

/*INC*/

//* Buffer descriptor manipulation routines.
//
//  These definitions describe the format of a buffer descriptor.
//  Macros are provided to query the size and pointer values of a
//  buffer desc.
//
//  Note that for the VxD implementation this must be kept in sync.
//  with NDIS.H
//
struct CTEBufDesc {
    struct CTEBufDesc   *cbd_next;      // Next in chain.
    void                *cbd_data;      // Pointer to buffer.
    uint                cbd_size;       // Size in bytes of buffer.
}; /* CTEBufDesc */

typedef struct CTEBufDesc   CTEBufDesc;

/*NOINC*/
#define CTE_BDBUFFER(b) (b)->cbd_data
#define CTE_BDSIZE(b)   (b)->cbd_size
#define CTE_BDNEXT(b)   (b)->cbd_next
#define CTE_EOL         ((CTEBufDesc *)NULL)
/*INC*/


//* Memory manipulation routines.
//
/*NOINC*/
#define CTEMemCopy(d,s,l)   memcpy((d),(s),(l))
#define CTEMemSet(d, v, l)  memset((d), (v), (l))
#define CTEMemCmp(d, s, l)  memcmp((d), (s), (l))
/*INC*/


//* Blocking routines. These routines allow a limited blocking capability. Using
//  them requires care, and they probably shouldn't be used outside of initialization time.
struct CTEBlockStruc {
    uint        cbs_status;
    uint        cbs_flag;
}; /* CTEBlockStruc */

typedef struct CTEBlockStruc CTEBlockStruc;

/*NOINC*/
#define CTEInitBlockStruc(x)    (x)->cbs_status = NDIS_STATUS_SUCCESS;(x)->cbs_flag = 0;

extern uint CTEBlock(CTEBlockStruc *);
extern void CTESignal(CTEBlockStruc *, uint);
/*INC*/

/*NOINC*/
// Debugging routines.

#ifdef DEBUG

#ifdef VXD

#define DEBUGCHK    _asm int 3
#define DEBUGSTRING(v, s) uchar v[] = s
extern void _CTECheckMem(uint, char *, uint);
#define CTECheckMem(s)  _CTECheckMem(0, s, __LINE__)

extern void CTEPrint(char *);
extern void CTEPrintNum(int);
extern void CTEPrintCRLF(void);

#define CTEStructAssert(s, t) if ((s)->t##_sig != t##_signature) {\
                CTEPrint("Structure assertion failure for type " #t " in file " __FILE__ " line ");\
                CTEPrintNum(__LINE__);\
                CTEPrintCRLF();\
                DEBUGCHK\
                }

#define CTEAssert(c)    if (!(c)) {\
                CTEPrint("Assertion failure in file " __FILE__ " line ");\
                CTEPrintNum(__LINE__);\
                CTEPrintCRLF();\
                DEBUGCHK\
                }
#else // VXD

#define DEBUGCHK
#define DEBUGSTRING(v,s)
#define CTECheckMem(s)
#define CTEStructAssert(s,t )
#define CTEAssert(c)
#define CTEPrint(s)

#endif // VXD

#else   // DEBUG

#define DEBUGCHK
#define DEBUGSTRING(v,s)
#define CTECheckMem(s)
#define CTEStructAssert(s,t )
#define CTEAssert(c)
#define CTEPrint(s)

#endif // DEBUG

//* Request completion routine definition.
typedef void    (*CTEReqCmpltRtn)(void *, uint , uint);

/*INC*/

#else // VXD

/*NOINC*/

#ifdef NT
//////////////////////////////////////////////////////////////////////////////
//
// Following are the NT environment definitions
//
//////////////////////////////////////////////////////////////////////////////

#include <updriver.h>

#ifndef FAR
#define FAR
#endif

//
// Structure manipulation macros
//
#define offsetof(type, field) FIELD_OFFSET(type, field)
#define STRUCT_OF(type, address, field) CONTAINING_RECORD(address, type, field)

//
// Macros to portably manipulate NDIS buffers.
//
#define NdisBufferLength(Buffer)  MmGetMdlByteCount(Buffer)
#define NdisBufferVirtualAddress(Buffer)  MmGetSystemAddressForMdl(Buffer)


//
//* CTE Initialization.
//

//++
//
// int
// CTEInitialize(
//     void
//     );
//
// Routine Description:
//
//     Initializes the Common Transport Environment. All users of the CTE
//     must call this routine during initialization before calling any
//     other CTE routines.
//
// Arguments:
//
//     None.
//
// Return Value:
//
//     Returns zero on failure, non-zero if it succeeds.
//
//--

extern int
CTEInitialize(
    void
    );


//
//* Lock related definitions.
//
typedef KSPIN_LOCK  CTELock;
typedef KIRQL       CTELockHandle;

#define DEFINE_LOCK_STRUCTURE(x)    CTELock x;
#define LOCK_STRUCTURE_SIZE         sizeof(CTELock)
#define EXTERNAL_LOCK(x)            extern CTELock x;

//++
//
// VOID
// CTEInitLock(
//     CTELOCK *SpinLock
//     );
//
// Routine Description:
//
//     Initializes a spin lock.
//
// Arguments:
//
//     SpinLock - Supplies a pointer to the lock structure.
//
// Return Value:
//
//     None.
//
//--

#define CTEInitLock(l) KeInitializeSpinLock(l)


//++
//
// VOID
// CTEGetLock(
//     CTELock        *SpinLock,
//     CTELockHandle  *OldIrqlLevel
//     );
//
// Routine Description:
//
//     Acquires a spin lock
//
// Arguments:
//
//     SpinLock     - A pointer to the lock structure.
//     OldIrqlLevel - A pointer to a variable to receive the old IRQL level .
//
// Return Value:
//
//     None.
//
//--

#define CTEGetLock(l, h) KeAcquireSpinLock((l),(h))


//++
//
// VOID
// CTEGetLockAtDPC(
//     CTELock        *SpinLock,
//     CTELockHandle  *OldIrqlLevel
//     );
//
// Routine Description:
//
//     Acquires a spin lock when the processor is already running at
//     DISPATCH_LEVEL.
//
// Arguments:
//
//     SpinLock     - A pointer to the lock structure.
//     OldIrqlLevel - A pointer to a variable to receive the old IRQL level .
//                    This parameter is not used in the NT version.
//
// Return Value:
//
//     None.
//
//--

#define CTEGetLockAtDPC(l, h) KeAcquireSpinLockAtDpcLevel((l))


//++
//
// VOID
// CTEFreeLock(
//     CTELock        *SpinLock,
//     CTELockHandle   OldIrqlLevel
//     );
//
// Routine Description:
//
//     Releases a spin lock
//
// Arguments:
//
//     SpinLock     - A pointer to the lock variable.
//     OldIrqlLevel - The IRQL level to restore.
//
// Return Value:
//
//     None.
//
//--

#define CTEFreeLock(l, h) KeReleaseSpinLock((l),(h))


//++
//
// VOID
// CTEFreeLockFromDPC(
//     CTELock        *SpinLock,
//     CTELockHandle   OldIrqlLevel
//     );
//
// Routine Description:
//
//     Releases a spin lock
//
// Arguments:
//
//     SpinLock     - A pointer to the lock variable.
//     OldIrqlLevel - The IRQL level to restore. This parameter is ignored
//                    in the NT version.
//
// Return Value:
//
//     None.
//
//--

#define CTEFreeLockFromDPC(l, h) KeReleaseSpinLockFromDpcLevel((l))


//
// Interlocked counter management routines.
//
typedef INTERLOCKED_RESULT CTEInterlockedResult;


//++
//
// ulong
// CTEInterlockedAddUlong(
//     ulong     *AddendPtr,
//     ulong      Increment,
//     CTELock   *LockPtr
//     );
//
// Routine Description:
//
//     Adds an increment to an unsigned long quantity using a spinlock
//     for synchronization.
//
// Arguments:
//
//     AddendPtr  - A pointer to the quantity to be updated.
//     LockPtr    - A pointer to the spinlock used to synchronize the operation.
//
// Return Value:
//
//     The initial value of the Added variable.
//
// Notes:
//
//     It is not permissible to mix calls to CTEInterlockedAddULong with
//     calls to the CTEInterlockedIncrement/DecrementLong routines on the
//     same value.
//
//--

#define CTEInterlockedAddUlong(AddendPtr, Increment, LockPtr) \
            ExInterlockedAddUlong(AddendPtr, Increment, LockPtr)


//++
//
// CTEInterlockedResult
// CTEInterlockedDecrementLong(
//     ulong     *AddendPtr,
//     CTELock   *LockPtr
//     );
//
// Routine Description:
//
//     Decrements a long quantity using a spinlock for synchronization.
//
// Arguments:
//
//     AddendPtr  - A pointer to the quantity to be updated.
//     Increment  - The value to be added to addend.
//     LockPtr    - A pointer to the spinlock used to synchronize the operation.
//
// Return Value:
//
//     ResultNegative if Addend is < 0 after decrement.
//     ResultZero     if Addend is = 0 after decrement.
//     ResultPositive if Addend is > 0 after decrement.
//
// Notes:
//
//     It is not permissible to mix calls to CTEInterlockedAddULong with
//     calls to the CTEInterlockedIncrement/DecrementLong routines on the
//     same value.
//
//--

#define CTEInterlockedDecrementLong(AddendPtr, LockPtr) \
            ExInterlockedDecrementLong(AddendPtr, LockPtr)

//++
//
// CTEInterlockedResult
// CTEInterlockedIncrementLong(
//     ulong     *AddendPtr,
//     CTELock   *LockPtr
//     );
//
// Routine Description:
//
//     Increments a long quantity using a spinlock for synchronization.
//
// Arguments:
//
//     AddendPtr  - A pointer to the quantity to be incremented.
//     LockPtr    - A pointer to the spinlock used to synchronize the operation.
//
// Return Value:
//
//     ResultNegative if Addend is < 0 after increment.
//     ResultZero     if Addend is = 0 after increment.
//     ResultPositive if Addend is > 0 after increment.
//
// Notes:
//
//     It is not permissible to mix calls to CTEInterlockedAddULong with
//     calls to the CTEInterlockedIncrement/DecrementLong routines on the
//     same value.
//
//--

#define CTEInterlockedIncrementLong(AddendPtr, LockPtr) \
            ExInterlockedIncrementLong(AddendPtr, LockPtr)


//
// Large Integer manipulation routines.
//

typedef ULARGE_INTEGER CTEULargeInt;

//++
//
// ulong
// CTEEnlargedUnsignedDivide(
//     CTEULargeInt  Dividend,
//     ulong         Divisor,
//     ulong        *Remainder
//     );
//
// Routine Description:
//
//     Divides an unsigned large integer quantity by an unsigned long quantity
//     to yield an unsigned long quotient and an unsigned long remainder.
//
// Arguments:
//
//     Dividend   - The dividend value.
//     Divisor    - The divisor value.
//     Remainder  - A pointer to a variable to receive the remainder.
//
// Return Value:
//
//     The unsigned long quotient of the division.
//
//--

#define CTEEnlargedUnsignedDivide(Dividend, Divisor, Remainder) \
    RtlEnlargedUnsignedDivide (Dividend, Divisor, Remainder)


//
//* String definitions and manipulation routines
//
//

//++
//
// BOOLEAN
// CTEInitString(
//     PNDIS_STRING   DestinationString,
//     char          *SourceString
//     );
//
// Routine Description:
//
//     Converts a C style ASCII string to an NDIS_STRING. Resources needed for
//     the NDIS_STRING are allocated and must be freed by a call to
//     CTEFreeString.
//
// Arguments:
//
//     DestinationString  - A pointer to an NDIS_STRING variable with no
//                          associated data buffer.
//
//     SourceString       - The C style ASCII string source.
//
//
// Return Value:
//
//     TRUE if the initialization succeeded. FALSE otherwise.
//
//--

BOOLEAN
CTEInitString(
    PUNICODE_STRING  DestinationString,
    char            *SourceString
    );


//++
//
// BOOLEAN
// CTEAllocateString(
//     PNDIS_STRING    String,
//     unsigned short  Length
//     );
//
// Routine Description:
//
//     Allocates a data buffer for Length characters in an uninitialized
//     NDIS_STRING. The allocated space must be freed by a call to
//     CTEFreeString.
//
//
// Arguments:
//
//     String         - A pointer to an NDIS_STRING variable with no
//                          associated data buffer.
//
//     MaximumLength  - The maximum length of the string. The unit of this
//                          value is system dependent.
//
// Return Value:
//
//     TRUE if the initialization succeeded. FALSE otherwise.
//
//--

BOOLEAN
CTEAllocateString(
    PUNICODE_STRING     String,
    unsigned short      Length
    );


//++
//
// VOID
// CTEFreeString(
//     PNDIS_STRING  String,
//     );
//
// Routine Description:
//
//     Frees the string buffer associated with an NDIS_STRING. The buffer must
//     have been allocated by a previous call to CTEInitString.
//
// Arguments:
//
//     String - A pointer to an NDIS_STRING variable.
//
//
// Return Value:
//
//     None.
//
//--

#define CTEFreeString(String) ExFreePool((String)->Buffer)


//++
//
// unsigned short
// CTELengthString(
//     PNDIS_STRING String
//     );
//
// Routine Description:
//
//     Calculates the length of an NDIS_STRING.
//
// Arguments:
//
//     The string to test.
//
// Return Value:
//
//     The length of the string parameter. The unit of this value is
//         system dependent.
//
//--

#define CTELengthString(String) ((String)->Length)


//++
//
// BOOLEAN
// CTEEqualString(
//     CTEString *String1,
//     CTEString *String2
//     );
//
// Routine Description:
//
//     Compares two NDIS_STRINGs for case-sensitive equality
//
// Arguments:
//
//     String1 - A pointer to the first string to compare.
//     String2 - A pointer to the second string to compare.
//
// Return Value:
//
//     TRUE if the strings are equivalent. FALSE otherwise.
//
//--

#define CTEEqualString(S1, S2) RtlEqualUnicodeString(S1, S2, FALSE)


//++
//
// VOID
// CTECopyString(
//     CTEString *DestinationString,
//     CTEString *SourceString
//     );
//
// Routine Description:
//
//     Copies one NDIS_STRING to another. Behavior is undefined if the
//     destination is not long enough to hold the source.
//
// Arguments:
//
//     DestinationString - A pointer to the destination string.
//     SourceString      - A pointer to the source string.
//
// Return Value:
//
//     None.
//
//--

#define CTECopyString(D, S) RtlCopyUnicodeString(D, S)


//
//* Delayed event definitions
//
// Delayed events are events scheduled that can be scheduled to
// occur 'later', without a timeout. They happen as soon as the system
// is ready for them. The caller specifies a parameter that will be
// passed to the event proc when the event is called.
//
// In the NT environmnet, delayed events are implemented using Executive
// worker threads.
//
// NOTE: The event handler routine may not block.
//

typedef void (*CTEEventRtn)(struct CTEEvent *, void *);

struct CTEEvent {
    uint             ce_scheduled;
    CTELock          ce_lock;
    CTEEventRtn      ce_handler;     // Procedure to be called.
    void            *ce_arg;         // Argument to pass to handler.
    WORK_QUEUE_ITEM  ce_workitem;    // Kernel ExWorkerThread queue item.
}; /* CTEEvent */

typedef struct CTEEvent CTEEvent;


//++
//
// void
// CTEInitEvent(
//     IN CTEEvent     *Event,
//     IN CTEEventRtn  *Handler
//     );
//
// Routine Description:
//
//    Initializes a delayed event structure.
//
// Arguments:
//
//    Event    - Pointer to a CTE Event variable
//    Handler  - Pointer to the function to be called when the event is
//                 scheduled.
//
// Return Value:
//
//    None.
//
//--

extern void
CTEInitEvent(
    IN CTEEvent    *Event,
    IN CTEEventRtn  Handler
    );


//++
//
// int
// CTEScheduleEvent(
//     IN CTEEvent    *Event,
//     IN void        *Argument
//     );
//
// Routine Description:
//
//    Schedules a routine to be executed later in a different context. In the
//    NT environment, the event is implemented as a kernel DPC.
//
// Arguments:
//
//    Event    - Pointer to a CTE Event variable
//    Argument - An argument to pass to the event handler when it is called
//
// Return Value:
//
//    0 if the event could not be scheduled. Nonzero otherwise.
//
//--

int
CTEScheduleEvent(
    IN CTEEvent    *Event,
    IN void        *Argument  OPTIONAL
    );


//++
//
// int
// CTECancelEvent(
//     IN CTEEvent *Event
//     );
//
// Routine Description:
//
//     Cancels a previously scheduled delayed event routine.
//
// Arguments:
//
//     Event - Pointer to a CTE Event variable
//
// Return Value:
//
//     0 if the event couldn't be cancelled. Nonzero otherwise.
//
// Notes:
//
//     In the NT environment, a delayed event cannot be cancelled.
//
//--

#define CTECancelEvent(Event)   0


//
//* Timer related declarations
//

struct  CTETimer {
    uint             t_running;
    CTELock          t_lock;
    CTEEventRtn      t_handler;
    void            *t_arg;
    KDPC             t_dpc;     // DPC for this timer.
    KTIMER           t_timer;   // Kernel timer structure.
}; /* CTETimer */

typedef struct CTETimer CTETimer;

//++
//
// void
// CTEInitTimer(
//     IN CTETimer *Timer
//     );
//
// Routine Description:
//
//     Initializes a CTE Timer structure. This routine must be used
//     once on every timer before it is set. It may not be invoked on
//     a running timer.
//
// Arguments:
//
//     Timer - Pointer to the CTE Timer to be initialized.
//
// Return Value:
//
//     0 if the timer could not be initialized. Nonzero otherwise.
//
//--

extern void
CTEInitTimer(
    IN CTETimer *Timer
    );


//++
//
// extern void *
// CTEStartTimer(
//     IN CTETimer *Timer
//     );
//
// Routine Description:
//
//     This routine starts a CTE timer running.
//
// Arguments:
//
//     Timer      - Pointer to the CTE Timer to start.
//     DueTime    - The time in milliseconds from the present at which the
//                    timer will be due.
//     Handler    - The function to call when the timer expires.
//     Context    - A value to pass to the Handler routine.
//
// Return Value:
//
//     NULL if the timer could not be started. Non-NULL otherwise.
//
// Notes:
//
//     In the NT environment, the first argument to the Handler function is
//     a pointer to the timer structure, not to a CTEEvent structure.
//
//--

extern void *
CTEStartTimer(
    IN CTETimer       *Timer,
    IN unsigned long   DueTime,
    IN CTEEventRtn     Handler,
    IN void           *Context   OPTIONAL
    );


//++
//
// int
// CTEStopTimer(
//     IN CTETimer *Timer
//     );
//
// Routine Description:
//
//     Cancels a running CTE timer.
//
// Arguments:
//
//     Timer - Pointer to the CTE Timer to be cancelled.
//
// Return Value:
//
//     0 if the timer could not be cancelled. Nonzero otherwise.
//
// Notes:
//
//     Calling this function on a timer that is not active has no effect.
//     If this routine fails, the timer may be in the process of expiring
//     or may have already expired. In either case, the caller must
//     sychronize with the Handler function as appropriate.
//
//--

#define CTEStopTimer(Timer)  ((int) KeCancelTimer(&((Timer)->t_timer)))


//++
//
// unsigned long
// CTESystemUpTime(
//     void
//     );
//
// Routine Description:
//
//     Returns the time in milliseconds that the system has been running.
//
// Arguments:
//
//     None.
//
// Return Value:
//
//     The time in milliseconds.
//
//--

extern unsigned long
CTESystemUpTime(
    void
    );


//
//* Memory allocation functions.
//
// There are only two main functions, CTEAllocMem and CTEFreeMem. Locks
// should not be held while calling these functions, and it is possible
// that they may yield when called, particularly in the VxD environment.
//
//  In the VxD environment there is a third auxillary function CTERefillMem,
//  used to refill the VxD heap manager.
//

//++
//
// void *
// CTEAllocMem(
//     ulong Size
//     );
//
// Routine Description:
//
//     Allocates a block of memory from nonpaged pool.
//
// Arguments:
//
//     Size   -  The size in bytes to allocate.
//
// Return Value:
//
//     A pointer to the allocated block, or NULL.
//
//--

#define CTEAllocMem(Size)  ExAllocatePool(NonPagedPool, (Size))


//++
//
// void
// CTEFreeMem(
//     void *MemoryPtr
//     );
//
// Routine Description:
//
//     Frees a block of memory allocated with CTEAllocMem.
//
// Arguments:
//
//     MemoryPtr   - A pointer to the memory to be freed.
//
// Return Value:
//
//     None.
//
//--

#define CTEFreeMem(MemoryPtr)   ExFreePool((MemoryPtr));


// Routine to Refill memory. Not used in NT environment.
#define CTERefillMem()


//
//* Memory manipulation routines.
//

//++
//
// void
// CTEMemCopy(
//     void          *Source,
//     void          *Destination,
//     unsigned long  Length
//     );
//
// RoutineDescription:
//
//     Copies data from one buffer to another.
//
// Arguments:
//
//     Source       - Source buffer.
//     Destination  - Destination buffer,
//     Length       - Number of bytes to copy.
//
// Return Value:
//
//     None.
//
//--

#define CTEMemCopy(Dst, Src, Len)   RtlCopyMemory((Dst), (Src), (Len))


//++
//
// void
// CTEMemSet(
//     void          *Destination,
//     unsigned char *Fill
//     unsigned long  Length
//     );
//
// RoutineDescription:
//
//     Sets the bytes of the destination buffer to a specific value.
//
// Arguments:
//
//     Destination  - Buffer to fill.
//     Fill         - Value with which to fill buffer.
//     Length       - Number of bytes of buffer to fill.
//
// Return Value:
//
//     None.
//
//--

#define CTEMemSet(Dst, Fill, Len)   RtlFillMemory((Dst), (Len), (Fill))


//++
//
// unsigned long
// CTEMemCmp(
//     void          *Source1,
//     void          *Source2,
//     unsigned long  Length
//     );
//
// RoutineDescription:
//
//     Compares Length bytes of Source1 to Source2 for equality.
//
// Arguments:
//
//     Source1   - First source buffer.
//     Source2   - Second source buffer,
//     Length    - Number of bytes of Source1 to compare against Source2.
//
// Return Value:
//
//     Zero if the data in the two buffers are equal for Length bytes.
//     NonZero otherwise.
//
//--

#define CTEMemCmp(Src1, Src2, Len)    \
            ((RtlCompareMemory((Src1), (Src2), (Len)) == (Len)) ? 0 : 1)


//
//* Blocking routines. These routines allow a limited blocking capability.
//  Using them requires care, and they probably shouldn't be used outside
//  of initialization time.
//

struct CTEBlockStruc {
    uint        cbs_status;
    KEVENT      cbs_event;
}; /* CTEBlockStruc */

typedef struct CTEBlockStruc CTEBlockStruc;


//++
//
// VOID
// CTEInitBlockStruc(
//     IN CTEBlockStruc *BlockEvent
//     );
//
// Routine Description:
//
//     Initializes a CTE blocking structure
//
// Arguments:
//
//     BlockEvent - Pointer to the variable to intialize.
//
// Return Value:
//
//     None.
//
//--

#define CTEInitBlockStruc(Event) \
            {                                                        \
            (Event)->cbs_status = NDIS_STATUS_SUCCESS;               \
            KeInitializeEvent(                                       \
                &((Event)->cbs_event),                               \
                SynchronizationEvent,                                \
                FALSE                                                \
                );                                                   \
            }


//++
//
// uint
// CTEBlock(
//     IN CTEBlockStruc *BlockEvent
//     );
//
// Routine Description:
//
//     Blocks the current thread of execution on the occurrence of an event.
//
// Arguments:
//
//     BlockEvent - Pointer to the event on which to block.
//
// Return Value:
//
//     The status value provided by the signaller of the event.
//
//--

extern uint
CTEBlock(
    IN CTEBlockStruc *BlockEvent
    );


//++
//
// VOID
// CTESignal(
//     IN CTEBlockStruc *BlockEvent,
//     IN uint           Status
//     );
//
// Routine Description:
//
//     Releases one thread of execution blocking on an event. Any other
//     threads blocked on the event remain blocked.
//
// Arguments:
//
//     BlockEvent - Pointer to the event to signal.
//     Status     - Status to return to the blocking thread.
//
// Return Value:
//
//     None.
//
//--

extern void
CTESignal(
    IN CTEBlockStruc *BlockEvent,
    IN uint Status
    );


//
// Event Logging routines.
//
// NOTE: These definitions are tentative and subject to change!!!!!!
//

#define CTE_MAX_EVENT_LOG_DATA_SIZE                                       \
            ( ( ERROR_LOG_MAXIMUM_SIZE - sizeof(IO_ERROR_LOG_PACKET) +    \
                sizeof(ULONG)                                             \
              ) & 0xFFFFFFFC                                              \
            )

//
//
// Routine Description:
//
//     This function allocates an I/O error log record, fills it in and
//     writes it to the I/O error log.
//
//
// Arguments:
//
//     LoggerId          - Pointer to the driver object logging this event.
//
//     EventCode         - Identifies the error message.
//
//     UniqueEventValue  - Identifies this instance of a given error message.
//
//     NumStrings        - Number of unicode strings in strings list.
//
//     DataSize          - Number of bytes of data.
//
//     Strings           - Array of pointers to unicode strings (PWCHAR').
//
//     Data              - Binary dump data for this message, each piece being
//                         aligned on word boundaries.
//
// Return Value:
//
//     TDI_SUCCESS                  - The error was successfully logged.
//     TDI_BUFFER_TOO_SMALL         - The error data was too large to be logged.
//     TDI_NO_RESOURCES             - Unable to allocate memory.
//
// Notes:
//
//     This code is paged and may not be called at raised IRQL.
//
LONG
CTELogEvent(
    IN PVOID             LoggerId,
    IN ULONG             EventCode,
    IN ULONG             UniqueEventValue,
    IN USHORT            NumStrings,
    IN PVOID             StringsList,        OPTIONAL
    IN ULONG             DataSize,
    IN PVOID             Data                OPTIONAL
    );


//
// Debugging routines.
//
#if DBG
#define DEBUG 1
#endif //DBG


#ifdef DEBUG

#define DEBUGCHK    DbgBreakPoint()

#define DEBUGSTRING(v, s) uchar v[] = s

// extern void _CTECheckMem(uint, char *, uint);
// #define CTECheckMem(s)  _CTECheckMem(0, s, __LINE__)
#define CTECheckMem(s)

#define CTEPrint(String)   DbgPrint(String)
#define CTEPrintNum(Num)   DbgPrint("%d", Num)
#define CTEPrintCRLF()     DbgPrint("\n");


#define CTEStructAssert(s, t) if ((s)->t##_sig != t##_signature) {\
                CTEPrint("Structure assertion failure for type " #t " in file " __FILE__ " line ");\
                CTEPrintNum(__LINE__);\
                CTEPrintCRLF();\
                DEBUGCHK;\
                }

#define CTEAssert(c)    if (!(c)) {\
                CTEPrint("Assertion failure in file " __FILE__ " line ");\
                CTEPrintNum(__LINE__);\
                CTEPrintCRLF();\
                DEBUGCHK;\
                }

#else // DEBUG

#define DEBUGCHK
#define DEBUGSTRING(v,s)
#define CTECheckMem(s)
#define CTEStructAssert(s,t )
#define CTEAssert(c)
#define CTEPrint(s)
#define CTEPrintNum(Num)
#define CTEPrintCRLF()

#endif // DEBUG


//* Request completion routine definition.
typedef void    (*CTEReqCmpltRtn)(void *, unsigned int , unsigned int);


#else // NT

/////////////////////////////////////////////////////////////////////////////
//
// Definitions for additional environments go here
//
/////////////////////////////////////////////////////////////////////////////

#error Environment specific definitions missing

#endif // NT
/*INC*/
#endif // VXD
