CeHeapCreate (Compact 2013)

3/28/2014

This function allows users to create a heap with a custom allocator or deallocator function.

Syntax

HANDLE CeHeapCreate(
  DWORD flOptions,
  DWORD dwInitialSize,
  DWORD dwMaximumSize,
  PFN_AllocHeapMem pfnAlloc,
  PFN_FreeHeapMem pfnFree
);

Parameters

  • flOptions
    [in] Reserved. This parameter must be set to zero.
  • dwInitialSize
    [in] Initial size, in bytes, of the heap.

    This value determines the initial amount of physical storage that is allocated for the heap.

    The value is rounded up to the next page boundary.

    To determine the size of a page on the host computer, use the GetSystemInfo function.

  • dwMaximumSize
    [in] If dwMaximumSize is a nonzero value, it specifies the maximum size, in bytes, of the heap.

    CeHeapCreate rounds dwMaximumSize up to the next page boundary and then reserves a block of that size in the virtual address space of the process for the heap.

    If allocation requests made by HeapAlloc or HeapReAlloc exceed the initial amount of physical storage space specified by dwInitialSize, the system allocates additional pages of physical storage for the heap, up to the heap's maximum size.

    If dwMaximumSize is nonzero, the heap cannot grow and an absolute limitation arises where all allocations are fulfilled within the specified heap unless there is not enough free space.

    If dwMaximumSize is zero, it specifies that the heap can grow and the heap's size is limited only by available memory.

    Requests to allocate blocks larger than 0x0018000 bytes do not automatically fail. The system calls VirtualAlloc to obtain the memory needed for such large blocks.

    Applications that need to allocate large memory blocks should set dwMaximumSize to zero.

  • pfnAlloc
    [in] The allocator function.
  • pfnFree
    [in] The deallocator function.

Return Value

A handle to the heap indicates success. NULL indicates failure.

Remarks

The following code sample shows an implementation that uses a single reservation on the physical memory.

It is possible to use the physical memory on a page-by-page basis if you maintain a free list of the physical memory. In such a case, you use the VirtualFree function on the pages during MEM_COMMIT and MEM_DECOMMIT.

Important

For readability, the following code example does not contain security checking or error handling. Do not use the following code in a production environment.

// Assuming there are some fast memory available on a platform at physical 
// address 0x40000000, of size 0x80000.
// The following code creates a heap on using this memory when possible.
//
#define  PHYS_MEM_ADDR 0x40000000
#define  PHYS_MEM_SIZE 0x00080000
//
BOOL g_fPhysMemUsed;
//
// The allocator
LPVOID MyAllocMem (LPVOID pAddr, DWORD cbSize, DWORD fdwAction, LPDWORD pdwData)
{
   LPVOID lpRet = NULL;
   switch (fdwAction) {
      case MEM_RESERVE:
      // Reserve VM using VirtualAlloc
      if (!(lpRet = VirtualAlloc (pAddr, cbSize, MEM_RESERVE, PAGE_NOACCESS))) {
         SetLastError (ERROR_OUTOFMEMORY);
         break;
      }
      // Use the physical memory if possible
      if (!g_fPhysMemUsed && (cbSize <= PHYS_MEM_SIZE)) {
         // Yes, physical memory is available, use VirtualCopy
         if (!VirtualCopy (lpRet, (LPVOID) (PHYS_MEM_ADDR >> 8), cbSize, PAGE_READWRITE|PAGE_PHYSICAL)) {
               SetLastError (ERROR_OUTOFMEMORY);
               break;
         }
         g_fPhysMemUsed = TRUE;
         *pdwData = PHYS_MEM_ADDR;
      } 
      else {
         *pdwData = 0;   // Indicates this is not using physical memory
      }
      break;
      case MEM_COMMIT:
      // MEM_COMMIT should not change the content of *pdwData, as the data
      // is a 'per-reservation' information.
      if (PHYS_MEM_ADDR  == *pdwData) {
         // This is using physical memory, already committed
         lpRet = pAddr;
      } 
      else {
         lpRet = VirtualAlloc (pAddr, cbSize, MEM_COMMIT, PAGE_READWRITE);
      }
      break;
      default:
      // This should never happen
         DEBUGCHK (0);
         break;
   }
return lpRet;
}
//
// The de-allocator
//
BOOL MyFreeMem (LPVOID pAddr, DWORD cbSize, DWORD fdwAction, DWORD dwData)
{
   BOOL fRet = FALSE;
   switch (fdwAction) {
      case MEM_DECOMMIT:
         if (PHYS_MEM_ADDR  == dwData) {
            // This is using physical memory; never needs to decommit
            break;
         }
         // VirtualAlloc'd data, decommit the memory
         fRet = VirtualFree (pAddr, cbSize, MEM_DECOMMIT);
         break;
      case MEM_RELEASE:
         // Release the reservation
         fRet = VirtualFree (pAddr, 0, MEM_RELEASE);
         if (fRet && (PHYS_MEM_ADDR  == dwData)) {
            // Physical memory is released and is available again
            g_fPhysMemUsed = TRUE;
         }
         break;
      default:
      // This should never happen
         DEBUGCHK (0);
         break;
      }
   return fRet;
}
//
// To create a heap with the custom allocator/de-allocator
int MyFunc ()
{
   HANDLE hHeap = CeHeapCreate (0, 0, 0, MyAllocMem, MyFreeMem);
   LPVOID p;
   if (hHeap) {
      // Heap creation failed
      // ErrorHandling ();
      return 0;
   }
   // Ordinary heap operation can be performed on the heap
   p = HeapAlloc (hHeap, 0, 100);  
   HeapFree (hHeap, 0, p);
   //...
   // Finish using the heap, destroy it
   HeapDestroy (hHeap);
    return 0;
}

Requirements

Header

winbase.h

Library

coredll.lib

See Also

Reference

Memory Management Functions
GetSystemInfo
HeapAlloc
HeapReAlloc
VirtualAlloc
VirtualCopy
VirtualFree

Other Resources

PFN_AllocHeapMem
PFN_FreeHeapMem