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

201 lines
8 KiB
PHP

; HGROUP.INC
;
; WARNING: This file contains structures used by both 16-bit and 32-bit code.
; Make sure the structures align the same in both!
;
; These structures support *handle groups*. Handle groups are global
; memory blocks that are ganged together so than when one gets freed,
; all get freed automatically. This solves the problems of cleanup when
; a Win32 thunk has to copy a shared block (for say DDE or clipboard)
; to repack a structure or move data into a shared heap. Figuring out
; when to free these intermediate copies is a nightmare (especially for DDE).
; Since the copy and the original are one "virtual block", a better solution
; is to put them in a handle group. Then all copies get cleaned
; up automatically.
;
; A "global block" is either a Win16 global memory block or a native
; Win32 global memory block. Blocks of different types can and do mix in the
; same group. Groups are disjoint.
;
; No attempt is made to keep the blocks in a group consistent. Win32
; apps cannot assume that DDE blocks represent shared memory. These blocks
; are used for short term, one way, read-only data transfer.
;
; If any member of a group is freed by an app (or dll), the memory
; managers nuke the entire group and free all of its members (due
; to implementation reasons, Win32 handles may not be freed till
; later. However, the group itself will disappear.)
;
; A block can also defect from a group. Blocks defect if they're cleaned
; up as a result of process termination. Since such a cleanup is probably
; unintentional and an abornal event, we prefer the memory leak to
; causing other apps to crash. Defections don't affect any other member
; of the group.
;
;
;
; For example, suppose a 32-bit DDE server posts a WM_DDE_DATA message.
; The DDE thunk gets a native Win32 handle that can't be used out of context.
;
; The DDE thunk gamely creates a Win16 copy of the block, creates a
; new group and puts the copy and original in the group. Then it sends
; the Win16 copy to the client. Both blocks (and the group) will get
; cleaned up when either the server or the client frees his block. Neither
; the thunk nor the group manager cares which way it happens.
;
; The DDE thunk can also do this to repack a structure. It can make
; a repacked copy and gang it to the original. All group members act
; as a single "virtual handle" which is what an app would expect to see
; in Win3.1.
;
;-------------------------------------------------------------------------
; This structure contains the global variables (in K16) used by the group
; manager. These globals are locked in linear memory since they're used
; by K32 as well. They're packaged in a structure to simplify commmunication
; between the two kernels.
;
; Access to this structure is synchronized by Win16Lock.
;
;
; hg_wSelHeap:
; Contains the *selector* of a movable Win16 global block which is an
; array of HG_NODE structs. Every element is on exactly one of three
; linked lists: the handle list, the death list and the free list.
;
; Initial value: 0. Lazily initialized.
;
; hg_wHndList:
; 16-bit offset into wSelHeap of the first node in the handle list (-1
; if empty). Each node represents a Win32 or Win16 handle that is part
; of some existing group. The list is not sorted in any way.
;
; For implementation reasons, NULL handles can appear on this list for
; short times (*)
;
; Initial value: -1.
;
;
; hg_wDeathList:
; 16-bit offset into wSelHeap of the first node in the death list (-1
; if empty). Each node represents a Win32 handle who is logically
; dead becaues their groups got nuked. The Win32 heap manager walks this
; list periodically and frees the handles. To keep innocent apps from
; paying a performance penalty, we set the TDBF_HGCLEANUP flag in
; the hTask iff the death list contains any handles with that hTask.
;
; DeathList handles do not have group id's. Their group has already gone.
;
; Initial value: -1.
;
; hg_wFreeList:
; 16-bit offset into wSelHeap of the first node in the free list (-1
; if empty). Basically, all nodes that aren't being used for some other
; purpose.
;
;
; hg_wDontTouch:
; normally 0. Set to 1 by certain routines to tell GlobalFree
; not to examine or modify the HG database. Used to prevent
; unwanted recursion when destroying groups. This flag is always set
; and reset within a single Win16 lock session.
;
;
; hg_wDeadGroup:
; used for communication between free_object and GlobalFree. free_object
; sets this global to the hgroup of the dying handle (unless
; hg_wDontTouch is set.) GlobalFree uses this to nuke the group
; and all its other members.
;
;
; (*) Why do NULL handles appear in the handle list? Because nodes need to
; defect from their group when they get freed since we can't have
; invalid handles in the database. But we can't always unlink the node
; at that time since it may be a group leader. So we null out its
; handle but leave the node intact to serve as a group leader.
;
; GrowHGHeap runs a garbage collector that goes and cleans up
; old groups that have no real handles left (BUGBUG: Not yet.)
;
;
; MAINTENANCE WARNING: If you change this structure, you have to build
; both k16 and k32 again. Also, you must ensure that all fields align
; identically in both 32-bit and 16-bit code.
;
; THIS STRUCTURE IS PROTECTED BY THE crstGHeap16Lock, *not* the
; Win16Mutex! Beware!
;
;------------------------------------------------------------------------
HG_GLOBALS STRUCT
hg_wSelHeap dw 0
hg_wHndList dw -1 ;Offset into wSelHeap
hg_wDeathList dw -1 ;Offset into wSelHeap
hg_wFreeList dw -1 ;Offset into wSelHeap
hg_wSlotCnt dw 0 ;# of HG_NODE slots in hg_wSelHeap
hg_wDontTouch dw 0 ;Special use: see above
hg_wDeadGroup dw -1 ;Special use: see above
HG_GLOBALS ENDS
;------------------------------------------------------------------------
; This structure represents nodes in the group manager's database.
; Each node lives on one of three linked lists: the handle list, the
; death list, and the free list.
;
; hgn_wNext: Next node in list (as 16-bit offset into hg_wSelHeap).
;
; hgn_wGroup: Handle-list nodes only: the group id. The group id
; is the address (16-bit offset into hg_wSelHeap) of
; a designated group member (called the group leader).
; All members of a group must use the same group leader.
;
; hgn_hTask16: Win32 handle-list and death-list nodes only: the
; hTask of the Win32 process that created the handle.
; Set to 0 for Win16 handles.
; Native handles are private to each process so they can
; be disambiguated only by using hTask16.
;
; hgn_wChkMk: Private field used by CheckHGHeap.
;
; hgn_dwHnd: Handle-list and death-list nodes only: the heap handle
; (either Win32, or a zero-extended Win16 handle).
; Death-list nodes can only contain native handles here.
;
; hgn_Flags: Flag bits
;
;
; MAINTENANCE WARNING: If you change this structure, you have to build
; both k16 and k32 again. Also, you must ensure that all fields align
; identically in both 32-bit and 16-bit code. You must also change
; SCALE_BY_SIZEOF_HGNODE to reflect any size changes.
;
; THIS STRUCTURE IS PROTECTED BY THE crstGHeap16Lock, *not* the
; Win16Mutex! Beware!
;
;
;------------------------------------------------------------------------
HG_NODE STRUCT
hgn_wNext dw 0 ;Next HG_NODE (offset into wSelHeap)
hgn_wGroup dw 0 ;Group leader (offset into wSelHeap)
hgn_hTask16 dw 0 ;Context of native Win32 handle
hgn_wChkMk dw 0 ;For CheckHGHeap's private use.
hgn_dwHnd dd 0 ;Win32 handle or 0-extended Win16 handle
hgn_Flags dd 0 ;Padding
HG_NODE ENDS
HGF_CANONICAL equ 00000001h ;This handle is a canonical DDE_EXECUTE handle
HGF_BLOWITAWAY equ 00000002h ;Used by HGGarbageCollect
SCALE_BY_SIZEOF_HGNODE macro reg
shl reg,4
endm