Every process has serial heaps. Heap structure is as this: copy from heap.h of Win2K source code.
Maybe Microsofe only tell us that can get HEAP_ENTRY with HeapWak function. But it's mislead.
HEAP_ENTRY is just part of HEAP.
typedef struct _HEAP {
HEAP_ENTRY Entry;
ULONG Signature;
ULONG Flags;
ULONG ForceFlags;
ULONG VirtualMemoryThreshold;
SIZE_T SegmentReserve;
SIZE_T SegmentCommit;
SIZE_T DeCommitFreeBlockThreshold;
SIZE_T DeCommitTotalFreeThreshold;
SIZE_T TotalFreeSize;
SIZE_T MaximumAllocationSize;
USHORT ProcessHeapsListIndex;
USHORT HeaderValidateLength;
PVOID HeaderValidateCopy;
USHORT NextAvailableTagIndex;
USHORT MaximumTagIndex;
PHEAP_TAG_ENTRY TagEntries;
PHEAP_UCR_SEGMENT UCRSegments;
PHEAP_UNCOMMMTTED_RANGE UnusedUnCommittedRanges;
//
// The following two fields control the alignment for each new heap entry
// allocation. The round is added to each size and the mask is used to
// align it. The round value includes the heap entry and any tail checking
// space
//
ULONG AlignRound;
ULONG AlignMask;
LIST_ENTRY VirtualAllocdBlocks;
PHEAP_SEGMENT Segments[ HEAP_MAXIMUM_SEGMENTS ];
union {
ULONG FreeListsInUseUlong[ HEAP_MAXIMUM_FREELISTS / 32 ];
UCHAR FreeListsInUseBytes[ HEAP_MAXIMUM_FREELISTS / 8 ];
} u;
USHORT FreeListsInUseTerminate;
USHORT AllocatorBackTraceIndex;
ULONG Reserved1[2];
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries;
LIST_ENTRY FreeLists[ HEAP_MAXIMUM_FREELISTS ];
PHEAP_LOCK LockVariable;
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine;
//
// The following field is used to manage the heap lookaside list. The
// pointer is used to locate the lookaside list array. If it is null
// then the lookaside list is not active.
//
// The lock count is used to denote if the heap is locked. A zero value
// means the heap is not locked. Each lock operation increments the
// heap count and each unlock decrements the counter
//
PVOID Lookaside;
ULONG LookasideLockCount;
} HEAP, *PHEAP;
"Heap Walker" is a useful tool from internet.
Download Url: http://www.nosec.org/web/files/HeapWalker.exe.txt