windows-nt/Source/XPSP1/NT/base/mvdm/meinc/object.h
2020-09-26 16:20:57 +08:00

949 lines
36 KiB
C

/************************************************************************/
/* */
/* OBJECT.H -- General Object Manager Definitions */
/* */
/************************************************************************/
/* Author: Gene Apperson */
/* Copyright: 1991 Microsoft */
/************************************************************************/
/* File Description: */
/* */
/* */
/************************************************************************/
/* Revision History: */
/* */
/* */
/************************************************************************/
// This file may have been implicitly included if the client included KERNEL32.H
// If so, we don't need to define and declare everything again. We match this
// directive at the bottom of the file.
#ifndef typObjAny
/* ------------------------------------------------------------ */
/* Object Type Codes */
/* ------------------------------------------------------------ */
#define typObjSemaphore 1
#define typObjEvent 2
#define typObjMutex 3
#define typObjCrst 4
#define typObjTimer 5
#define typObjProcess 6
#define typObjThread 7
#define typObjFile 8
#define typObjChange 9
#define typObjConsole 10
#define typObjIO 11
#define typObjConScreenbuf 12
#define typObjMapFile 13
#define typObjSerial 14
#define typObjDevIOCtl 15
#define typObjPipe 16
#define typObjMailslot 17
#define typObjToolhelp 18
#define typObjSocket 19
#define typObjR0ObjExt 20
#define typObjMsgIndicator 21
#ifdef WOW32_EXTENSIONS
#define typObjTDBX 22
#endif
#define typObjAny 0xffffffff
#define typObjNone 0
// to let us determine what type of object were dealing with in a
// wait condition
#define typObjFirstSync typObjSemaphore
#define typObjLastSync typObjTimer
#define typObjFirstWait typObjProcess
#define typObjLastWait typObjIO
#define typObjMaxValid typObjMsgIndicator
#define typObjShiftAdjust (-1)
/* ------------------------------------------------------------ */
/* Common Object Definition */
/* ------------------------------------------------------------ */
// This structure defines a generic object. There is an instance
// of this structure at the head of all objects in the system. The
// generic object manipulation functions operate on fields in this
// structure and call on the object specific manipulation functions
// based on the object type when necessary.
// IMPORTANT NOTE: all synchronization objects contain a field called
// pwnWait which must be at the same offset for all types. Since
// we are constrained by NT compatibility to keep critical section
// structures a certain size, you cannot change this structure
// without ensuring that this field is at the same offset in all
// sync objects and that critical sections are NT compatible in
// size.
typedef struct _obj {
BYTE typObj; // object type
BYTE objFlags; // object flags
WORD cntUses; // count of this objects usage
} OBJ;
typedef OBJ *POBJ;
#define fObjTypeSpecific 0x80 // meaning depends on object type
#define fObjTypeSpecific2 0x40 // meaning depends on object type
#define fObjTypeSpecific3 0x20 // meaning depends on object type
// type-specific objFlag bits.
#define fNewCrstBlock fObjTypeSpecific // (typObjCrst) high bit for thread blocked while crst owned
#define fEvtManualReset fObjTypeSpecific // (typObjEvent) set for manual reset
#define fTimerRing3 fObjTypeSpecific2 // (typObjTimer) timer has ring-3 completion
// Every object type contains a nested generic object as its first member
#define COMMON_OBJECT OBJ objBase;
// This is a generic non-synchronization object which can be waited on
// all of them include a pointer to an event object which is created when
// they are.
#define COMMON_NSOBJECT OBJ objBase; \
struct _evt *psyncEvt; // here's the embedded event
// This is the external object structure which is used to
// supply a Win32 handle to an external component's structure.
// e.g. Winsock socket handles
typedef struct _external_obj {
COMMON_OBJECT // it is an object
DWORD context; // typically a pointer for use by the external component
} EXTERNAL_OBJ, * PEXTERNAL_OBJ;
/* ------------------------------------------------------------ */
/* Synchronization Object & Structure Definition */
/* ------------------------------------------------------------ */
#define fWaitDefault 0 // default flags
#define fWaitAllFlag 1 // set for wait all, clear for wait any
#define fWaitCrst 2 // special critical section wait
typedef struct _wnod {
struct _wnod *pwnNext; // pointer to next in circular list
struct _wnod *pwnCirc; // pointer to wait node in next circular list
struct TDBX *ptdbxWait; // thread waiting
struct _synco *pobjWait; // object being waited on
} WNOD;
// Every object name is stored in a structure like this one. Each hash table entry
// points to a forward linked list of these structures.
typedef struct _objnamestruct {
struct _objnamestruct *NextOName; // next in hash list
OBJ *ObjPtr; // named object this refers to
char NameStr[1]; // name string
} OBJNAME;
// This is a generic synchronization object which is a subset of the other
// synchronization objects
typedef struct _synco {
COMMON_OBJECT
WNOD *pwnWait; // pointer to the wait node for this object
LONG cntCur; // current count to test state, != 0 is signaled
OBJNAME *NameStruct; // name structure for this object
} SYNCO;
// A semaphore object
// IMPORTANT NOTE: This structure must fit inside the NT KSEMAPHORE type, where
// sizeof(KSEMAPHORE) is 20.
typedef struct _sem {
COMMON_OBJECT
WNOD *pwnWait; // pointer to the wait node for this object
LONG cntCur; // current count of semaphore availability
OBJNAME *NameStruct; // name structure for this object
LONG cntMax; // maximum allowed count
} SEM;
// A Mutex
typedef struct _mutx {
COMMON_OBJECT
WNOD *pwnWait; // pointer to the wait node for this object
LONG cntCur; // current count of object
OBJNAME *NameStruct; // name structure for this object
struct TDBX *ptdbxOwner; // owner thread
struct _mutx *SysMutexLst; // system list of mutexes
} MUTX;
typedef MUTX *PMUTX;
// This structure defines a critical section. Although it has the
// typObj field, a critical section is not a true object. This limitation
// is to provide structure size compatibility with NT.
// IMPORTANT NOTE: Since the pwnWait is at a specific offset in order
// to use generic sync object functions, it is important not to
// reorder this structure's members unless absolutely necessary.
// If you do, be sure to look at the OBJ data type and other
// synchronization object types.
typedef struct _crst {
BYTE typObj; // type of object
BYTE objFlags; // object flags
WORD objPadding; // OBJ.cntUses not needed
LONG cntRecur; // recursion count of ownership
struct TDBX *ptdbxOwner; // owner thread of this critical section
struct TDBX *ptdbxWait; // pointer to the first waiting TDB
LONG cntCur; // count of critical section ownership
struct _crst *SysCrstLst; // system list of critical sections
LST *pdbLst; // list of owning processes
struct _crstexport *pextcrst; // pointer to external critical section
} CRST;
// This is the exported critical section structure which is used to
// indirectly access the internal critical section structure and cleanup.
typedef struct _crstexport {
COMMON_OBJECT // it is an object
CRST *crstInternal; // pointer to internal critical section
} CRST_EXPORT;
// This structure and defines make up an event object.
// IMPORTANT NOTE: This structure must fit inside the NT KEVENT type, where
// sizeof(KEVENT) is 16.
typedef struct _evt {
COMMON_OBJECT
WNOD *pwnWait; // pointer to the wait node for this object
LONG cntCur; // signaled state
OBJNAME *NameStruct; // name structure for this object
} EVT;
typedef EVT *PEVT;
// so we have access to generic NSOBJ's data structure
typedef struct _nsobj {
COMMON_NSOBJECT
} NSOBJ;
#define LCRST_DEFINED // disable duplicate definition in syslevel.h
// Include heirarchical critical section support
#include <syslevel.h>
// This is a heirarchical critical section used to ensure
// deadlock resistant code
typedef struct _lcrst {
CRST cstSync;
#ifdef SYSLEVELCHECK
SYSLVL slLevel;
#endif
} LCRST;
typedef LCRST *LPLCRST;
typedef struct _createdata16 {
LPVOID pProcessInfo; // LPPROCESS_INFORMATION
LPVOID pStartupInfo; // LPSTARTUPINFO
LPVOID pCmdLine; // points to command line
} CREATEDATA16;
// Include the TIB definition
#include <k32share.h>
#include <apc.h>
#define TLS_MINIMUM_AVAILABLE_GLOBAL 8
// Thread Data Block structure.
//
// !!!! BUGBUG !!!!
// This definition is duplicated in object.inc and core\inc\object16.inc
//
typedef struct _tdb
{
COMMON_NSOBJECT // standard waitable non-synchronization object
#ifdef WOW
TIB * ptib; // Thread Information Block--from k32share.h
#else // WOW
TIB tib; // Thread Information Block--from k32share.h
#endif ; else WOW
// opengl32 depend on TslArray at offset 0x88 from pTIB. Someone has remove the ppdbProc
// and wnodLst probably for good reasons. But to keep apps happy, we will add 2 dowords back
// currently sizeof(TIB)==56
//struct _pdb* ppdbProc; // DON'T MOVE THIS RELATIVE TO tib!! (for M3 NTcompat)
DWORD cntHandles; // count of handles to this thread
WORD selEmul; // selector to 80x87 emulator data area
WORD selTib; // selector to the TIB for this process
DWORD dwStatus; // thread status/termination code
DWORD flFlags; // state of thread
DWORD dwPad1; // just to pad
//WNLST wnodLst; // embedded structure for synchronization
//
// keep R0ThreadHandle offset at 0x54 for Javasup.vxd
//
DWORD R0ThreadHandle; // ring 0 thread handle
// Warning !!! move dwPad2 below cus SAS 6.12 hardcoded pStackBase at offset 0x54 from
// pTib. It also used the defunc field pStackTerm ( now dwPad2 ). Whoever gave this
// internal structure to SAS is a bonehead.
// Break SAS and see what happen
WORD wMacroThunkSelStack16; // Used to be TIBSTRUCT.selStack16
WORD wPad;
VOID * pvMapSSTable; //Table of 16-bit ss's for flat thunks
DWORD dwCurSS; //Current default 16-bit ss for flat thunks
DWORD dwCurNegBase; //negative base of current default ss
VOID * pvThunkConnectList; //head of list of in-progress thunk handshakes
VOID * pvExcept16; //Head of 16-bit thread exception handler chain
PCONTEXT tdb_pcontext; // pointer to context. if 0, goto ring 0
HANDLE tdb_ihteDebugger; // thread handle for debugger
struct _der * tdb_pderDebugger; // pointer to debugger control block
DWORD ercError; // extended error code for last thread error
VOID * pvEmulData; // Pointer to emulator data area
VOID * pStackBase; // stack object base address
struct TDBX * ptdbx; // ring 0 per thread data pointer
// wnodLst is 8 bytes, tib has grown, only need 4 bytes here
DWORD dwPad2; // just to pad, see comment on ppdbProc.
LPVOID TlsArray[TLS_MINIMUM_AVAILABLE+TLS_MINIMUM_AVAILABLE_GLOBAL]; // thread local storage array
LONG tpDeltaPri; // delta from base priority class
TPITERM tdb_tpiterm;// tpi and termination data union
struct _createdata16 * pCreateData16; // ptr to creat data for 16-bit creat
DWORD dwAPISuspendCount; // suspend/resume api count
LPSTR lpLoadLibExDir; // ptr to LoadLibraryEx() dir
// For 16-bit threads only
WORD wSSBig; // selector of optional Big Stack
WORD wPad2;
DWORD lp16SwitchRec;
DWORD tdb_htoEndTask;
DWORD tdb_cMustCompletely;
#ifdef DEBUG
DWORD apiTraceReenterCount; // api trace reenter count
PWORD pSavedRip; // pointer to saved rip string from 16 bit krnl
LPVOID
TlsSetCallerArray[TLS_MINIMUM_AVAILABLE+TLS_MINIMUM_AVAILABLE_GLOBAL]; // caller's to TlsSetValue
#endif
#ifdef WOW
HANDLE hTerminate;
#endif
} TDB;
typedef TDB *PTDB;
#define TDBSTUBSIZE sizeof(TDB)
/* Flags for fields of TDB.flFlags
*/
#define fCreateThreadEvent 0x00000001
#define fCancelExceptionAbort 0x00000002
#define fOnTempStack 0x00000004
#define fGrowableStack 0x00000008
#define fDelaySingleStep 0x00000010
#define fOpenExeAsImmovableFile 0x00000020
#define fCreateSuspended 0x00000040
#define fStackOverflow 0x00000080
#define fNestedCleanAPCs 0x00000100
#define fWasOemNowAnsi 0x00000200
#define fOKToSetThreadOem 0x00000400
#define fTermCleanupStack 0x00000800
#define fInCreateProcess 0x00001000
#define fHoldDisplay 0x00002000
#define fHoldSystem 0x00004000
/* Flags for fields of PDB.flFlags
*/
#define fDebugSingle 0x00000001
#define fCreateProcessEvent 0x00000002
#define fExitProcessEvent 0x00000004
#define fWin16Process 0x00000008
#define fDosProcess 0x00000010
#define fConsoleProcess 0x00000020
#define fFileApisAreOem 0x00000040
#define fNukeProcess 0x00000080
#define fServiceProcess 0x00000100
#define fProcessCreated 0x00000200
#define fDllRedirection 0x00000400
#define fLoginScriptHack 0x00000800 //DOS app loaded into existing console and TSR'd
/* These bits can be in either the TDB or the PDB
*/
#define fSignaled 0x80000000
#define fInitError 0x40000000
#define fTerminated 0x20000000
#define fTerminating 0x10000000
#define fFaulted 0x08000000
#define fTHISFLAGISFREE 0x04000000
#define fNearlyTerminating 0x00800000
#define fDebugEventPending 0x00400000
#define fSendDLLNotifications 0x00200000
/* Process Data Block Structure and support defines and structures.
*/
typedef VOID (KERNENTRY *PFN_CONTROL)(DWORD CtrlType);
/* Environment data block for various per-process data including arguments,
** current directories, handles, and environment strings. This data block
** resides in the scratch heap.
*/
typedef struct _edb {
char * pchEnv; /* environment block (preceded by PchEnvHdr) */
DWORD unused; /* was cbEnvMax */
char * szCmdA; /* command line (ANSI copy)*/
char * szDir; /* current directory of process */
STARTUPINFO * lpStartupInfo; /* pointer to startup information */
HANDLE hStdIn; /* handle of standard in */
HANDLE hStdOut; /* handle of standard out */
HANDLE hStdErr; /* handle of standard error */
HANDLE hProc; /* handle to the owning process. */
struct _console * pInheritedConsole; /* Console to inherit if needed */
DWORD ctrlType; /* ctrlNone, ctrlC, ctrlBreak */
SEM * psemCtrl; /* Protects access to control data */
EVT * pevtCtrl; /* Control C or Break event */
TDB * ptdbCtrl; /* Control handler thread */
PFN_CONTROL * rgpfnCtrl; /* Array of Control C or Break handlers */
int cpfnCtrlMac; /* Last item in array */
int cpfnCtrlMax; /* Size of array */
char * rgszDirs[26]; /* array of drive directories */
LPWSTR szCmdW; /* command line (Unicode copy)*/
char * szDirO; /* current directory OEM copy*/
} EDB;
// We need a fake DOS MCB structure at the start of our Win32 environment
// block, because this block also doubles as the DOS environment for Win16
// apps.
struct _dosMCB {
BYTE type; // Set to 'M'
BYTE owner_lo; // Owner PSP
BYTE owner_hi;
BYTE size_lo; // Size (in paragraphs)
BYTE size_hi;
BYTE unused[11];
};
// PCHENVHDR: This header structure must precede the environment strings
// block pointed to by _edb->pchEnv. It contains the info about the
// block allocation.
typedef struct _pchEnvHdr {
DWORD dwSig; /* Signature: must be PCHENVHDR_SIG */
DWORD cbReserved; /* # of bytes reserved (must be page-size divisible) */
DWORD cbCommitted; /* # of bytes committed (must be page-size divisible) */
struct _pdb * ppdb; /* PDB32 who's context this belongs to. */
struct _dosMCB MCB; /* Fake DOS MCB for compatibility */
// Do not add any fields after the MCB. The MCB must immediately precede
// the environment strings for compatibility.
} PCHENVHDR, *LPPCHENVHDR;
#define PCHENVHDR_SIG 0x45484350 /* 'PCHE' */
// MODREF - a double, doubly linked list of module references.
// Each loaded module has its own MODREF record. Follow the
// nextMod element to get a list of modules owned by the process.
// Follow the nextPdb element to get a list of PDBs that refer
// to this module.
#define fModRecycle 0x8000 /* This modules read only sections
** should be recycled in context (i.e. before they go away)
*/
#define fModRetain 0x400 /* Used to prevent child from getting
** freed before the parent
*/
#define fModRefSnapped 0x200 /* This module's IATs are fixed up
** in this context (so what is
** 'fModFixupIAT' below?)
*/
#define fModPrivateResource 0x100/* the resource object has been privatized
** in this process. Attaches should not be
** made to the resource object.
*/
#define fModFixupIAT 0x80 /* the IAT has been already fixed
** up for debugging
*/
#define fModNoThrdNotify 0x40 /* doesn't need thread notifications */
#define fModHasStaticTLS 0x20 /* this module has static TLS */
#define fModRefShared 0x10 /* this MODREF is in a shared arena */
#define fModAttach 0x8 /* process attach notification has been sent
** to this module in this process context
*/
#define fModDebug 0x4 /* debug notification has been sent
** to the debugger for this module
*/
#define fModPrivate 0x2 /* the module has been privatized in this
** process. Attaches should not be made.
*/
#define fModBusy 0x1 /* set to detect dependency loops */
#define MOD_USAGE_MAX 0xffff
typedef struct _tagMODREF {
struct _tagMODREF
* nextMod, // next module in this process
* prevMod,
* nextPdb, // next process linked to this mod
* prevPdb;
IMTE imte; // index in module table
WORD usage; // reference count this process to this module
WORD flags; // fModFlags as set above
WORD cntRefs; // count of implicit references
struct _pdb *ppdb; // process that owns module
struct _tagMODREF *refs[1]; // implicit refs of this module, variable length
// Must be last item in structure
} MODREF;
// Entrypoints into WSOCK32.DLL
struct socket_epts {
DWORD recv;
DWORD arecv;
DWORD send;
DWORD asend;
DWORD close;
};
#define MAX_PROCESS_DWORD 1
typedef struct _pdb {
COMMON_NSOBJECT // standard waitable non-synchronization object
DWORD dwReserved1; // so that other offsets don't change
DWORD dwReserved2; // so that other offsets don't change
DWORD dwStatus; // process termination status code
DWORD wasDwImageBase; // Points to header of process (MZ + stub)
struct heapinfo_s *hheapLocal; // DON'T MOVE THIS!!! handle to heap in private memeory
DWORD hContext; // handle to process' private memory context
DWORD flFlags; // debugging and inheritance flags
PVOID pPsp; // linear address of PSP
WORD selPsp; // selector of the PSP for the process
SHORT imte; // index to module table entry for this process
SHORT cntThreads; // number of threads in this process
SHORT cntThreadsNotTerminated; // threads not past termination code
SHORT cntFreeLibRecurse; // keep track of recursion into FreeLibrary
SHORT R0ThreadCount; // ring 0 version of same
HANDLE hheapShared; // handle to heap in shared memory
DWORD hTaskWin16; // associated Win16 task handle
struct fvd_s * pFvd; // ptr to memory mapped file view descriptors
EDB * pedb; // pointer to environment data block
struct _htb * phtbHandles;
struct _pdb * ppdbParent; // pointer to PDB of parent process
MODREF * plstMod; // pointer to process module table list
struct _lst * plstTdb; // pointer to list of process threads
struct _dee * pdb_pdeeDebuggee; // pointer to debuggee control block
struct lhandle_s *plhFree; // Local heap free handle list head ptr
DWORD pid; // id, same as initial thread id
LCRST crstLoadLock; // per-process load synch (hierarchical)
struct _console * pConsole; // pointer to Console for this process
DWORD TlsIdxMask[((TLS_MINIMUM_AVAILABLE+31)/32)]; // mask of used TLS idxs
DWORD adw[MAX_PROCESS_DWORD]; // free-form storage
struct _pdb * ppdbPGroup; // process group this process belongs to (default 0)
MODREF * pModExe; // parent EXE ModRef record
LPTOP_LEVEL_EXCEPTION_FILTER pExceptionFilter; // set by SetUnhandledExceptionFilter
LONG pcPriClassBase; // priority value of this processes' pri class
struct heapinfo_s *hhi_procfirst; // linked list of heaps for this process
struct lharray_s *plhBlock; // local heap lhandle blocks
struct socket_epts * psock_epts; // socket entrypoints
struct _console * pconsoleProvider; // pconsole that winoldapp is providing.
WORD wEnvSel; // selman alloced DOS environment selector
WORD wErrorMode; // handling of critical errors
PEVT pevtLoadFinished; // waiting for load to be finished
WORD hUTState; // UT info
BYTE bProcessAcpiFlags; // ACPI flags for this process, see def below
BYTE bPad3;
LPCSTR lpCmdLineNoQuote; // Optional unquoted command line (apphack)
} PDB;
//
// Flags def for bProcessAcpiFlags
//
#define PROCESS_ACPI_FLAGS_WAKEUP_LT_DONT_CARE 0x00
#define PROCESS_ACPI_FLAGS_WAKEUP_LT_LOWEST_LATENCY 0x01
#define PDBSTUBSIZE sizeof(PDB)
typedef PDB *PPDB;
/* File Data Block Structure.
*/
/* SPECIAL NOTE on memory mapped files and cached file handles
* CreateFile(filename, FILE_FLAG_MM_CACHED_FILE_HANDLE);
* In this case the caller indicates an intention to later
* call CreateFileMapping(hFile, ...) and desires that the file
* handle we will using be a cached file handle.
* So we store away the filename and fsAccessDos in the FDB and
* in CreateFileMapping() retrieve the filename and flgs for use
* in implementing cached file handles, where extended handles are
* not available. eg. real-mode netware drivers
*/
typedef struct _cfh_id {
DWORD fsAccessDos; /* dos openfile flgs: used for cached fh
* of memory mapped files
*/
LPSTR lpFilename; /* filename stored only for
* cached Memory mapped files
* win32 loader modules and
* delete_on_close
*/
} CFH_ID;
typedef struct _fdb {
COMMON_NSOBJECT // standard waitable non-synchronization object
WORD hdevDos; /* DOS device handle */
WORD wDupSrcPSPSel; /* NETX: if inter-process dup'ed
* holds the PSP dup'ed from so that
* PSP will remain around till this
* handle gets closed.
*/
CFH_ID cfhid;
DWORD devNode; // The devvice node where the handle lives on
DWORD dwCountRequestDeviceWakeup;
} FDB, *PFDB;
/*
* Spl value for FDB.fsAccessDos to indicate that filename stored should be
* deleted on close.
*/
#define DELETE_ON_CLOSE_FILENAME -1
/* Find Change Notify Data Block Structure.
*/
typedef struct _fcndb {
COMMON_NSOBJECT // base of every ns object structure
DWORD hChangeInt; /* internal change handle */
} FCNDB;
typedef FCNDB *PFCNDB;
/* Pipe Data Block Structure.
*/
typedef struct _pipdb {
COMMON_OBJECT // base of every object structure
BYTE * hMem; // Mem handle of pipe
DWORD hNmPipe; // Named pipe handle (hInvalid if anon)
DWORD rdRef; // Ref count on read handle
DWORD wrRef; // Ref count on write handle
DWORD pszByt; // Size of hMem (pipe) in bytes
DWORD wPtr; // write pointer (offset in hMem)
// Pointer to last byte written
DWORD rPtr; // read pointer (offset in hMem)
// Pointer to next byte to read
EVT * wBlkEvnt; // write event handle (waiting for room to write)
EVT * rBlkEvnt; // read event handle (waiting for data to read)
} PIPDB;
/* MailSlot Data Block Structure.
*/
typedef struct _msdb {
COMMON_OBJECT // base of every object structure
LPSTR lpMSName; // Pnt to name of mailslot (== 0 for
// read (CreateMailslot) handle)
DWORD hMSDos; // INT 21 mailslot handle (== 0xFFFFFFFF
// for write (CreateFile) handle)
} MSDB;
/* ToolHelp Data Block Structure.
*/
typedef struct _tlhpdb {
COMMON_OBJECT // base of every object structure
DWORD ClassEntryCnt;
BYTE * ClassEntryList; // actually (CLASSENTRY32 *)
DWORD HeapListCnt;
BYTE * HeapList; // actually (HEAPLIST32 *)
DWORD ProcessEntryCnt;
BYTE * ProcessEntryList; // actually (PROCESSENTRY32 *)
DWORD ThreadEntryCnt;
BYTE * ThreadEntryList; // actually (TREADENTRY32 *)
DWORD ModuleEntryCnt;
BYTE * ModuleEntryList; // actually (MODULEENTRY32 *)
} TLHPDB;
/* Device IO Control Object
*/
typedef struct _diodb {
COMMON_OBJECT // base of every object structure
DWORD pDDB; /* VxD/device DDB */
LPSTR lpUnloadOnCloseModuleName; /* delete_on_close for a vxd */
char DDB_Name[8];
} DIODB;
/* Serial Data Block Structure
*/
#define OVERLAPPED_OPEN 1
#define READEVENT_INUSE 2
#define WRITEEVENT_INUSE 4
typedef struct _sdb {
COMMON_OBJECT // base of every object structure
DWORD SerialHandle;
EVT * pWriteEvent;
EVT * pReadEvent;
EVT * pWaitEvent;
DWORD Flags;
DWORD DevNode;
DWORD dwCountRequestDeviceWakeup;
} SDB;
typedef VOID (CALLBACK *PTIMER_APC_ROUTINE)(LPVOID,ULONG,LONG);
// Timer object.
//
// Notes:
// The timerdb must ALWAYS be pagelocked. This is consistent
// with the requirement that the structure passed to KeSetTimer
// be pagelocked. Furthermore, we use the non-preemptibility of
// of ring-0 code to serialize access to many parts of the structure
// (due to the fact that much of this code has to run at event time.)
// This non-preemptibility is guaranteed only if the structure is
// locked.
//
// Timers can be created at ring-0 or ring-3. If a timer is created at
// ring-3, the memory is always allocated and deallocated by kernel32.
// Kernel32 also makes sure that an explicit canceltimer is always done
// on the timer before it is finally freed - we depend on this fact
// to do the proper cleanup for timerr3apc's.
//
// Timers created at ring-3 can be passed to Ke* routines.
//
// Timers created at ring-0 cannot be passed to SetWaitableTimer() at
// ring-3. (There are some nasty cleanup problems associated with this
// due to the fact that ring-0 timers are freed by the device driver
// with no notification given to the system.)
//
// We use the cntUses field to determine whether a timer was created
// at ring 3.
//
// Synchronization:
//
// typObj Static, none needed
// objFlags
// fTimerIsRing3 by being in a no-preempt section
// cntUses Used by handle manager
// pwnWait WaitR0
// cntCur WaitR0 [w/ one exception: see [1])
// NameStruct Krn32Lock - used only at ring3
// lpNextTimerDb by being in a no-preempt section
// hTimeout by being in a no-preempt section
// DueTime by being in a no-preempt section
// Completion by being in a no-preempt section
// lPeriod by being in a no-preempt section
//
// [1] Because KeSetTimer has to unsignal the timer, and be
// able to do it at event time, it pokes a zero directly
// into cntCur. But this is ok because the only code
// that signals timers is TimerDoTimeout which is
// non-preemptive.
//
// Flag descriptions:
//
// fTimerIsEventHandle
// hTimeout - a timeout handle
//
// fTimerIsRing3
// If the COMPLETION is non-null, this bit indicates whether the
// COMPLETION points to a TIMERR3APC (ring-3 completion) or a KDPC
// (ring-0 completion.) The value of this bit is undefined at any
// other time.
//
// Field descriptions:
//
// <common-obj and common-sync stuff omitted>
//
// lpNextTimerDb:
// All active timers that were set with fResume TRUE are linked into
// TimerSysLst (for the purpose of knowing how to program the power
// timer.) This field is NULL when the timer is inactive or active
// without fResume.
//
// hTimeout:
// If the timer is active, this field contains the handle to the
// underlying VMM hTimeout. If the timer is inactive, this
// field is NULL. If the timer is in the in-progress state,
// this field is undefined (actually points to a stale VMM timeout
// handle!)
//
//
// DueTime:
// If the timer is active, contains the absolute time that the
// timer is due to go off. Expressed as a FILETIME converted from
// GetSystemTime. Undefined if the timer isn't active.
//
// Completion:
// Then contains either:
// NULL - no completion was set
// LPTIMERR3APC - if fTimerIsRing3 is set
// PKDPC - if fTimerIsRing3 is not set.
//
// Note that it is normal for a timer to be inactive and contain
// a pointer to a TIMERR3APC structure. This case occurs when
// a timer set with a ring-3 completion fires normally. The
// TIMERR3APC structure is kept around so that a subsequent
// CancelWaitableTimer() can retrieve the underlying apc handle
// embedded in it.
//
// lPeriod:
// Contains either 0 for a one-shot timer or a positive value
// (the firing period in milliseconds.)
typedef struct _timerdb {
COMMON_OBJECT // standard waitable non-synchronization object
// These fields have to appear in this form because a timer is a sync object.
WNOD *pwnWait; // pointer to the wait node for this object
LONG cntCur; // signaled state
OBJNAME *NameStruct; // name structure for this object
// These fields are timer-specific.
struct _timerdb *lpNextTimerDb; //Link in TimerSysLst (can be NULL)
DWORD hTimeout;
FILETIME DueTime;
DWORD Completion;
LONG lPeriod; //Optional period
// Try not to add new fields. This structure cannot exceed 40 bytes
// or we break compatibility with NT's Ke api. If you try to hang
// another structure off it, remember that the Ke*Timer apis can't
// allocate memory from the heap (system meltdown if these apis
// are called at event time on a system that's paging thru DOS.)
} TIMERDB, *LPTIMERDB;
//
// A dynamic extension to the timerdb that's used whenever a ring-3 timer
// is armed with a completion function. This structure must live in locked
// memory.
//
// Access to this structure is serialized by being in a no-preempt section.
// There are no semaphores guarding it.
//
// This structure is allocated whenever SetWaitableTimer() is called on a
// timer with a non-null completion function. It's stored in the Completion
// field and the fTimerIsRing3 bit is set to indicate that this a TIMERR3APC
// (opposed to a ring-0 DPC.)
//
// This structure is detached from the timerdb on the next call to
// CancelWaitableTimer(). It's also usually freed at this time except
// if a cancel occurs after the last apc has been delivered but TimerApcHandler
// hasn't yet set fHandlerDone to indicate that's it finished using the
// structure. In this case, we can't free it so we instead link it onto
// the TimerDisposalWaitingList. When fHandlerDone does become TRUE,
// it will be available for pickup the next time we need one of these
// structures.
//
// The automatic rearming of a periodic timer reuses the existing
// TIMERR3APC. It checks the fHandleDone: if the handler hasn't
// finished (or begun) on the previous apc, we don't schedule a new
// one (as per specs).
//
// Fields:
// cRef - reference count
// pfnCompletion - Ptr to ring-3 completion (never NULL)
// lpCompletionArg - uninterpreted argument to pfnCompletion
// R0ThreadHandle - thread that called SetWaitableTimer()
// DueTime - trigger time to pass to pfnCompletion. This
// field isn't set until the timer goes off.
// dwApcHandle - if apc has been queued, contains the underlying
// apc handle. NULL otherwise. This apc handle gets
// freed at the same time we free the TIMERR3APC
// (or in the case of a periodic timer, when we
// reuse the structure for the next arming.)
// lpNext - Used for linking in TimerDisposalWaitingList,
// undefined otherwise.
//
//
//
typedef struct _timerr3apc {
DWORD cRef;
PTIMER_APC_ROUTINE pfnCompletion; //completion routine
LPVOID lpCompletionArg; //arg to pass to pfnCompletion
DWORD ApcTdbx; //thread that set the timer
FILETIME DueTime; //the DueTime passed to completion
DWORD dwApcHandle; //underlying apc handle
struct _timerr3apc *lpNext; //next ptr
LPTIMERDB lpTimerDB; // back pointer to my TimerDB
} TIMERR3APC, *LPTIMERR3APC;
// Ring 0 External Object.
//
// Kernel object used to store data about an externally allocated object. VxDs
// can use the VWIN32_AllocExternalHandle service to make a Win32 handle for
// one of their data structures and return the handle back to a Win32 app.
// An application may use this handle to communicate with the VxD, ideally
// through the DeviceIoControl interface. The VxD can get back to the original
// object by using the VWIN32_UseExternalObject service. When the VxD is
// through using the object, it must call VWIN32_UnuseExternalObject.
//
// Because the handle returned by VWIN32_AllocExternalHandle is a standard
// Win32 handle, all of the standard Win32 handle services, such as
// DuplicateHandle, will work with it. In addition, when a process terminates,
// the object cleanup is automatically performed. Thus, a VxD doesn't have to
// watch process notification messages just to check if a per-process data
// structure should be cleaned-up.
//
// When allocating the Win32 handle, the VxD provides a virtual table (vtbl) of
// functions to invoke whenever type specific handle operations are performed.
// For example, when the usage count of an object goes to zero, the vtbl is
// used to notify the VxD that the external object should be released.
struct _R0OBJTYPETABLE; // Forward reference (in vwin32.h)
typedef struct _r0objext {
COMMON_NSOBJECT
DWORD cntExternalUses;
struct _R0OBJTYPETABLE* pR0ObjTypeTable;
LPVOID pR0ObjBody;
ULONG devNode;
} R0OBJEXT, * PR0OBJEXT;
//
// objTypMsgIndicator
//
typedef struct _MsgIndicatorDb {
COMMON_NSOBJECT
ULONG ulMsgCount;
} MSGINDICATORDB, *PMSGINDICATORDB;
/* ------------------------------------------------------------ */
/* Function Prototypes
/* ------------------------------------------------------------ */
GLOBAL VOID KERNENTRY UseObject (VOID *); // incs usage count
GLOBAL OBJ * KERNENTRY NewObject (DWORD, BYTE); // allocates generic obj of size and type
GLOBAL VOID KERNENTRY DisposeObject (OBJ *); // deallocates generic object
GLOBAL BOOL KERNENTRY FUnuseObject (VOID *); // decs usage count
GLOBAL OBJ * KERNENTRY PobjDupObject (OBJ *, PDB *, PDB *); // duplicates pointer to object
GLOBAL VOID KERNENTRY LockObject(OBJ *);
GLOBAL VOID KERNENTRY UnlockObject(OBJ *);
GLOBAL MODREF * KERNENTRY MRAlloc(IMTE imte, PDB *ppdb);
#endif
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/****************************************************************/