#include "reactos/ntos/types.h" /* for PVOID etc. */
#include <glib/gmessages.h>
#include <glib/gmem.h>
+#include <glib/ghash.h>
+
+
+/* map PVOID->GUINT_TO_POINTER(ULONG Tag) */
+static GHashTable *memory_Tag_hash;
+
+static void memory_Tag_hash_init(void)
+{
+ if (memory_Tag_hash)
+ return;
+ memory_Tag_hash=g_hash_table_new(g_direct_hash,g_direct_equal);
+}
/**
* @PoolType: Type of memory to allocate. Safely ignored by libcaptive as it is
* too low level for it.
* @NumberOfBytes: Size of the requested allocation. Value 0 permitted (returns %NULL).
- * @Tag: 4-bytes of block identification for debugging purposes.
- * Ignored by libcaptive.
+ * @Tag: 4-bytes of block identification for debugging purposes and/or ExFreePoolWithTag().
+ * Bit 7 (==%0x80 ) of each byte must be cleared.
+ * %PROTECTED_POOL with @Tag bit 31 set is not yet implemented.
*
* Allocates the specified memory block. libcaptive passes the allocation to
- * g_malloc(). @Tag is no longer trackable for the allocated memory block.
- * @Tag is ignored by libcaptive.
+ * g_malloc() and @Tag is marked to this allocation.
*
* Returns: Memory block base if successfuly allocated. %NULL otherwise.
* The allocated memory block is not cleared.
*/
PVOID ExAllocatePoolWithTag(ULONG PoolType,ULONG NumberOfBytes,ULONG Tag)
{
+PVOID r;
+
+ g_return_val_if_fail((Tag&0x80808080)==0,NULL);
+
+ memory_Tag_hash_init();
+
if (!NumberOfBytes)
return NULL;
+ /* FIXME: >=PAGE_SIZE allocations should be PAGE_SIZE aligned */
+ r=g_malloc(NumberOfBytes);
+
+ g_assert(FALSE==g_hash_table_lookup_extended(memory_Tag_hash,
+ r, /* lookup_key */
+ NULL, /* orig_key */
+ NULL)); /* value */
+ g_hash_table_insert(memory_Tag_hash,
+ (gpointer)r, /* key */
+ GUINT_TO_POINTER(Tag)); /* value */
- return g_malloc(NumberOfBytes);
+ return r;
}
/**
* @NumberOfBytes: Size of the requested allocation. Value 0 permitted (returns %NULL).
*
* Allocates the specified memory block. Calls ExAllocatePoolWithTag() with
- * undeterministic @Tag value.
+ * @Tag value %0x00000000. At least this value seems to be assumed by WXP <ntddk.h>
+ * although it is not officially documented for W32.
*
* Returns: Memory block base if successfuly allocated. %NULL otherwise.
* The allocated memory block is not cleared.
*/
PVOID ExAllocatePool(POOL_TYPE PoolType,ULONG NumberOfBytes)
{
+ /* FIXME: It would be better to mark such block as 'unTagged' but we would have
+ * to maintain some structure for 'memory_Tag_hash' values instead of just GUINT_TO_POINTER().
+ */
return ExAllocatePoolWithTag(PoolType,NumberOfBytes,
- 0); /* Tag; reactos uses TAG_NONE ('None') but it is not documented for W32 */
+ 0x00000000); /* Tag; reactos uses TAG_NONE ('None') but it W32 uses %0x00000000 */
}
/**
*/
VOID ExFreePool(IN PVOID Block)
{
+gboolean errbool;
+
g_return_if_fail(Block!=NULL);
+ memory_Tag_hash_init();
+
+ errbool=g_hash_table_remove(memory_Tag_hash,Block);
+ g_assert(errbool==TRUE);
+
g_free(Block);
}
+
+
+/**
+ * ExFreePoolWithTag:
+ * @Block: Base address of the memory block. %NULL value is forbidden.
+ * @Tag: 4-bytes of required block identification.
+ * Bit 7 (==%0x80 ) of each byte must be cleared.
+ * %PROTECTED_POOL with @Tag bit 31 set is not yet implemented.
+ * Value %0x0000000 is permitted for blocks marked with any Tag.
+ *
+ * Deallocate the given memory block. Block must be already successfuly
+ * allocated by a previous ExAllocatePoolWithTag() call.
+ * Block may be allocated by ExAllocatePool() if @Tag is passed %0x00000000.
+ * Please see more about @Tag in ExAllocatePool().
+ * It is forbidden to pass invalid @Tag for @Block.
+ *
+ * You can no longer assume anything about this base address / memory block.
+ */
+VOID ExFreePoolWithTag(IN PVOID Block,IN ULONG Tag)
+{
+gpointer memory_Tag_gpointer;
+gboolean errbool;
+
+ g_return_if_fail(Block!=NULL);
+ g_return_if_fail((Tag&0x80808080)==0);
+
+ memory_Tag_hash_init();
+
+ errbool=g_hash_table_lookup_extended(memory_Tag_hash,
+ Block, /* lookup_key */
+ NULL, /* orig_key */
+ &memory_Tag_gpointer); /* value */
+ g_return_if_fail(errbool==TRUE);
+ g_return_if_fail(!Tag || GPOINTER_TO_UINT(memory_Tag_gpointer)==Tag);
+
+ ExFreePool(Block);
+}