/************************************************************************/ /* */ /* 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 // 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 #include #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: // // // // 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 /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /****************************************************************/