An O/S isn't magical-- the very same questions you're asking, it has to have answers to in order to maintain itself.
And yes, this is O/S dependent. Some O/S's use more bytes or fewer, depending on what information they want to store with each block.
Some O/S's don't use blockheaders at all, they retain that information in the master pointer list which instead of just pointers contains structures.
Locate Memory Manager information from the O/S builder.
As for accessing block headers (if your O/S handles allocations this way), yes it's just a negative offset from the base pointer. For example:
I hope this helps.
/* defines */
#define 0x00000001 flagLOCKED;
#define 0x00000002 flagRESIZE;
/* typedefs */
typedef struct /* block header format (12 bytes) */
long blockSize; /* size of ramblock + blockheader size */
long flagBits; /* block 'state' */
int whichZone; /* what heap is ramblock allocated from */
int elemSize; /* smallest incrementing step */
/* prototypes */
void foo(void); /* our test function */
/* functions & procs */
bhPtr = 0L; /* init vars */
rawData = (char*)malloc(1024L);
/* assume, from our research, that a windows blockheader appears as above typedef'd */
bhPtr = (blockheader*)(rawData - sizeof(blockheader));
blockSize = bhPtr->blockSize; /* get block size */
blockSize -= sizeof(blockheader); /* account for header size */
rawData = 0L;
bhPtr = 0L;